Repackaging isochrones from MIST#

The purpose of this notebook is to keep track of how we generate the file containing the isochrone data.

The source of the data is: https://waps.cfa.harvard.edu/MIST/

Download the synthetic CMDs for SDSS (both v/vcrit = 0 and 0.4) from the “Packaged Model Grids” tab, and decompress using the following lines:

wget https://waps.cfa.harvard.edu/MIST/data/tarballs_v1.2/MIST_v1.2_vvcrit0.0_SDSSugriz.txz

wget https://waps.cfa.harvard.edu/MIST/data/tarballs_v1.2/MIST_v1.2_vvcrit0.4_SDSSugriz.txz

tar xvf MIST_v1.2_vvcrit0.0_SDSSugriz.txz

tar xvf MIST_v1.2_vvcrit0.4_SDSSugriz.txz

To read these files, a module is provided, see https://waps.cfa.harvard.edu/MIST/resources.html .

Alternate link to this module: jieunchoi/MIST_codes

Note one difficulty: the number of rows (i.e., initial masses) differs for each age, making it not that trivial to store the whole data into a multidimensional array. We therfore opt for the list structure detailed below.

import read_mist_models
import pathlib
import numpy as np
import astropy.table
import pickle
# metalicities fe/H (as they appear in the filenames)
fehs = np.array([-4, -3.5, -3, -2.5, -2, -1.75, -1.5, -1.25, -1, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5])
# rotation velocities (as they appear in the filenames)
vrots = np.array([0, 0.4])

# How the metalicity is written in the filename:
def feh_string(feh):
    if feh < -0.01:
        return f"m{-feh:.2f}"
    else:
        return f"p{feh:.2f}"
    
# How rotation is written in the filename:
def vrot_string(vrot):
    return f"vvcrit{vrot:.1f}"

# Filename:
def isocmd_filename(vrot, feh):
    return str(pathlib.Path(f"./MIST_v1.2_{vrot_string(vrot)}_SDSSugriz") / f"MIST_v1.2_feh_{feh_string(feh)}_afe_p0.0_{vrot_string(vrot)}_SDSSugriz.iso.cmd")

# Testing:
#print(isocmd_filename(rots[1], fehs[0]))
# Obtainign some metadata
isocmd = read_mist_models.ISOCMD(isocmd_filename(0.0, 0.0))

print( 'version: ', isocmd.version)
print( 'photometric system: ', isocmd.photo_sys)
print( 'abundances: ', isocmd.abun)
print( 'rotation: ', isocmd.rot)
print( 'ages: ', [round(x,2) for x in isocmd.ages])
print( 'number of ages: ', isocmd.num_ages)
print( 'available columns: ', isocmd.hdr_list)
print( 'Av extinction: ', isocmd.Av_extinction)

print(f"Log10 of ages in Gyr: {[float(round(x,2)) for x in isocmd.ages]}")
print(f"Available columns: {isocmd.hdr_list}")

#for feh in fehs:
#    isocmd = read_mist_models.ISOCMD(isocmd_filename(0.0))
#    print( 'number of ages: ', isocmd.num_ages)
#    print(f"Log10 of ages in Gyr: {[float(round(x,2)) for x in isocmd.ages]}")

# Ages are the same for all metallicities:
logages = np.array(isocmd.ages)

In principle, the data to draw an isochrone is a 2D table: columns are absolute magnitudes in g, r, i, and rows correspond to different stellar masses. We have such a table for each age, and for each metallicity. These table don’t have the same size, as the number of masses changes with age! We store them in a list of lists, with indices (metallicity, age).

# Assembling all the data:

columns_to_extract = ['SDSS_g', 'SDSS_r', 'SDSS_i', 'initial_mass']
corresponding_new_names = ['g', 'r', 'i', 'initial_mass']
assert len(columns_to_extract) == len(corresponding_new_names)

vrot_list = []
for vrot in vrots:
    feh_list = []
    for feh in fehs:#[:2]:
        age_list = []
        isocmd = read_mist_models.ISOCMD(isocmd_filename(vrot, feh))

        for age_index in range(isocmd.num_ages): # [0, 50, 106]
            column_list = []
            for column_to_extract in columns_to_extract:
                #print(column_to_extract)
                column_data = np.array(isocmd.isocmds[age_index][column_to_extract], dtype=np.float32)
                #print(data)
                column_list.append(column_data)
            isochrone = astropy.table.Table(column_list, names=corresponding_new_names)
            
            age_list.append(isochrone)
        feh_list.append(age_list)
    vrot_list.append(feh_list)
to_write = (vrot_list, vrots, fehs, logages)

with open('isochrones_MIST.pickle', 'wb') as f:
    pickle.dump(to_write, f, pickle.HIGHEST_PROTOCOL)
# how to read:

with open('isochrones_MIST.pickle', 'rb') as f:
    (isochrones, vrots, metallicities, logages) = pickle.load(f)

print(len(isochrones))
print(len(isochrones[0]))
print(len(isochrones[0][0]))
print(len(isochrones[0][0][0]))