Analyzing Synthetic Populations and Fiducials in Astronomy
This Python script is designed to analyze synthetic stellar populations and their fiducial lines in the context of astronomy. It involves generating synthetic populations based on specific parameters, such as metallicity, age, and binary fraction, and then measuring the goodness-of-fit between observed and synthetic fiducial lines using a Chi-squared method. The script imports modules for data manipulation (pandas), mathematical operations (NumPy, SciPy), and file management, indicating a comprehensive approach to processing astronomical data. The code includes functionalities for loading pre-computed empirical fiducials, handling bolometric correction tables, interpolating synthetic fiducial lines, and performing optimizations to minimize the difference between observed and modeled data. This script is likely part of a larger research project aimed at understanding the properties of globular clusters or stellar populations within galaxies.
from fidanka.population.synthesize import population from fidanka.fiducial.fiducial import fiducial_line from fidanka.isofit.fit import pfD import pickle as pkl import os import pathlib import pandas as pd from scipy.interpolate import interp1d from scipy.optimize import minimize from itertools import permutations, product import re import numpy as np from tqdm import tqdm ISOPATH = "../../../outputs.denseAlpha/" ARTSTARTEST = "/home/tboudreaux/d/Astronomy/GraduateSchool/Thesis/GCConsistency/NGC2808/ArtificialStarTests/ArtificialStarCalibratedErrorFunctions.pkl" RESPONSEFUNCTIONS = "../../../inputs/responseFunctions/" BOLTABLES = "../../../bolTables/HSTWFC3/" def obs_synth_chi2(obs, synth): oMag, oColor, oWidth = obs[:,0], obs[:,1], obs[:,2] sMag, sColor, sWidth = synth[:,0], synth[:,1], synth[:,2] # Interpolate the synthetic fiducial to the observed magnitudes sColorFunc = interp1d(sMag, sColor, kind='linear', fill_value='extrapolate', bounds_error=False) sWidthFunc = interp1d(sMag, sWidth, kind='linear', fill_value='extrapolate', bounds_error=False) sColor = sColorFunc(oMag) sWidth = sWidthFunc(oMag) oColorFunc = interp1d(oMag, oColor, kind='linear', fill_value='extrapolate', bounds_error=False) colorChi2 = np.empty(len(oMag)) colorChi2[:] = np.nan widthChi2 = np.empty(len(oMag)) for idx, (mag, sC, sW, oW) in enumerate(zip(oMag, sColor, sWidth, oWidth)): d = pfD((sC,mag), oColorFunc) nearest = minimize(d, mag, method='Nelder-Mead') if not nearest.success: print("Warning: minimization failed") else: colorChi2[idx] = d(nearest.x)**2 widthChi2[idx] = ((oW - sW)**2/sW) colorChi2 = np.sum(colorChi2) widthChi2 = np.sum(widthChi2) return (colorChi2 + widthChi2)/(2*len(oMag)) def build_and_measure_population(mu, E, fb, artStar, targetAge, iso, alpha, bolTables, n=10000): pop = population( iso, alpha, fb, lambda x: x-x + targetAge, n, targetAge, targetAge, 0.25, 2, artStar, 10**((mu+5)/5), E, "F606W", bolTables ) df = pop.to_pandas() fid = fiducial_line( df["F606W"], df["F814W"], df["F606W_err"], df["F814W_err"], mcruns=1, percHigh=97, percLow=4, method='spline' ) # only retain mag bin, color loc, and width return df, fid[:,(0,1,4)] if __name__ == "__main__": assert 'HUGSFiducials.pkl' in os.listdir('.'), "Cannot find pre computed empirical fiducials" with open(ARTSTARTEST, 'rb') as f: artStar = pkl.load(f) with open('./HUGSFiducials.pkl', 'rb') as f: hugFids = pkl.load(f) bolTables = list(filter(lambda x: re.match(r'feh[mp]\d{3}\.HST_WFC3', x), os.listdir(BOLTABLES))) bolTablePaths = [os.path.join(BOLTABLES, x) for x in bolTables] isos = list() isoGlob = pathlib.Path(ISOPATH).rglob("isochrones.txt") for idx, iso in tqdm(enumerate(isoGlob), desc="Scanning for bolometrically corrected isochrones"): isos.append(str(iso)) AIsos = list(filter(lambda x: 'PopA' in x, isos)) EIsos = list(filter(lambda x: 'PopE' in x, isos)) uCombs = list(product(AIsos, EIsos)) uCombsValid = filter(lambda x: float(re.search('Pop[AE]\+(\d+\.\d+)', x[0]).groups()[0]) < float(re.search('Pop[AE]\+(\d+\.\d+)', x[1]).groups()[0]), uCombs) uCombsValid = filter(lambda x: re.search('alpha-(\d+\.\d+)', x[0]).groups()[0] == re.search('alpha-(\d+\.\d+)', x[1]).groups()[0], uCombsValid) mu = 14.89 E = 0.17 fb = 0.02 targetAge = 12.5e9 for idx, isoComb in enumerate(uCombsValid): # if idx < 200: # continue print(f"Working on {idx} with {isoComb[0]}") print(artStar.keys()) moveOn = False while not moveOn: synthPopFiducial = build_and_measure_population(mu, E, fb, artStar.copy(), targetAge, list(isoComb), -0.84, bolTablePaths) if len(synthPopFiducial[1][:,0]) == 0: print("Warning: synthetic fiducial failure, retrying") else: moveOn = True chi2 = obs_synth_chi2(hugFids, synthPopFiducial[1]) print(chi2) with open(f"DumpTestResults_{idx}.pkl", "wb") as f: pkl.dump(synthPopFiducial, f) if idx == 0: exit()