Padova Demo

Padova provides pythonic access to Padova group's stellar isochrone web app, CMD. This notebook will briefly show you what Padova can do. First, some setup for this notebook:

In [1]:
%matplotlib inline
%config InlineBackend.figure_format='retina'
import numpy as np
In [2]:
%%bash
pip install -U palettable
Requirement already up-to-date: palettable in /Users/jsick/.virtualenvs/starfish/lib/python2.7/site-packages
Cleaning up...

Intro

Padova provides three classes tailored to the types of isochrone queries you want to make.

  • IsochroneRequest will query for a single isochrone
  • AgeGridRequest will query for a set of isochrones with a single metallicity for a grid of ages
  • MetallicityGridRequest will query for a set of isochrones with a single age, for a grid of metallicities.
In [3]:
from padova import IsochroneRequest, AgeGridRequest, MetallicityGridRequest

Single isochrone requests

To obtain a single isochrone for a speific age and metallicity we'll create a IsochroneRequest instance and pass the stellar population settings: the age as $\log (A/\mathrm{yr})$, metallicity as a fraction the composition. We also specify the photometric system, (WFC3 filters). Since WFC3 isn't supported by the latest bolometric correction library, we use the older Girardi et al 2008 specification ('odfnew').

In [4]:
r = IsochroneRequest(log_age=9, z=0.02, photsys='wfc3_wide', photsys_version='odfnew')

Now that the request has been computed and downloaded from the CMD API, we can inspect the isochrones. First, we can look at the raw result:

In [5]:
r.data[:2000]
Out[5]:
'# File generated by CMD 2.7 (http://stev.oapd.inaf.it/cmd) on Thu Apr 16 19:48:23 CEST 2015\n# PARSEC isochrones, release v1.2S\n# Basic references: Bressan et al. (2012), MNRAS, 427, 127 + Chen et al. (2014), MNRAS, 444, 2525 + Tang et al. (2014), MNRAS, 445, 4287\n# Warning: the TP-AGB phase is not included! TP-AGB tracks are in preparation by Marigo et al.\n# Photometric system: HST/WFC3 wide filters (UVIS1+IR, final throughputs)\n# BCs of Carbon stars derive from Aringer et al. (2009, A&A 503, 913)\n# O-rich circumstellar silicate dust from Bressan et al. (1998)\n# C-rich circumstellar dust ignored\n# IMF: Chabrier (2001) lognormal \n# On RGB, assumed Reimers mass loss with efficiency eta=0.20\n# Kind of output: isochrone tables\n#\tIsochrone  Z = 0.02000\tY = 0.28400\t[M/H] = 0.142\teta_R = 0.200\tAge = \t1.0000e+09 yr\n#      Z\tlog(age/yr)\tM_ini   \tM_act\tlogL/Lo\tlogTe\tlogG\tmbol    F218W1  F225W1  F275W1  F336W   F390W   F438W   F475W   F555W   F606W   F625W   F775W   F814W   F105W   F110W   F125W   F140W   F160W\tint_IMF\tstage\n\t0.020000\t9.0000\t0.09000000\t0.0900\t-3.4008\t3.3572\t5.1740\t13.272\t24.470\t23.294\t24.569\t25.766\t23.569\t21.875\t19.863\t18.862\t17.773\t17.391\t14.405\t13.875\t11.847\t11.572\t11.219\t11.132\t10.849\t1.46765435\t0\n\t0.020000\t9.0000\t0.10000000\t0.1000\t-3.2508\t3.3786\t5.1553\t12.897\t23.856\t22.714\t23.985\t24.084\t22.209\t20.644\t18.895\t18.008\t17.054\t16.697\t13.768\t13.271\t11.402\t11.149\t10.818\t10.732\t10.481\t1.57040203\t0\n\t0.020000\t9.0000\t0.10185494\t0.1019\t-3.2306\t3.3814\t5.1543\t12.846\t23.775\t22.639\t23.909\t23.859\t22.026\t20.482\t18.768\t17.888\t16.950\t16.596\t13.684\t13.192\t11.346\t11.095\t10.767\t10.680\t10.432\t1.58836877\t0\n\t0.020000\t9.0000\t0.11256193\t0.1126\t-3.0985\t3.3983\t5.1330\t12.516\t23.265\t22.162\t23.426\t22.446\t20.875\t19.467\t17.972\t17.140\t16.300\t15.961\t13.153\t12.695\t10.983\t10.747\t10.436\t10.345\t10.117\t1.68575954\t0\n\t0.020000\t9.0000\t0.11717338\t0.1172\t-3.0443\t3.4051\t5.1236\t12.381\t23.051\t21.974\t23.232\t21.909\t20.409\t19.067\t17.650\t16.829\t16.018\t15.682\t12.943\t12.499\t10.844\t10.611\t10.307\t10.211\t9.988\t1.72'

The Padova package parses this result into Astropy-compatible tables. You can access the isochrone table with isochone attribute.

In [6]:
isoc = r.isochrone
print("Isochrone of Z={0:.2f}, age={0:.3e}".format(isoc.z, isoc.age))
print("Available filters: {0}".format(" ".join(isoc.filter_names)))
print(isoc.meta)
print(isoc)
Isochrone of Z=0.02, age=2.000e-02
Available filters: F218W1 F225W1 F275W1 F336W F390W F438W F475W F555W F606W F625W F775W F814W F105W F110W F125W F140W F160W
OrderedDict([('Z', 0.02), ('Y', 0.284), ('[M/H]', 0.142), ('eta_R', 0.2), ('Age', 1000000000.0), ('header', ['File generated by CMD 2.7 (http://stev.oapd.inaf.it/cmd) on Thu Apr 16 19:48:23 CEST 2015', 'PARSEC isochrones, release v1.2S', 'Basic references: Bressan et al. (2012), MNRAS, 427, 127 + Chen et al. (2014), MNRAS, 444, 2525 + Tang et al. (2014), MNRAS, 445, 4287', 'Warning: the TP-AGB phase is not included! TP-AGB tracks are in preparation by Marigo et al.', 'Photometric system: HST/WFC3 wide filters (UVIS1+IR, final throughputs)', 'BCs of Carbon stars derive from Aringer et al. (2009, A&A 503, 913)', 'O-rich circumstellar silicate dust from Bressan et al. (1998)', 'C-rich circumstellar dust ignored', 'IMF: Chabrier (2001) lognormal', 'On RGB, assumed Reimers mass loss with efficiency eta=0.20', 'Kind of output: isochrone tables'])])
 Z   logageyr   M_ini    M_act   logLLo ... F140W  F160W   int_IMF   stage
---- -------- ---------- ------ ------- ... ------ ------ ---------- -----
0.02      9.0       0.09   0.09 -3.4008 ... 11.132 10.849 1.46765435     0
0.02      9.0        0.1    0.1 -3.2508 ... 10.732 10.481 1.57040203     0
0.02      9.0 0.10185494 0.1019 -3.2306 ...  10.68 10.432 1.58836877     0
0.02      9.0 0.11256193 0.1126 -3.0985 ... 10.345 10.117 1.68575954     0
0.02      9.0 0.11717338 0.1172 -3.0443 ... 10.211  9.988 1.72473001     0
0.02      9.0       0.12   0.12 -3.0128 ... 10.134  9.914 1.74782515     0
0.02      9.0       0.14   0.14 -2.8278 ...  9.683  9.477 1.89584959     0
0.02      9.0 0.14555061 0.1456 -2.7862 ...  9.583  9.378 1.93262291     1
0.02      9.0       0.16   0.16 -2.6836 ...  9.335  9.134  2.0211525     1
0.02      9.0 0.19606914 0.1961 -2.4891 ...  8.871  8.675 2.20443201     1
 ...      ...        ...    ...     ... ...    ...    ...        ...   ...
0.02      9.0  2.3538475 2.3538  2.6059 ... -3.615 -3.884 3.28570533     7
0.02      9.0 2.35413408 2.3541  2.6467 ... -3.729 -4.002  3.2857163     7
0.02      9.0 2.35440564 2.3544  2.6872 ... -3.842 -4.119 3.28572655     7
0.02      9.0 2.35466266 2.3547  2.7266 ... -3.952 -4.233 3.28573632     7
0.02      9.0 2.35491347 2.3549  2.7655 ...  -4.06 -4.345 3.28574586     7
0.02      9.0 2.35515571 2.3552  2.8039 ... -4.167 -4.456 3.28575492     7
0.02      9.0  2.3553679 2.3554   2.842 ... -4.273 -4.566 3.28576303     7
0.02      9.0 2.35551143 2.3555  2.8927 ... -4.415 -4.714 3.28576827     7
0.02      9.0  2.3555913 2.3556  2.9321 ... -4.526 -4.829 3.28577137     7
0.02      9.0 2.35560608 2.3556  2.9398 ... -4.548 -4.852 3.28577185     7
0.02      9.0 2.35637045 2.3564  3.3656 ...  -5.77 -6.122  3.2858007     8
Length = 207 rows

We can plot up the isochrones as if they were in a nearby galaxy:

In [7]:
from astropy.coordinates import Distance
import astropy.units as u
import matplotlib.pyplot as plt
import matplotlib as mpl

fig = plt.figure(figsize=(4, 4), dpi=300)
gs = mpl.gridspec.GridSpec(1, 1)
ax = fig.add_subplot(gs[0])

d = Distance(785 * u.kpc)
ax.plot(isoc['F475W'] - isoc['F814W'], isoc['F814W'] + d.distmod.value)
ax.set_xlim(-1, 4.)
ax.set_ylim(36., 16.)
ax.set_xlabel("F475W-F814W")
ax.set_ylabel("F814W")
fig.show()
/Users/jsick/.virtualenvs/starfish/lib/python2.7/site-packages/matplotlib/figure.py:387: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure
  "matplotlib is currently using a non-GUI backend, "

Requesting isochrones for a grid of ages

Rather than repeatedly calling the CMD server to generate isochrones over a grid, we can generate age or metallicity grids in one call. Here we'll request a set of isochrones spanning a grid of ages, for a single metallicity.

In [8]:
r2 = AgeGridRequest(z=0.02,
                    min_log_age=7., max_log_age=10.1, delta_log_age=0.1,
                    photsys='wfc3_wide', photsys_version='odfnew')
In [9]:
r2_isochrones = r2.isochrone_set
In [10]:
from palettable.cubehelix import perceptual_rainbow_16
from astropy.coordinates import Distance
import astropy.units as u
import matplotlib.pyplot as plt
import matplotlib as mpl

fig = plt.figure(figsize=(4, 4), dpi=300)
gs = mpl.gridspec.GridSpec(1, 1)
ax = fig.add_subplot(gs[0])

scalar_map = mpl.cm.ScalarMappable(norm=mpl.colors.Normalize(vmin=7., vmax=10.1),
                                   cmap=perceptual_rainbow_16.mpl_colormap)
scalar_map.set_array(np.array([isoc.age for isoc in r2_isochrones]))

d = Distance(785 * u.kpc)
for isoc in r2_isochrones:
    ax.plot(isoc['F475W'] - isoc['F814W'], isoc['F814W'] + d.distmod.value,
            c=scalar_map.to_rgba(np.log10(isoc.age)))
cb = plt.colorbar(mappable=scalar_map, cax=None, ax=ax)
cb.set_label(r"$\log(A/\mathrm{yr})$")
ax.set_xlim(-1, 4.)
ax.set_ylim(36., 16.)
ax.set_xlabel("F475W-F814W")
ax.set_ylabel("F814W")
fig.show()

Requesting isochrones for a grid of metallicities

This request behaves similarly to the age grid. Here's a complete demonstration:

In [11]:
r3 = MetallicityGridRequest(log_age=9., min_z=0.0001, max_z=0.03, delta_z=0.001,
                            photsys='wfc3_wide', photsys_version='odfnew')
r3_isochrones = r3.isochrone_set
In [12]:
from palettable.cubehelix import perceptual_rainbow_16
from astropy.coordinates import Distance
import astropy.units as u
import matplotlib.pyplot as plt
import matplotlib as mpl

fig = plt.figure(figsize=(4, 4), dpi=300)
gs = mpl.gridspec.GridSpec(1, 1)
ax = fig.add_subplot(gs[0])

scale_z = lambda z: np.log10(z / 0.019)
z_values = np.array([scale_z(isoc.z) for isoc in r3_isochrones])

scalar_map = mpl.cm.ScalarMappable(norm=mpl.colors.Normalize(vmin=z_values.min(), vmax=z_values.max()),
                                   cmap=perceptual_rainbow_16.mpl_colormap)
scalar_map.set_array(z_values)

d = Distance(785 * u.kpc)
for isoc in r3_isochrones:
    ax.plot(isoc['F475W'] - isoc['F814W'], isoc['F814W'] + d.distmod.value,
            c=scalar_map.to_rgba(scale_z(isoc.z)))
cb = plt.colorbar(mappable=scalar_map, cax=None, ax=ax)
cb.set_label(r"$\log(Z/Z_\odot)$")
ax.set_xlim(-1, 4.)
ax.set_ylim(36., 16.)
ax.set_xlabel("F475W-F814W")
ax.set_ylabel("F814W")
fig.show()

Caching

Padova caches all results from the CMD web application. This means that you can repeatedly test and run your code without hammering the CMD servers, or experiencing any lag. Each request instance has a hash generated from the complete parameter set (including defaults):

In [13]:
r.settings.__hash__()
Out[13]:
'473ded32c87d20810d5d98d7f1c71c71'

We can verify that the request we just made has been cached:

In [14]:
from padova.resultcache import PadovaCache
cache = PadovaCache()
r.settings in cache
Out[14]:
True

Note that by default the cache files are located in ~/.padova_cache.

Exporting Isochrones to StarFISH

StarFISH is a Hess diagram simulation and fitting tool by Harris and Zaritsky. Padova can export isochrones into the format expected by StarFISH.

In [15]:
isoc.export_for_starfish("here")