"""Parse actual fixed Gaia and original model tables, preserving release identities.""" from pathlib import Path import csv import io import zipfile import numpy as np def gaia_rows(path): with Path(path).open() as stream: rows = list(csv.DictReader(stream)) columns = {key: np.array([float(row[key]) if row[key] else np.nan for row in rows]) for key in rows[0] if key not in ['source_id', 'duplicated_source']} columns['source_id'] = np.array([row['source_id'] for row in rows]) columns['duplicated_source'] = np.array([row['duplicated_source'] == 'true' for row in rows]) if len(set(columns['source_id'])) != len(rows): raise ValueError('Duplicate Gaia source identity') return columns def parsec_rows(path): lines = Path(path).read_text().splitlines() header = next(line[1:].split() for line in lines if line.startswith('# Zini')) rows = np.loadtxt(io.StringIO('\n'.join(line for line in lines if not line.startswith('#')))) return {name: rows[:, index] for index, name in enumerate(header)} def mist_rows(path): text=Path(path).read_text() header=next(line[1:].split() for line in text.splitlines() if line.startswith('# EEP ')) rows=np.loadtxt(io.StringIO(text)) return {name:rows[:,index] for index,name in enumerate(header)} def native_rows(path): rows = np.genfromtxt(path, delimiter=',', names=True) return {name: rows[name] for name in rows.dtype.names} def take(columns, mask): return {name: values[mask] for name, values in columns.items()} def model_at_age(columns, log_age): result = take(columns, np.isclose(columns['logAge'], log_age, atol=1e-8, rtol=0)) if not len(result['Mini']): raise ValueError(f'No native age {log_age}') if np.any(np.diff(result['Mini']) < 0): raise ValueError('Initial mass order changed; do not silently sort evolutionary branches') return result