Tutorial: Generating type Ia supernova lightcurves based on ztf_sim output

This notebook shows how to load the output for Eric's survey simulator ztf_sim and generate SN Ia lightcurves using the SALT2 template. (Check out the other notebooks for examples how to simulate other transients.)

Note: You need to download Eric's newest sample output here. The link was also included in Eric's email, so you will likely only need to change the path below.

Furthermore you'll require the dust map from Schlegel, Finkbeiner & Davis (1998) for full functionality. It can be found here.


In [1]:
import os
home_dir = os.environ.get('HOME')

# Please enter the filename of the ztf_sim output file you would like to use. The example first determines
# your home directory and then uses a relative path (useful if working on several machines with different usernames)
survey_file = os.path.join(home_dir, 'data/ZTF/test_schedule_v6.db')

# Please enter the path to where you have placed the Schlegel, Finkbeiner & Davis (1998) dust map files
# You can also set the environment variable SFD_DIR to this path (in that case the variable below should be None)
sfd98_dir = os.path.join(home_dir, 'data/sfd98')

In [2]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

import simsurvey
import sncosmo
from astropy.cosmology import Planck15

import simsurvey_tools as sst

In [3]:
# Load the ZTF CCD corners and filters
ccds = sst.load_ztf_ccds()
sst.load_ztf_filters()

In [4]:
# Load simulated survey from file (download from ftp://ftp.astro.caltech.edu/users/ebellm/one_year_sim_incomplete.db)
# Currently DES filters are used as proxies for ZTF filters
plan = simsurvey.SurveyPlan(load_opsim=survey_file, band_dict={'g': 'ztfg', 'r': 'ztfr', 'i': 'desi'}, ccds=ccds)

mjd_range = (plan.cadence['time'].min() - 30, plan.cadence['time'].max() + 30)

In [5]:
# To review the pointing schedule, you can use this table
plan.pointings


Out[5]:
<Table length=128477>
timebandzpskynoiseRADecfieldcomment
float64str4int64float64float64float64int64unicode13
57433.16732874228ztfr301235.45825479312997.27032-24.25258all_sky
57433.167791705244ztfr301032.415561403389693.69218000000001-17.05307all_sky
57433.16825466821ztfr30831.160655475382996.84022-9.85358all_sky
57433.16874926458ztfr30768.01432553431189.369684.55459all_sky
57433.16922019285ztfr30754.615141346931185.5846311.75511all_sky
57433.169683155815ztfr30845.739329548502882.35884.55458all_sky
57433.170146118784ztfr30754.615141346931185.5846311.75511all_sky
57433.170609081746ztfr30717.256118437486388.3730918.95562nightly_plane
57433.171118378836ztfr30666.061663741040591.2468626.15612all_sky
57433.171581341805ztfr30666.061663741040591.2468626.15612nightly_plane
........................
57706.412179100786ztfg301488.667313911661377.1428669.35837all_sky
57706.412662422554ztfg301553.241249284032686.6666762.15812all_sky
57706.413125385516ztfg301444.029966600034982.0524454.95780all_sky
57706.41358834848ztfg301416.803845784154281.8535447.75744all_sky
57706.41410365161ztfg301432.952975692837580.2314140.55703nightly_plane
57706.414577398355ztfg301467.57312783621672.2538547.75743nightly_plane
57706.41505362554ztfg301463.543339976470971.1276854.95779nightly_plane
57706.41552502806ztfg301550.010568972826873.3333362.15811all_sky
57706.41602904431ztfg301578.244011156435459.9999999999999976.55856all_sky
57706.41649200727ztfg301677.488192211204359.9999999999999969.35836all_sky

TransientGenerator

The transient generator combines a model and a distribution representing the transient population, and randomly draws all parameters needed to simulate the lightcurves. For well studied transient types, e.g. SNe Ia, models and generators have been predefined for easy use.

Here the maximum redshift has been kept very low in order make the simulation short. In reality $z_{max} = 0.2$ would be more realistic.


In [6]:
tr = simsurvey.get_transient_generator((0.0, 0.05),
                                       transient='Ia',
                                       template='salt2',
                                       dec_range=(-30,90),
                                       mjd_range=(mjd_range[0],
                                                  mjd_range[1]),
                                       sfd98_dir=sfd98_dir)

SimulSurvey

Lastly, all parts are combined in a SimulSurvey object that will generate the lightcurves. (This may take about a minute or two.)


In [7]:
survey = simsurvey.SimulSurvey(generator=tr, plan=plan)
    
lcs = survey.get_lightcurves(
    #progress_bar=True, notebook=True # If you get an error because of the progress_bar, delete this line.
)


/home/ufeindt/.local/lib/python2.7/site-packages/simsurvey-0.4.0-py2.7.egg/simsurvey/simulsurvey.py:1355: RuntimeWarning: invalid value encountered in log10

In [8]:
len(lcs.lcs)


Out[8]:
350

In [9]:
lcs[0]


Out[9]:
<Table length=177>
timebandfluxfluxerrzpzpsysfieldccdcomment
float64str4float64float64int64str2int64int64unicode7
57551.445018122424ztfg2024.0255338498682436.7831200453519530ab6908all_sky
57551.47332394582ztfr2339.522439281221491.0455361817302630ab6908all_sky
57552.42489128937ztfr11281.8666337656472.8960385737453330ab6908all_sky
57552.44623390818ztfg8664.782710347088443.001702307873330ab6908all_sky
57552.46824813182ztfr11440.430928533457500.107003764208630ab6908all_sky
57552.468711094785ztfr12106.589403582266500.1126160935565430ab6908all_sky
57553.446264031285ztfg23149.665153266586459.018590902228130ab6908all_sky
57553.47789399839ztfr27503.32176647366515.25934164188530ab6908all_sky
57553.47835696135ztfr28041.069004076533515.26808228003630ab6908all_sky
57554.43032346158ztfr49400.379677909965510.359490029391330ab6908all_sky
...........................
57615.33040988668ztfr149933.5595470008898.68891524541830ab6908all_sky
57615.33087284964ztfr150887.54513318354898.687303765082230ab6908all_sky
57615.369698168826ztfg67728.49461080985812.360777764782930ab6908all_sky
57616.30697930057ztfr145096.394916992631077.18601462648830ab6908all_sky
57616.32955082128ztfr143671.875837504021073.487491231595930ab6908all_sky
57616.330013784245ztfr143906.35415143811073.486298001497530ab6908all_sky
57616.3379623132ztfg66917.957542884091003.965482394193730ab6908all_sky
57621.37368562338ztfr125138.48496631371053.627286888321430ab6908all_sky
57621.37414858634ztfr124396.512070029521053.62665683148230ab6908all_sky
57621.37807957876ztfg63959.23568376774973.82173451765930ab6908all_sky

In [ ]:

Analysing the output

The output of get_lightcurves() is a LightcurveCollection object. Lightcurves are automatically filter, so only those that would be detected in the survey are kept.

You can save a the lightcurves in a pickle file and load them again later without rerunning the simulation.


In [10]:
lcs.save('lcs_tutorial.pkl')

In [11]:
lcs = simsurvey.LightcurveCollection(load='lcs_tutorial.pkl')

You can inspect the lightcurves manually. This example should return the lightcurve with the most points with S/N > 5.


In [12]:
_ = sncosmo.plot_lc(lcs[0])


The two figures below show how early the MNe are detected and at what redshifts. The simulation input parameters of transients that were not detected are also kept, so can check completeness.


In [13]:
plt.hist(lcs.stats['p_det'], lw=2, histtype='step', range=(-20,0), bins=20)
plt.xlabel('Detection phase (observer-frame)', fontsize='x-large')
_ = plt.ylabel(r'$N_{SNe}$', fontsize='x-large')



In [14]:
plt.hist(lcs.meta_full['z'], lw=1, histtype='step', range=(0,0.05), bins=20, label='all')
plt.hist(lcs.meta['z'], lw=2, histtype='step', range=(0,0.05), bins=20, label='detected')
plt.xlabel('Redshift', fontsize='x-large')
plt.ylabel(r'$N_{SNe}$', fontsize='x-large')
plt.xlim((0, 0.05))
plt.legend()


Out[14]:
<matplotlib.legend.Legend at 0x7f7845ba0f10>

In [ ]: