In [1]:

```
from IPython.core.display import HTML
css_file = '../styles/styles.css'
HTML(open(css_file, "r").read())
```

Out[1]:

The `isochrones`

library is not a standard Python library. If you are running on the managed desktop computers or your own laptop you will have to install it. Start a terminal (linux/OS X) or start an Anaconda command prompt on the managed desktop and type `pip install git+https://github.com/timothydmorton/isochrones`

. This will install the library and its (many) dependencies.

The guide below shows how to use this library to create isochrones to plot on top of your colour-magnitude diagram for the PHY242 observing project. First we'll import the libraries we will need:

In [2]:

```
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
```

In [3]:

```
bv, v = np.loadtxt('ngc7789.txt',unpack=True)
```

In [4]:

```
fig, axis = plt.subplots(figsize=(8,6))
axis.plot(bv,v,'r.',alpha=0.1)
axis.invert_yaxis()
axis.set_xlabel('B-V')
axis.set_ylabel('V')
plt.show()
```

`isochrones`

library has a nice interface to the Dartmouth group model isochrones (Dotter et al 2008). We import them using the following Python code:

In [5]:

```
from isochrones.dartmouth import Dartmouth_Isochrone
```

In [6]:

```
iso = Dartmouth_Isochrone(bands=['B','V'])
```

`isochrone`

member. This has one mandatory argument, which is $log_{10}$ of the age in Myr. For NGC 7789 (1.7 Gyr) this is roughly 9.235.

In [7]:

```
model = iso.isochrone(9.235)
print(type(model))
```

`isochrone`

function returns a `DataFrame`

object from the `pandas`

library. We haven't time or space to go into `pandas`

except to say that many people love it for dealing with complex data tables. All we need to know is we can access the $B$ and $V$ magnitudes like so:

In [8]:

```
model_b = model.B_mag
model_v = model.V_mag
# calculate B-V for this model
model_bv = model_b - model_v
```

Alright! Let's plot this isochrone on top of our data and see how it looks!

In [9]:

```
# same plotting code as earlier
fig, axis = plt.subplots(figsize=(8,6))
axis.plot(bv,v,'r.',alpha=0.1)
axis.invert_yaxis()
axis.set_xlabel('B-V')
axis.set_ylabel('V')
# now I plot the isochrone
axis.plot(model_bv,model_v)
plt.show()
```

Wow - that looks like a lousy fit. That is because our data are in apparent, reddened magnitudes and the isochrones provide **absolute**, unreddened magnitudes.

As a first step in making our isochrone units the same as our data, let's apply the distance modulus. NGC 7789 is at roughly 2330 pc...

In [10]:

```
distance = 2300
distance_modulus = 5*np.log10(distance/10)
print ('dm = {}'.format(distance_modulus))
model_v = model_v + distance_modulus
# note: distance doesn't affect colour!
```

Let's plot again:

In [11]:

```
# same plotting code as earlier
fig, axis = plt.subplots(figsize=(8,6))
axis.plot(bv,v,'r.',alpha=0.1)
axis.invert_yaxis()
axis.set_xlabel('B-V')
axis.set_ylabel('V')
# now I plot the isochrone
axis.plot(model_bv,model_v)
plt.show()
```

In [12]:

```
ebv = 0.2
av = 3.2*ebv
model_v = model_v + av
model_bv = model_bv + ebv
# same plotting code as earlier
fig, axis = plt.subplots(figsize=(8,6))
axis.plot(bv,v,'r.',alpha=0.1)
axis.invert_yaxis()
axis.set_xlabel('B-V')
axis.set_ylabel('V')
# now I plot the isochrone
axis.plot(model_bv,model_v)
axis.set_ylim([22,10])
axis.set_xlim([0.0,2.0])
plt.show()
```

The plot above doesn't look too bad. We could certainly do better by altering the distance and reddening until the main-sequence lines up with the data.

We could do this for an isochrone of any age of course: even if the isochrone is the wrong age there'll be a value of the reddening and distance which will make the main sequence of the isochrone line up with the main sequence in the data. How then do we find the age of the cluster?

The answer is that only an isochrone of the correct age will simultaneously fit the main sequence and the location of the turn-off from the main sequence. Thus you can find the age, distance and reddening all from one colour-magnitude diagram by trying isochrones of different ages until you find an acceptable fit!

Naturally you'll have to fiddle a lot to get this right, so it makes sense to wrap the code above into a **function** that you can call which gives a model isochrone in apparent, reddened magnitudes, given an age, distance and reddening. Something like the code below:

In [13]:

```
def get_isochrone(log_age,distance,ebv):
# your code here!
raise NotImplementedException
```