In [1]:
%matplotlib inline
In [2]:
import numpy as np
import pylab as plt
from matplotlib.colors import LogNorm
from ugali import isochrone
To use the isochrone module, you must have the isochrone library installed (see instructions here). The isochrone
module provides an API to create isochrones and calculate various characteristics. The easiest way to create an isochrone is through the general factory interface shown below.
In [3]:
def plot_iso(iso):
plt.scatter(iso.mag_1-iso.mag_2,iso.mag_1+iso.distance_modulus,marker='o',c='k')
plt.gca().invert_yaxis()
plt.xlabel('%s - %s'%(iso.band_1,iso.band_2)); plt.ylabel(iso.band_1)
In [4]:
iso1 = isochrone.factory(name='Padova',
age=12, # Gyr
metallicity=0.0002, # Z
distance_modulus=17
)
print(iso1)
plot_iso(iso1)
In [5]:
# Change the two bands that the isochrone loads
iso2 = isochrone.factory(name='Padova',
age=12, # Gyr
metallicity=0.0002, # Z
distance_modulus=17,
band_1 = 'i',
band_2 = 'z'
)
print(iso2)
plot_iso(iso2)
In [6]:
# Create a Dotter isochrone
iso3 = isochrone.factory(name='Dotter',
age=12, # Gyr
metallicity=0.0002, # Z
distance_modulus=17
)
print(iso3)
plot_iso(iso3)
In [7]:
iso = isochrone.factory(name='Padova',
age=12, # Gyr
metallicity=0.0002, # Z
distance_modulus=17
)
# You can set the age, metallicity, and distance modulus
iso.age = 11
iso.distance_modulus = 20
iso.metallicity = 0.00015
print(iso)
In [8]:
# Each parameter has bounds and will throw an error if you are outside the range (useful for fitting)
try:
iso.distance_modulus = 40
except ValueError as e:
print("Error:",e)
# However, you can increase the range
iso.params['distance_modulus'].set_bounds([10,50])
iso.distance_modulus = 40
print(iso)
iso.distance_modulus = 17
In [9]:
# Updating a parameters just changes the underlying isochrone file
# Note: There is no interpolation being done
for metal in [0.00011,0.00012,0.00013]:
iso.metallicity = metal
print("Metallicity:",iso.metallicity,iso.filename)
iso.metallicity = 0.000115
print("Metallicity:",iso.metallicity,iso.filename)
In [10]:
# Draw a regular grid of points from the isochrone with associated IMF
initial_mass,mass_pdf,actual_mass,mag_1,mag_2 = iso1.sample(mass_steps=1e2)
plt.scatter(mag_1-mag_2,mag_1+iso1.distance_modulus,c=mass_pdf,marker='o',facecolor='none',vmax=0.001)
plt.colorbar()
plt.gca().invert_yaxis()
plt.xlabel('%s - %s'%(iso.band_1,iso.band_2)); plt.ylabel(iso.band_1)
plt.ylim(23,15); plt.xlim(-0.5,1.0)
Out[10]:
In [11]:
# Randomly sample stars from the isochrone pdf
# Note: `sample` returns the apparent magnitudes of stars
mag_1,mag_2 = iso1.simulate(stellar_mass=3e5)
n,bx,by,p = plt.hist2d(mag_1-mag_2,mag_2,bins=50,norm=LogNorm())
plt.colorbar(label="Number of Stars")
plt.gca().invert_yaxis()
plt.xlabel('%s - %s'%(iso.band_1,iso.band_2)); plt.ylabel(iso.band_1)
Out[11]:
In [12]:
# The isochrone is normalized using a `richness` parameter (number of stars above a given mass threshold)
richness = 1e4
# Total stellar mass above some minimum mass
print("Stellar Mass:",richness * iso.stellar_mass())
# Luminosity calculated from the isochrone file and mass pdf
print("Stellar Luminosity:",richness * iso.stellar_luminosity())
# Calculate the richness
print("Absolute Magnitude:",iso.absolute_magnitude(richness=richness))
# Calculate the absolute magnitude using the random sampling of Martin et al. 2008
print("Martin Absolute Magnitude:",iso.absolute_magnitude_martin(richness=richness))