From 0bebf200ee462594fa820f1463ad2b896a69dcc3 Mon Sep 17 00:00:00 2001 From: Robert Morgan Date: Wed, 3 Mar 2021 14:04:36 -0600 Subject: [PATCH] update docs pages --- docs/check.html | 161 +++++++-- docs/input_reader.html | 200 +++++++---- docs/timeseries.html | 738 +++++++++++++++++++++++++---------------- docs/utils.html | 62 +++- docs/visualize.html | 138 +++++++- 5 files changed, 903 insertions(+), 396 deletions(-) diff --git a/docs/check.html b/docs/check.html index 8a2a488..545ba02 100644 --- a/docs/check.html +++ b/docs/check.html @@ -53,7 +53,7 @@

Module deeplenstronomy.check

exec(f'import lenstronomy.LensModel.Profiles.{model} as {model}_lens') -from deeplenstronomy.utils import KeyPathDict +from deeplenstronomy.utils import KeyPathDict, read_cadence_file import deeplenstronomy.distributions as distributions class ConfigFileError(Exception): pass @@ -838,9 +838,12 @@

Module deeplenstronomy.check

errs.append('GEOMETRY.' + k + '.' + config_k + ' needs a valid integer index greater than zero') # Plane must have a redshift - if 'REDSHIFT' not in config_k in self.config['GEOMETRY'][k][config_k]['PARAMETERS'].keys(): - errs.append('REDSHIFT is missing from GEOMETRY.' + k + '.' + config_k) - + try: + if 'REDSHIFT' not in self.config['GEOMETRY'][k][config_k]['PARAMETERS'].keys(): + errs.append('REDSHIFT is missing from GEOMETRY.' + k + '.' + config_k) + except AttributeError: + errs.append('Incorrect format detected in ' + k + '.' + config_k) + detected_objects = [] for obj_k in self.config['GEOMETRY'][k][config_k].keys(): # check individual object properties @@ -913,15 +916,43 @@

Module deeplenstronomy.check

if "NITES" not in self.config['GEOMETRY'][k][config_k].keys(): errs.append("GEOMETRY." + k + ".TIMESERIES is missing the NITES parameter") else: - if not isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], list): - errs.append("GEOMETRY." + k + ".TIMESERIES.NITES must be a list") + if not (isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], list) or isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], str)): + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES must be a list or a filename") else: - # listed nights must be numeric - try: - nites = [int(float(x)) for x in self.config['GEOMETRY'][k][config_k]["NITES"]] - del nites - except TypeError: - errs.append("Listed NITES in GEOMETRY." + k + ".TIMESERIES.NITES must be numeric") + if isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], list): + nitelists = [self.config['GEOMETRY'][k][config_k]["NITES"]] + else: + # filename of cadence file + try: + cadence_dict = read_cadence_file(self.config['GEOMETRY'][k][config_k]["NITES"]) + + # Pointings must be incrementally sequenced + nitelists = [] + bands = set(self.config['SURVEY']['PARAMETERS']['BANDS'].strip().split(',')) + pointings = [x for x in cadence_dict.keys() if x.startswith('POINTING_')] + if len(pointings) == 0: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + " contains no POINTING entries") + for pointing in pointings: + if set(list(cadence_dict[pointing].keys())) != bands: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + pointing + " does not contain same bands as the survey") + else: + cad_length = len(cadence_dict[pointing][self.config['SURVEY']['PARAMETERS']['BANDS'].strip().split(',')[0]]) + for band in bands: + if len(cadence_dict[pointing][band]) != cad_length: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + pointing + " contains cadences of different lengths") + nitelists.append(cadence_dict[pointing][band]) + + except Exception: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + " caused an error when reading file") + nitelists = [[]] + + for nitelist in nitelists: + # listed nights must be numeric + try: + nites = [int(float(x)) for x in nitelist] + del nites + except TypeError: + errs.append("Listed NITES in GEOMETRY." + k + ".TIMESERIES.NITES must be numeric") # Check validity of PEAK argument, if passed if "PEAK" in self.config['GEOMETRY'][k][config_k].keys(): @@ -1800,9 +1831,12 @@

Classes

errs.append('GEOMETRY.' + k + '.' + config_k + ' needs a valid integer index greater than zero') # Plane must have a redshift - if 'REDSHIFT' not in config_k in self.config['GEOMETRY'][k][config_k]['PARAMETERS'].keys(): - errs.append('REDSHIFT is missing from GEOMETRY.' + k + '.' + config_k) - + try: + if 'REDSHIFT' not in self.config['GEOMETRY'][k][config_k]['PARAMETERS'].keys(): + errs.append('REDSHIFT is missing from GEOMETRY.' + k + '.' + config_k) + except AttributeError: + errs.append('Incorrect format detected in ' + k + '.' + config_k) + detected_objects = [] for obj_k in self.config['GEOMETRY'][k][config_k].keys(): # check individual object properties @@ -1875,15 +1909,43 @@

Classes

if "NITES" not in self.config['GEOMETRY'][k][config_k].keys(): errs.append("GEOMETRY." + k + ".TIMESERIES is missing the NITES parameter") else: - if not isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], list): - errs.append("GEOMETRY." + k + ".TIMESERIES.NITES must be a list") + if not (isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], list) or isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], str)): + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES must be a list or a filename") else: - # listed nights must be numeric - try: - nites = [int(float(x)) for x in self.config['GEOMETRY'][k][config_k]["NITES"]] - del nites - except TypeError: - errs.append("Listed NITES in GEOMETRY." + k + ".TIMESERIES.NITES must be numeric") + if isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], list): + nitelists = [self.config['GEOMETRY'][k][config_k]["NITES"]] + else: + # filename of cadence file + try: + cadence_dict = read_cadence_file(self.config['GEOMETRY'][k][config_k]["NITES"]) + + # Pointings must be incrementally sequenced + nitelists = [] + bands = set(self.config['SURVEY']['PARAMETERS']['BANDS'].strip().split(',')) + pointings = [x for x in cadence_dict.keys() if x.startswith('POINTING_')] + if len(pointings) == 0: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + " contains no POINTING entries") + for pointing in pointings: + if set(list(cadence_dict[pointing].keys())) != bands: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + pointing + " does not contain same bands as the survey") + else: + cad_length = len(cadence_dict[pointing][self.config['SURVEY']['PARAMETERS']['BANDS'].strip().split(',')[0]]) + for band in bands: + if len(cadence_dict[pointing][band]) != cad_length: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + pointing + " contains cadences of different lengths") + nitelists.append(cadence_dict[pointing][band]) + + except Exception: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + " caused an error when reading file") + nitelists = [[]] + + for nitelist in nitelists: + # listed nights must be numeric + try: + nites = [int(float(x)) for x in nitelist] + del nites + except TypeError: + errs.append("Listed NITES in GEOMETRY." + k + ".TIMESERIES.NITES must be numeric") # Check validity of PEAK argument, if passed if "PEAK" in self.config['GEOMETRY'][k][config_k].keys(): @@ -2372,9 +2434,12 @@

Methods

errs.append('GEOMETRY.' + k + '.' + config_k + ' needs a valid integer index greater than zero') # Plane must have a redshift - if 'REDSHIFT' not in config_k in self.config['GEOMETRY'][k][config_k]['PARAMETERS'].keys(): - errs.append('REDSHIFT is missing from GEOMETRY.' + k + '.' + config_k) - + try: + if 'REDSHIFT' not in self.config['GEOMETRY'][k][config_k]['PARAMETERS'].keys(): + errs.append('REDSHIFT is missing from GEOMETRY.' + k + '.' + config_k) + except AttributeError: + errs.append('Incorrect format detected in ' + k + '.' + config_k) + detected_objects = [] for obj_k in self.config['GEOMETRY'][k][config_k].keys(): # check individual object properties @@ -2447,15 +2512,43 @@

Methods

if "NITES" not in self.config['GEOMETRY'][k][config_k].keys(): errs.append("GEOMETRY." + k + ".TIMESERIES is missing the NITES parameter") else: - if not isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], list): - errs.append("GEOMETRY." + k + ".TIMESERIES.NITES must be a list") + if not (isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], list) or isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], str)): + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES must be a list or a filename") else: - # listed nights must be numeric - try: - nites = [int(float(x)) for x in self.config['GEOMETRY'][k][config_k]["NITES"]] - del nites - except TypeError: - errs.append("Listed NITES in GEOMETRY." + k + ".TIMESERIES.NITES must be numeric") + if isinstance(self.config['GEOMETRY'][k][config_k]["NITES"], list): + nitelists = [self.config['GEOMETRY'][k][config_k]["NITES"]] + else: + # filename of cadence file + try: + cadence_dict = read_cadence_file(self.config['GEOMETRY'][k][config_k]["NITES"]) + + # Pointings must be incrementally sequenced + nitelists = [] + bands = set(self.config['SURVEY']['PARAMETERS']['BANDS'].strip().split(',')) + pointings = [x for x in cadence_dict.keys() if x.startswith('POINTING_')] + if len(pointings) == 0: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + " contains no POINTING entries") + for pointing in pointings: + if set(list(cadence_dict[pointing].keys())) != bands: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + pointing + " does not contain same bands as the survey") + else: + cad_length = len(cadence_dict[pointing][self.config['SURVEY']['PARAMETERS']['BANDS'].strip().split(',')[0]]) + for band in bands: + if len(cadence_dict[pointing][band]) != cad_length: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + pointing + " contains cadences of different lengths") + nitelists.append(cadence_dict[pointing][band]) + + except Exception: + errs.append("GEOMETRY." + k + ".TIMESERIES.NITES." + self.config['GEOMETRY'][k][config_k]["NITES"] + " caused an error when reading file") + nitelists = [[]] + + for nitelist in nitelists: + # listed nights must be numeric + try: + nites = [int(float(x)) for x in nitelist] + del nites + except TypeError: + errs.append("Listed NITES in GEOMETRY." + k + ".TIMESERIES.NITES must be numeric") # Check validity of PEAK argument, if passed if "PEAK" in self.config['GEOMETRY'][k][config_k].keys(): diff --git a/docs/input_reader.html b/docs/input_reader.html index e4d41d1..2b58d3c 100644 --- a/docs/input_reader.html +++ b/docs/input_reader.html @@ -39,7 +39,7 @@

Module deeplenstronomy.input_reader

import numpy as np import deeplenstronomy.timeseries as timeseries -from deeplenstronomy.utils import dict_select, dict_select_choose, draw_from_user_dist, KeyPathDict +from deeplenstronomy.utils import dict_select, dict_select_choose, draw_from_user_dist, KeyPathDict, read_cadence_file import deeplenstronomy.distributions as distributions import deeplenstronomy.special as special import deeplenstronomy.surveys as surveys @@ -316,6 +316,11 @@

Module deeplenstronomy.input_reader

#Object IDs for band in bands: output_dict[band]['OBJID'] = objid + + #Pointing + pointing = random.choice(list(set(self.cadence_dict.keys()) - set(['REFERENCE_MJD']))) + for band in bands: + output_dict[band]['POINTING'] = pointing #COSMOLOGY for k, v in config_dict['COSMOLOGY_DICT'].items(): @@ -550,18 +555,22 @@

Module deeplenstronomy.input_reader

# Get flattened and filled dictionary base_output_dict = self._flatten_and_fill(config_dict, cosmo, objid) + pointing = base_output_dict[bands[0]]['POINTING'] closest_redshift_lcs = [] for obj_name, obj_string in zip(self.main_dict['GEOMETRY'][configuration]['TIMESERIES']['OBJECTS'], obj_strings): # determine closest lc in library to redshift redshift = base_output_dict[bands[0]][obj_string + '-REDSHIFT'] - lcs = eval('self.{0}_{1}_lightcurves'.format(configuration, obj_name)) + lcs = eval('self.{0}_{1}_lightcurves_{2}'.format(configuration, obj_name, pointing)) closest_redshift_lcs.append(lcs['library'][np.argmin(np.abs(redshift - lcs['redshifts']))]) - # overwrite the image sim dictionary - for orig_nite in self.main_dict['GEOMETRY'][configuration]['TIMESERIES']['NITES']: - nite = orig_nite - peakshift - output_dict = base_output_dict.copy() + # overwrite the image sim dictionary + nite_dict = self.cadence_dict[pointing] + for nite_idx in range(len(nite_dict[bands[0]])): for band in bands: + orig_nite = nite_dict[band][nite_idx] + #for orig_nite in nite_dict[band]: + nite = orig_nite - peakshift + output_dict = base_output_dict.copy() for obj_sting, closest_redshift_lc in zip(obj_strings, closest_redshift_lcs): try: @@ -602,35 +611,49 @@

Module deeplenstronomy.input_reader

Args: configuration (str): like 'CONFIGURATION_1', 'CONFIGURATION_2', etc... - nites (List[int]): a list of nites relative to explosion to get a photometric measurement + nites (List[int] or str): a list of nites relative to explosion to get a photometric measurement or the name of a cadence file objects (List[str]): a list of object names redshift_dicts (List[dict]): a list of redshift information about the objects cosmo (astropy.cosmology): An astropy.cosmology instance for distance calculations """ + # Convert nites to a cadence dict + if isinstance(nites, str): + cadence_dict = read_cadence_file(nites) + else: + cadence_dict = {'REFERENCE_MJD': 0.0, + 'POINTING_1': {b: nites for b in self.main_dict['SURVEY']['PARAMETERS']['BANDS'].split(',')}} + self.cadence_dict = cadence_dict + + # Use the reference MJD to shift all the nites to be relative to 0 + shifted_cadence_dict = {k: {b: [x - cadence_dict['REFERENCE_MJD'] for x in cadence_dict[k][b]] for b in self.main_dict['SURVEY']['PARAMETERS']['BANDS'].split(',')} for k in cadence_dict.keys() if k.startswith('POINTING_')} + # instantiate an LCGen object lc_gen = timeseries.LCGen(bands=self.main_dict['SURVEY']['PARAMETERS']['BANDS']) - for obj, redshift_dict in zip(objects, redshift_dicts): - lc_library = [] - - # get redshifts to simulate light curves at - if isinstance(redshift_dict, dict): - drawn_redshifts = [self._draw(redshift_dict['DISTRIBUTION'], bands='g') for _ in range(100)] - redshifts = np.linspace(np.min(drawn_redshifts), np.max(drawn_redshifts), 15) - else: - redshifts = np.array([redshift_dict]) + # make a library for each pointing - need to speed this up (horrible performance for non-fixed redshifts and many pointings) + for pointing, nite_dict in shifted_cadence_dict.items(): + + for obj, redshift_dict in zip(objects, redshift_dicts): + lc_library = [] + + # get redshifts to simulate light curves at + if isinstance(redshift_dict, dict): + drawn_redshifts = [self._draw(redshift_dict['DISTRIBUTION'], bands='g') for _ in range(100)] + redshifts = np.linspace(np.min(drawn_redshifts), np.max(drawn_redshifts), 15) + else: + redshifts = np.array([redshift_dict]) - # get model to simulate - model_info = self.main_dict['SPECIES'][self._species_map[obj]]['MODEL'].split('_') - if model_info[-1].lower() == 'random' or len(model_info) == 1: - for redshift in redshifts: - lc_library.append(eval('lc_gen.gen_{0}(redshift, nites, cosmo=cosmo)'.format(model_info[0]))) - else: - for redshift in redshifts: - lc_library.append(eval('lc_gen.gen_{0}(redshift, nites, sed_filename="{1}", cosmo=cosmo)'.format(model_info[0], model_info[1]))) + # get model to simulate + model_info = self.main_dict['SPECIES'][self._species_map[obj]]['MODEL'].split('_') + if model_info[-1].lower() == 'random' or len(model_info) == 1: + for redshift in redshifts: + lc_library.append(eval('lc_gen.gen_{0}(redshift, nite_dict, cosmo=cosmo)'.format(model_info[0]))) + else: + for redshift in redshifts: + lc_library.append(eval('lc_gen.gen_{0}(redshift, nite_dict, sed_filename="{1}", cosmo=cosmo)'.format(model_info[0], model_info[1]))) - setattr(self, configuration + '_' + obj + '_' + 'lightcurves', {'library': lc_library, 'redshifts': redshifts}) + setattr(self, configuration + '_' + obj + '_lightcurves_' + pointing, {'library': lc_library, 'redshifts': redshifts}) return @@ -918,6 +941,11 @@

Args

#Object IDs for band in bands: output_dict[band]['OBJID'] = objid + + #Pointing + pointing = random.choice(list(set(self.cadence_dict.keys()) - set(['REFERENCE_MJD']))) + for band in bands: + output_dict[band]['POINTING'] = pointing #COSMOLOGY for k, v in config_dict['COSMOLOGY_DICT'].items(): @@ -1152,18 +1180,22 @@

Args

# Get flattened and filled dictionary base_output_dict = self._flatten_and_fill(config_dict, cosmo, objid) + pointing = base_output_dict[bands[0]]['POINTING'] closest_redshift_lcs = [] for obj_name, obj_string in zip(self.main_dict['GEOMETRY'][configuration]['TIMESERIES']['OBJECTS'], obj_strings): # determine closest lc in library to redshift redshift = base_output_dict[bands[0]][obj_string + '-REDSHIFT'] - lcs = eval('self.{0}_{1}_lightcurves'.format(configuration, obj_name)) + lcs = eval('self.{0}_{1}_lightcurves_{2}'.format(configuration, obj_name, pointing)) closest_redshift_lcs.append(lcs['library'][np.argmin(np.abs(redshift - lcs['redshifts']))]) - # overwrite the image sim dictionary - for orig_nite in self.main_dict['GEOMETRY'][configuration]['TIMESERIES']['NITES']: - nite = orig_nite - peakshift - output_dict = base_output_dict.copy() + # overwrite the image sim dictionary + nite_dict = self.cadence_dict[pointing] + for nite_idx in range(len(nite_dict[bands[0]])): for band in bands: + orig_nite = nite_dict[band][nite_idx] + #for orig_nite in nite_dict[band]: + nite = orig_nite - peakshift + output_dict = base_output_dict.copy() for obj_sting, closest_redshift_lc in zip(obj_strings, closest_redshift_lcs): try: @@ -1204,35 +1236,49 @@

Args

Args: configuration (str): like 'CONFIGURATION_1', 'CONFIGURATION_2', etc... - nites (List[int]): a list of nites relative to explosion to get a photometric measurement + nites (List[int] or str): a list of nites relative to explosion to get a photometric measurement or the name of a cadence file objects (List[str]): a list of object names redshift_dicts (List[dict]): a list of redshift information about the objects cosmo (astropy.cosmology): An astropy.cosmology instance for distance calculations """ + # Convert nites to a cadence dict + if isinstance(nites, str): + cadence_dict = read_cadence_file(nites) + else: + cadence_dict = {'REFERENCE_MJD': 0.0, + 'POINTING_1': {b: nites for b in self.main_dict['SURVEY']['PARAMETERS']['BANDS'].split(',')}} + self.cadence_dict = cadence_dict + + # Use the reference MJD to shift all the nites to be relative to 0 + shifted_cadence_dict = {k: {b: [x - cadence_dict['REFERENCE_MJD'] for x in cadence_dict[k][b]] for b in self.main_dict['SURVEY']['PARAMETERS']['BANDS'].split(',')} for k in cadence_dict.keys() if k.startswith('POINTING_')} + # instantiate an LCGen object lc_gen = timeseries.LCGen(bands=self.main_dict['SURVEY']['PARAMETERS']['BANDS']) - for obj, redshift_dict in zip(objects, redshift_dicts): - lc_library = [] - - # get redshifts to simulate light curves at - if isinstance(redshift_dict, dict): - drawn_redshifts = [self._draw(redshift_dict['DISTRIBUTION'], bands='g') for _ in range(100)] - redshifts = np.linspace(np.min(drawn_redshifts), np.max(drawn_redshifts), 15) - else: - redshifts = np.array([redshift_dict]) + # make a library for each pointing - need to speed this up (horrible performance for non-fixed redshifts and many pointings) + for pointing, nite_dict in shifted_cadence_dict.items(): + + for obj, redshift_dict in zip(objects, redshift_dicts): + lc_library = [] + + # get redshifts to simulate light curves at + if isinstance(redshift_dict, dict): + drawn_redshifts = [self._draw(redshift_dict['DISTRIBUTION'], bands='g') for _ in range(100)] + redshifts = np.linspace(np.min(drawn_redshifts), np.max(drawn_redshifts), 15) + else: + redshifts = np.array([redshift_dict]) - # get model to simulate - model_info = self.main_dict['SPECIES'][self._species_map[obj]]['MODEL'].split('_') - if model_info[-1].lower() == 'random' or len(model_info) == 1: - for redshift in redshifts: - lc_library.append(eval('lc_gen.gen_{0}(redshift, nites, cosmo=cosmo)'.format(model_info[0]))) - else: - for redshift in redshifts: - lc_library.append(eval('lc_gen.gen_{0}(redshift, nites, sed_filename="{1}", cosmo=cosmo)'.format(model_info[0], model_info[1]))) + # get model to simulate + model_info = self.main_dict['SPECIES'][self._species_map[obj]]['MODEL'].split('_') + if model_info[-1].lower() == 'random' or len(model_info) == 1: + for redshift in redshifts: + lc_library.append(eval('lc_gen.gen_{0}(redshift, nite_dict, cosmo=cosmo)'.format(model_info[0]))) + else: + for redshift in redshifts: + lc_library.append(eval('lc_gen.gen_{0}(redshift, nite_dict, sed_filename="{1}", cosmo=cosmo)'.format(model_info[0], model_info[1]))) - setattr(self, configuration + '_' + obj + '_' + 'lightcurves', {'library': lc_library, 'redshifts': redshifts}) + setattr(self, configuration + '_' + obj + '_lightcurves_' + pointing, {'library': lc_library, 'redshifts': redshifts}) return @@ -1548,8 +1594,8 @@

Args

configuration : str
like 'CONFIGURATION_1', 'CONFIGURATION_2', etc…
-
nites : List[int]
-
a list of nites relative to explosion to get a photometric measurement +
nites : List[int] or str
+
a list of nites relative to explosion to get a photometric measurement or the name of a cadence file
objects : List[str]
a list of object names @@ -1569,35 +1615,49 @@

Args

Args: configuration (str): like 'CONFIGURATION_1', 'CONFIGURATION_2', etc... - nites (List[int]): a list of nites relative to explosion to get a photometric measurement + nites (List[int] or str): a list of nites relative to explosion to get a photometric measurement or the name of a cadence file objects (List[str]): a list of object names redshift_dicts (List[dict]): a list of redshift information about the objects cosmo (astropy.cosmology): An astropy.cosmology instance for distance calculations """ + # Convert nites to a cadence dict + if isinstance(nites, str): + cadence_dict = read_cadence_file(nites) + else: + cadence_dict = {'REFERENCE_MJD': 0.0, + 'POINTING_1': {b: nites for b in self.main_dict['SURVEY']['PARAMETERS']['BANDS'].split(',')}} + self.cadence_dict = cadence_dict + + # Use the reference MJD to shift all the nites to be relative to 0 + shifted_cadence_dict = {k: {b: [x - cadence_dict['REFERENCE_MJD'] for x in cadence_dict[k][b]] for b in self.main_dict['SURVEY']['PARAMETERS']['BANDS'].split(',')} for k in cadence_dict.keys() if k.startswith('POINTING_')} + # instantiate an LCGen object lc_gen = timeseries.LCGen(bands=self.main_dict['SURVEY']['PARAMETERS']['BANDS']) - for obj, redshift_dict in zip(objects, redshift_dicts): - lc_library = [] - - # get redshifts to simulate light curves at - if isinstance(redshift_dict, dict): - drawn_redshifts = [self._draw(redshift_dict['DISTRIBUTION'], bands='g') for _ in range(100)] - redshifts = np.linspace(np.min(drawn_redshifts), np.max(drawn_redshifts), 15) - else: - redshifts = np.array([redshift_dict]) + # make a library for each pointing - need to speed this up (horrible performance for non-fixed redshifts and many pointings) + for pointing, nite_dict in shifted_cadence_dict.items(): + + for obj, redshift_dict in zip(objects, redshift_dicts): + lc_library = [] + + # get redshifts to simulate light curves at + if isinstance(redshift_dict, dict): + drawn_redshifts = [self._draw(redshift_dict['DISTRIBUTION'], bands='g') for _ in range(100)] + redshifts = np.linspace(np.min(drawn_redshifts), np.max(drawn_redshifts), 15) + else: + redshifts = np.array([redshift_dict]) - # get model to simulate - model_info = self.main_dict['SPECIES'][self._species_map[obj]]['MODEL'].split('_') - if model_info[-1].lower() == 'random' or len(model_info) == 1: - for redshift in redshifts: - lc_library.append(eval('lc_gen.gen_{0}(redshift, nites, cosmo=cosmo)'.format(model_info[0]))) - else: - for redshift in redshifts: - lc_library.append(eval('lc_gen.gen_{0}(redshift, nites, sed_filename="{1}", cosmo=cosmo)'.format(model_info[0], model_info[1]))) + # get model to simulate + model_info = self.main_dict['SPECIES'][self._species_map[obj]]['MODEL'].split('_') + if model_info[-1].lower() == 'random' or len(model_info) == 1: + for redshift in redshifts: + lc_library.append(eval('lc_gen.gen_{0}(redshift, nite_dict, cosmo=cosmo)'.format(model_info[0]))) + else: + for redshift in redshifts: + lc_library.append(eval('lc_gen.gen_{0}(redshift, nite_dict, sed_filename="{1}", cosmo=cosmo)'.format(model_info[0], model_info[1]))) - setattr(self, configuration + '_' + obj + '_' + 'lightcurves', {'library': lc_library, 'redshifts': redshifts}) + setattr(self, configuration + '_' + obj + '_lightcurves_' + pointing, {'library': lc_library, 'redshifts': redshifts}) return diff --git a/docs/timeseries.html b/docs/timeseries.html index 1a1bebd..2a5f66e 100644 --- a/docs/timeseries.html +++ b/docs/timeseries.html @@ -65,10 +65,21 @@

Module deeplenstronomy.timeseries

self.bands = bands.split(',') # Interpolate the transmission curves + self.norm_dict = {} for band in self.bands: transmission_frequency, transmission_wavelength = self.__read_passband(band) setattr(self, '{0}_transmission_frequency'.format(band), transmission_frequency) setattr(self, '{0}_transmission_wavelength'.format(band), transmission_wavelength) + + # Store normalizations + lower_bound = eval('self._{0}_obs_frame_freq_min'.format(band)) + upper_bound = eval('self._{0}_obs_frame_freq_max'.format(band)) + frequency_arr = np.linspace(upper_bound, lower_bound, 10000) + norm_arr = np.ones(len(frequency_arr)) * 3631.0 + + norm_sed = pd.DataFrame(data=np.vstack((norm_arr, frequency_arr)).T, + columns=['FLUX', 'FREQUENCY_REST']) + self.norm_dict[band] = self._integrate_through_band(norm_sed, band, 0.0, frame='REST') return @@ -122,8 +133,8 @@

Module deeplenstronomy.timeseries

setattr(self, '_{0}_obs_frame_freq_max'.format(band), 2.99792458e18 / np.min(passband['WAVELENGTH'].values)) # Add boundary terms to cover the whole range - passband.loc[passband.shape[0]] = (1.e-1, 0.0) - passband.loc[passband.shape[0]] = (4.e+4, 0.0) + passband.loc[passband.shape[0]] = (1.e-9, 0.0) + passband.loc[passband.shape[0]] = (4.e+9, 0.0) # Convert to frequency using speed of light in angstroms passband['FREQUENCY'] = 2.99792458e18 / passband['WAVELENGTH'].values @@ -147,17 +158,26 @@

Module deeplenstronomy.timeseries

sed = pd.read_csv(sed_filename, names=['NITE', 'WAVELENGTH_REST', 'FLUX'], delim_whitespace=True, comment='#') + + # Remove unrealistic wavelengths + sed = sed[sed['WAVELENGTH_REST'].values > 10.0].copy().reset_index(drop=True) + + # Add new boundaries + boundary_data = [] for nite in np.unique(sed['NITE'].values): - sed.loc[sed.shape[0]] = (nite, 10.0, 0.0) - sed.loc[sed.shape[0]] = (nite, 25000.0, 0.0) + boundary_data.append((nite, 10.0, 0.0)) + boundary_data.append((nite, 25000.0, 0.0)) + sed = sed.append(pd.DataFrame(data=boundary_data, columns=['NITE', 'WAVELENGTH_REST', 'FLUX'])) + + # Convert to frequency sed['FREQUENCY_REST'] = 2.99792458e18 / sed['WAVELENGTH_REST'].values - + # Normalize func = interp1d(sed['WAVELENGTH_REST'].values, sed['FLUX'].values) sed['FLUX'] = sed['FLUX'].values / quad(func, 10.0, 25000.0)[0] # Round nights to nearest int - sed['NITE'] = [round(x) for x in sed['NITE'].values] + sed['NITE'] = sed['NITE'].values.round() return sed @@ -173,6 +193,20 @@

Module deeplenstronomy.timeseries

return -2.5 * np.log10((1.0 + redshift) * (self._integrate_through_band(sed, band, redshift, frame='OBS') / self._integrate_through_band(sed, band, redshift, frame='REST'))) + + def _get_kcorrections(self, sed, sed_filename, redshift): + """ + Cache the k-correction factors and return + """ + attr_name = sed_filename.split('.')[0] + '-kcorrect_dict-' + str(redshift*100).split('.')[0] + if hasattr(self, attr_name): + return [getattr(self, attr_name)[b] for b in self.bands] + else: + peak_sed = sed[sed['NITE'].values == self._get_closest_nite(np.unique(sed['NITE'].values), 0)].copy().reset_index(drop=True) + k_corrections = [self._get_kcorrect(peak_sed, band, redshift) for band in self.bands] + setattr(self, attr_name, {b: k for b, k in zip(self.bands, k_corrections)}) + return k_corrections + def _get_distance_modulus(self, redshift, cosmo): """ @@ -194,19 +228,12 @@

Module deeplenstronomy.timeseries

:param redshift: the redshift of the source :param frame: chose from ['REST', 'OBS'] to choose the rest frame or the observer frame :return: flux: the measured flux from the source through the filter - """ - # Tighten bounds for accurate integration - lower_bound = eval('self._{0}_obs_frame_freq_min'.format(band)) - upper_bound = eval('self._{0}_obs_frame_freq_max'.format(band)) - frequency_arr = np.linspace(lower_bound, upper_bound, 100000) - - # Make an interpolated version of the integrand - interpolated_sed = interp1d(sed['FREQUENCY_{0}'.format(frame)].values, sed['FLUX'].values, fill_value=0.0) - integrand = eval('self.{0}_transmission_frequency(frequency_arr) * interpolated_sed(frequency_arr) / frequency_arr'.format(band)) - interpolated_integrand = interp1d(frequency_arr, integrand, fill_value=0.0) - - # Integrate and return - return quad(interpolated_integrand, lower_bound, upper_bound, limit=500)[0] + """ + frequency_arr = sed['FREQUENCY_{0}'.format(frame)].values + delta_frequencies = np.diff(frequency_arr) * -1.0 + integrand = eval("self.{0}_transmission_frequency(frequency_arr) * sed['FLUX'].values / frequency_arr".format(band)) + average_integrands = 0.5 * np.diff(integrand) + integrand[0:-1] + return np.sum(delta_frequencies * average_integrands) def _get_closest_nite(self, unique_nites, nite): """ @@ -216,15 +243,21 @@

Module deeplenstronomy.timeseries

:param nite: the nite you wish to find the closest neighbor for :return: closest_nite: the closest nite in the sed to the given nite """ - return unique_nites[np.argmin(np.abs(nite - unique_nites))] + + ## If nite not in the sed, (but within range) set nite to the closest nite in the sed + ## If nite is outside range, keep the same + if nite > unique_nites.max() or nite < unique_nites.min(): + return nite + else: + return unique_nites[np.argmin(np.abs(nite - unique_nites))] - def gen_variable(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_variable(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a random variable light curve Args: redshift (float): ignored - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed_filename (str): ignored cosmo (astropy.cosmology): ignored @@ -238,22 +271,22 @@

Module deeplenstronomy.timeseries

output_data = [] central_mag = random.uniform(12.0, 23.0) colors = {band: mag for band, mag in zip(self.bands, np.random.uniform(low=-2.0, high=2.0, size=len(self.bands)))} - for nite in nites: - central_mag = random.uniform(central_mag - 1.0, central_mag + 1.0) - for band in self.bands: + for band in self.bands: + for nite in nite_dict[band]: + central_mag = random.uniform(central_mag - 1.0, central_mag + 1.0) output_data.append([nite, band, central_mag + colors[band]]) return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols), 'obj_type': 'Variable', 'sed': 'Variable'} - def gen_flat(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_flat(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a random flat light curve. Args: redshift (float): ignored - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed_filename (str): ignored cosmo (astropy.cosmology): ignored @@ -267,35 +300,36 @@

Module deeplenstronomy.timeseries

central_mag = random.uniform(12.0, 23.0) mags = {band: mag for band, mag in zip(self.bands, central_mag + np.random.uniform(low=-2.0, high=2.0, size=len(self.bands)))} output_data = [] - for nite in nites: - for band in self.bands: + for band in self.bands: + for nite in nite_dict[band]: output_data.append([nite, band, mags[band]]) return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols), 'obj_type': 'Flat', 'sed': 'Flat'} - def gen_static(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_static(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Make a static source capable of having time-series data by introducing a mag=99 source on each NITE of the simulation. Args: redshift (float): ignored - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed_filename (str): ignored cosmo (astropy.cosmology): ignored Returns: lc_dict: a dictionary with keys ['lc, 'obj_type', 'sed'] - 'lc' contains a dataframe of the light from the object - 'obj_type' contains a string for the type of object. Will always be 'Static' here - - 'sed' contains the filename of the sed used. Will always be 'Flat' here """ + - 'sed' contains the filename of the sed used. Will always be 'Flat' here + """ output_data_cols = ['NITE', 'BAND', 'MAG'] central_mag = 99.0 mags = {band: central_mag for band in self.bands} output_data = [] - for nite in nites: - for band in self.bands: + for band in self.bands: + for nite in nite_dict[band]: output_data.append([nite, band, mags[band]]) return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols), @@ -304,13 +338,13 @@

Module deeplenstronomy.timeseries

- def gen_variablenoise(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_variablenoise(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a variable light curve with small random noise Args: redshift (float): ignored - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed_filename (str): ignored cosmo (astropy.cosmology): ignored @@ -320,7 +354,7 @@

Module deeplenstronomy.timeseries

- 'obj_type' contains a string for the type of object. Will always be 'VariableNoise' here - 'sed' contains the filename of the sed used. Will always be 'VariableNoise' here """ - noiseless_lc_dict = self.gen_variable(redshift, nites) + noiseless_lc_dict = self.gen_variable(redshift, nite_dict) noise = np.random.normal(loc=0, scale=0.25, size=noiseless_lc_dict['lc'].shape[0]) noiseless_lc_dict['lc']['MAG'] = noiseless_lc_dict['lc']['MAG'].values + noise noiseless_lc_dict['obj_type'] = 'VariableNoise' @@ -328,13 +362,13 @@

Module deeplenstronomy.timeseries

return noiseless_lc_dict - def gen_flatnoise(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_flatnoise(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a flat light curve will small random noise Args: redshift (float): ignored - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed_filename (str): ignored cosmo (astropy.cosmology): ignored @@ -344,20 +378,20 @@

Module deeplenstronomy.timeseries

- 'obj_type' contains a string for the type of object. Will always be 'FlatNoise' here - 'sed' contains the filename of the sed used. Will always be 'FlatNoise' here """ - noiseless_lc_dict = self.gen_flat(redshift, nites) + noiseless_lc_dict = self.gen_flat(redshift, nite_dict) noise = np.random.normal(loc=0, scale=0.25, size=noiseless_lc_dict['lc'].shape[0]) noiseless_lc_dict['lc']['MAG'] = noiseless_lc_dict['lc']['MAG'].values + noise noiseless_lc_dict['obj_type'] = 'FlatNoise' noiseless_lc_dict['sed'] = 'FlatNoise' return noiseless_lc_dict - def gen_user(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_user(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a light curve from a user-specidied SED Args: redshift (float): the redshift of the source - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN sed_filename (str): filename containing the time-series sed you want to use cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations @@ -368,18 +402,28 @@

Module deeplenstronomy.timeseries

- 'obj_type' contains a string for the type of object. Will always be <sed_filename> here - 'sed' contains the filename of the sed used """ - if not sed: - sed = self._read_sed('seds/user/' + sed_filename) + if sed is None: + if sed_filename.startswith('seds/user/'): + attr_name = sed_filename.split('.')[0] + else: + attr_name = 'seds/user/' + sed_filename.split('.')[0] + sed_filename = 'seds/user/' + sed_filename + + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: + sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) - return self.gen_lc_from_sed(redshift, nites, sed, sed_filename, sed_filename, cosmo=cosmo) + return self.gen_lc_from_sed(redshift, nite_dict, sed, sed_filename, sed_filename, cosmo=cosmo) - def gen_kn(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_kn(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a GW170817-like light curve. Args: redshift (float): the redshift of the source - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN sed_filename (str): filename containing the time-series sed you want to use cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations @@ -392,19 +436,23 @@

Module deeplenstronomy.timeseries

""" sed_filename = 'seds/kn/kn.SED' - if not sed: - sed = self._read_sed(sed_filename) - - return self.gen_lc_from_sed(redshift, nites, sed, 'KN', sed_filename, cosmo=cosmo) + if sed is None: + attr_name = sed_filename.split('.')[0] + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: + sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) + + return self.gen_lc_from_sed(redshift, nite_dict, sed, 'KN', sed_filename, cosmo=cosmo) - def gen_ia(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_ia(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a SN-Ia light curve. - Args: redshift (float): the redshift of the source - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN sed_filename (str): filename containing the time-series sed you want to use cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations @@ -417,23 +465,32 @@

Module deeplenstronomy.timeseries

""" # Read rest-frame sed if not supplied as argument - if not sed: - if sed_filename: - sed = self._read_sed('seds/ia/' + sed_filename) - else: + if sed is None: + if sed_filename is None: sed_filename = random.choice(self.ia_sed_files) + + if sed_filename.startswith('seds/ia/'): + attr_name = sed_filename.split('.')[0] + else: + attr_name = 'seds/ia/' + sed_filename.split('.')[0] + sed_filename = 'seds/ia/' + sed_filename + + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) # Trigger the lc generation function on this sed - return self.gen_lc_from_sed(redshift, nites, sed, 'Ia', sed_filename, cosmo=cosmo) + return self.gen_lc_from_sed(redshift, nite_dict, sed, 'Ia', sed_filename, cosmo=cosmo) - def gen_cc(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_cc(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a SN-CC light curve Args: redshift (float): the redshift of the source - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN sed_filename (str): filename containing the time-series sed you want to use cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations @@ -446,26 +503,35 @@

Module deeplenstronomy.timeseries

""" # If sed not specified, choose sed based on weight map - if not sed: - if sed_filename: - sed = self._read_sed('seds/cc/' + sed_filename) - else: + if sed is None: + if sed_filename is None: sed_filename = random.choices(self.cc_sed_files, weights=self.cc_weights, k=1)[0] + + if sed_filename.startswith('seds/cc/'): + attr_name = sed_filename.split('.')[0] + else: + attr_name = 'seds/cc/' + sed_filename.split('.')[0] + sed_filename = 'seds/cc/' + sed_filename + + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) # Get the type of SN-CC obj_type = self.cc_info_df['SNTYPE'].values[self.cc_info_df['SED'].values == sed_filename.split('/')[-1].split('.')[0]][0] # Trigger the lc generation function on this sed - return self.gen_lc_from_sed(redshift, nites, sed, obj_type, sed_filename, cosmo=cosmo) + return self.gen_lc_from_sed(redshift, nite_dict, sed, obj_type, sed_filename, cosmo=cosmo) - def gen_lc_from_sed(self, redshift, nites, sed, obj_type, sed_filename, cosmo=None): + def gen_lc_from_sed(self, redshift, nite_dict, sed, obj_type, sed_filename, cosmo=None): """ Generate a light curve based on a time-series sed. Args: redshift (float): the redshift of the source - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN sed_filename (str): filename containing the time-series sed you want to use cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations @@ -477,15 +543,17 @@

Module deeplenstronomy.timeseries

- 'sed' contains the filename of the sed used """ - # If nite not in the sed, set nite to the closest nite in the sed - useable_nites = [] + # Adjust nites + nites = {} sed_nites = np.unique(sed['NITE'].values) - for nite in nites: - if nite not in sed_nites: - useable_nites.append(self._get_closest_nite(sed_nites, nite)) - else: - useable_nites.append(nite) - nites = useable_nites + for band, cad_nites in nite_dict.items(): + useable_nites = [] + for nite in cad_nites: + if nite not in sed_nites: + useable_nites.append(self._get_closest_nite(sed_nites, nite)) + else: + useable_nites.append(nite) + nites[band] = useable_nites # Redshift the sed frequencies and wavelengths sed['WAVELENGTH_OBS'] = (1.0 + redshift) * sed['WAVELENGTH_REST'].values @@ -498,35 +566,33 @@

Module deeplenstronomy.timeseries

distance_modulus = self._get_distance_modulus(redshift, cosmo=cosmo) # Calculate k-correction at peak - peak_sed = sed[sed['NITE'].values == self._get_closest_nite(np.unique(sed['NITE'].values), 0)].copy().reset_index(drop=True) - k_corrections = [self._get_kcorrect(peak_sed, band, redshift) for band in self.bands] + k_corrections = self._get_kcorrections(sed, sed_filename, redshift) # On each nite, in each band, calculate the absolute mag output_data = [] output_data_cols = ['NITE', 'BAND', 'MAG'] - for nite in nites: - nite_sed = sed[sed['NITE'].values == nite].copy().reset_index(drop=True) - - # Apply factors to calculate absolute mag - nite_sed['FLUX'] = (cosmo.luminosity_distance(redshift).value * 10 ** 6 / 10) ** 2 / (1 + redshift) * nite_sed['FLUX'].values - nite_sed['FREQUENCY_REST'] = nite_sed['FREQUENCY_REST'].values / (1. + redshift) - - # Convert to AB Magnitude system - norm_sed = nite_sed.copy() - norm_sed['FLUX'] = 3631.0 + + for band, k_correction in zip(self.bands, k_corrections): - for band, k_correction in zip(self.bands, k_corrections): + for nite in nites[band]: + nite_sed = sed[sed['NITE'].values == nite].copy().reset_index(drop=True) + + # Flux is zero if requested nite is noe in sed + if len(nite_sed) == 0: + output_data.append([nite, band, 99.0]) + continue + # Apply factors to calculate absolute mag + nite_sed['FLUX'] = (cosmo.luminosity_distance(redshift).value * 10 ** 6 / 10) ** 2 / (1 + redshift) * nite_sed['FLUX'].values + nite_sed['FREQUENCY_REST'] = nite_sed['FREQUENCY_REST'].values / (1. + redshift) + # Calculate the apparent magnitude - norm = self._integrate_through_band(norm_sed, band, redshift, frame='REST') - absolute_ab_mag = self._integrate_through_band(nite_sed, band, redshift, frame='REST') / norm + absolute_ab_mag = self._integrate_through_band(nite_sed, band, redshift, frame='REST') / self.norm_dict[band] output_data.append([nite, band, -2.5 * np.log10(absolute_ab_mag) + distance_modulus + k_correction]) - return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols).replace(np.nan, 30.0, inplace=False), + return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols).replace(np.nan, 99.0, inplace=False), 'obj_type': obj_type, - 'sed': sed_filename} - - + 'sed': sed_filename}
@@ -578,10 +644,21 @@

Args

self.bands = bands.split(',') # Interpolate the transmission curves + self.norm_dict = {} for band in self.bands: transmission_frequency, transmission_wavelength = self.__read_passband(band) setattr(self, '{0}_transmission_frequency'.format(band), transmission_frequency) setattr(self, '{0}_transmission_wavelength'.format(band), transmission_wavelength) + + # Store normalizations + lower_bound = eval('self._{0}_obs_frame_freq_min'.format(band)) + upper_bound = eval('self._{0}_obs_frame_freq_max'.format(band)) + frequency_arr = np.linspace(upper_bound, lower_bound, 10000) + norm_arr = np.ones(len(frequency_arr)) * 3631.0 + + norm_sed = pd.DataFrame(data=np.vstack((norm_arr, frequency_arr)).T, + columns=['FLUX', 'FREQUENCY_REST']) + self.norm_dict[band] = self._integrate_through_band(norm_sed, band, 0.0, frame='REST') return @@ -635,8 +712,8 @@

Args

setattr(self, '_{0}_obs_frame_freq_max'.format(band), 2.99792458e18 / np.min(passband['WAVELENGTH'].values)) # Add boundary terms to cover the whole range - passband.loc[passband.shape[0]] = (1.e-1, 0.0) - passband.loc[passband.shape[0]] = (4.e+4, 0.0) + passband.loc[passband.shape[0]] = (1.e-9, 0.0) + passband.loc[passband.shape[0]] = (4.e+9, 0.0) # Convert to frequency using speed of light in angstroms passband['FREQUENCY'] = 2.99792458e18 / passband['WAVELENGTH'].values @@ -660,17 +737,26 @@

Args

sed = pd.read_csv(sed_filename, names=['NITE', 'WAVELENGTH_REST', 'FLUX'], delim_whitespace=True, comment='#') + + # Remove unrealistic wavelengths + sed = sed[sed['WAVELENGTH_REST'].values > 10.0].copy().reset_index(drop=True) + + # Add new boundaries + boundary_data = [] for nite in np.unique(sed['NITE'].values): - sed.loc[sed.shape[0]] = (nite, 10.0, 0.0) - sed.loc[sed.shape[0]] = (nite, 25000.0, 0.0) + boundary_data.append((nite, 10.0, 0.0)) + boundary_data.append((nite, 25000.0, 0.0)) + sed = sed.append(pd.DataFrame(data=boundary_data, columns=['NITE', 'WAVELENGTH_REST', 'FLUX'])) + + # Convert to frequency sed['FREQUENCY_REST'] = 2.99792458e18 / sed['WAVELENGTH_REST'].values - + # Normalize func = interp1d(sed['WAVELENGTH_REST'].values, sed['FLUX'].values) sed['FLUX'] = sed['FLUX'].values / quad(func, 10.0, 25000.0)[0] # Round nights to nearest int - sed['NITE'] = [round(x) for x in sed['NITE'].values] + sed['NITE'] = sed['NITE'].values.round() return sed @@ -686,6 +772,20 @@

Args

return -2.5 * np.log10((1.0 + redshift) * (self._integrate_through_band(sed, band, redshift, frame='OBS') / self._integrate_through_band(sed, band, redshift, frame='REST'))) + + def _get_kcorrections(self, sed, sed_filename, redshift): + """ + Cache the k-correction factors and return + """ + attr_name = sed_filename.split('.')[0] + '-kcorrect_dict-' + str(redshift*100).split('.')[0] + if hasattr(self, attr_name): + return [getattr(self, attr_name)[b] for b in self.bands] + else: + peak_sed = sed[sed['NITE'].values == self._get_closest_nite(np.unique(sed['NITE'].values), 0)].copy().reset_index(drop=True) + k_corrections = [self._get_kcorrect(peak_sed, band, redshift) for band in self.bands] + setattr(self, attr_name, {b: k for b, k in zip(self.bands, k_corrections)}) + return k_corrections + def _get_distance_modulus(self, redshift, cosmo): """ @@ -707,19 +807,12 @@

Args

:param redshift: the redshift of the source :param frame: chose from ['REST', 'OBS'] to choose the rest frame or the observer frame :return: flux: the measured flux from the source through the filter - """ - # Tighten bounds for accurate integration - lower_bound = eval('self._{0}_obs_frame_freq_min'.format(band)) - upper_bound = eval('self._{0}_obs_frame_freq_max'.format(band)) - frequency_arr = np.linspace(lower_bound, upper_bound, 100000) - - # Make an interpolated version of the integrand - interpolated_sed = interp1d(sed['FREQUENCY_{0}'.format(frame)].values, sed['FLUX'].values, fill_value=0.0) - integrand = eval('self.{0}_transmission_frequency(frequency_arr) * interpolated_sed(frequency_arr) / frequency_arr'.format(band)) - interpolated_integrand = interp1d(frequency_arr, integrand, fill_value=0.0) - - # Integrate and return - return quad(interpolated_integrand, lower_bound, upper_bound, limit=500)[0] + """ + frequency_arr = sed['FREQUENCY_{0}'.format(frame)].values + delta_frequencies = np.diff(frequency_arr) * -1.0 + integrand = eval("self.{0}_transmission_frequency(frequency_arr) * sed['FLUX'].values / frequency_arr".format(band)) + average_integrands = 0.5 * np.diff(integrand) + integrand[0:-1] + return np.sum(delta_frequencies * average_integrands) def _get_closest_nite(self, unique_nites, nite): """ @@ -729,15 +822,21 @@

Args

:param nite: the nite you wish to find the closest neighbor for :return: closest_nite: the closest nite in the sed to the given nite """ - return unique_nites[np.argmin(np.abs(nite - unique_nites))] + + ## If nite not in the sed, (but within range) set nite to the closest nite in the sed + ## If nite is outside range, keep the same + if nite > unique_nites.max() or nite < unique_nites.min(): + return nite + else: + return unique_nites[np.argmin(np.abs(nite - unique_nites))] - def gen_variable(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_variable(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a random variable light curve Args: redshift (float): ignored - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed_filename (str): ignored cosmo (astropy.cosmology): ignored @@ -751,22 +850,22 @@

Args

output_data = [] central_mag = random.uniform(12.0, 23.0) colors = {band: mag for band, mag in zip(self.bands, np.random.uniform(low=-2.0, high=2.0, size=len(self.bands)))} - for nite in nites: - central_mag = random.uniform(central_mag - 1.0, central_mag + 1.0) - for band in self.bands: + for band in self.bands: + for nite in nite_dict[band]: + central_mag = random.uniform(central_mag - 1.0, central_mag + 1.0) output_data.append([nite, band, central_mag + colors[band]]) return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols), 'obj_type': 'Variable', 'sed': 'Variable'} - def gen_flat(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_flat(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a random flat light curve. Args: redshift (float): ignored - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed_filename (str): ignored cosmo (astropy.cosmology): ignored @@ -780,35 +879,36 @@

Args

central_mag = random.uniform(12.0, 23.0) mags = {band: mag for band, mag in zip(self.bands, central_mag + np.random.uniform(low=-2.0, high=2.0, size=len(self.bands)))} output_data = [] - for nite in nites: - for band in self.bands: + for band in self.bands: + for nite in nite_dict[band]: output_data.append([nite, band, mags[band]]) return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols), 'obj_type': 'Flat', 'sed': 'Flat'} - def gen_static(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_static(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Make a static source capable of having time-series data by introducing a mag=99 source on each NITE of the simulation. Args: redshift (float): ignored - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed_filename (str): ignored cosmo (astropy.cosmology): ignored Returns: lc_dict: a dictionary with keys ['lc, 'obj_type', 'sed'] - 'lc' contains a dataframe of the light from the object - 'obj_type' contains a string for the type of object. Will always be 'Static' here - - 'sed' contains the filename of the sed used. Will always be 'Flat' here """ + - 'sed' contains the filename of the sed used. Will always be 'Flat' here + """ output_data_cols = ['NITE', 'BAND', 'MAG'] central_mag = 99.0 mags = {band: central_mag for band in self.bands} output_data = [] - for nite in nites: - for band in self.bands: + for band in self.bands: + for nite in nite_dict[band]: output_data.append([nite, band, mags[band]]) return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols), @@ -817,13 +917,13 @@

Args

- def gen_variablenoise(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_variablenoise(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a variable light curve with small random noise Args: redshift (float): ignored - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed_filename (str): ignored cosmo (astropy.cosmology): ignored @@ -833,7 +933,7 @@

Args

- 'obj_type' contains a string for the type of object. Will always be 'VariableNoise' here - 'sed' contains the filename of the sed used. Will always be 'VariableNoise' here """ - noiseless_lc_dict = self.gen_variable(redshift, nites) + noiseless_lc_dict = self.gen_variable(redshift, nite_dict) noise = np.random.normal(loc=0, scale=0.25, size=noiseless_lc_dict['lc'].shape[0]) noiseless_lc_dict['lc']['MAG'] = noiseless_lc_dict['lc']['MAG'].values + noise noiseless_lc_dict['obj_type'] = 'VariableNoise' @@ -841,13 +941,13 @@

Args

return noiseless_lc_dict - def gen_flatnoise(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_flatnoise(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a flat light curve will small random noise Args: redshift (float): ignored - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed_filename (str): ignored cosmo (astropy.cosmology): ignored @@ -857,20 +957,20 @@

Args

- 'obj_type' contains a string for the type of object. Will always be 'FlatNoise' here - 'sed' contains the filename of the sed used. Will always be 'FlatNoise' here """ - noiseless_lc_dict = self.gen_flat(redshift, nites) + noiseless_lc_dict = self.gen_flat(redshift, nite_dict) noise = np.random.normal(loc=0, scale=0.25, size=noiseless_lc_dict['lc'].shape[0]) noiseless_lc_dict['lc']['MAG'] = noiseless_lc_dict['lc']['MAG'].values + noise noiseless_lc_dict['obj_type'] = 'FlatNoise' noiseless_lc_dict['sed'] = 'FlatNoise' return noiseless_lc_dict - def gen_user(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_user(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a light curve from a user-specidied SED Args: redshift (float): the redshift of the source - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN sed_filename (str): filename containing the time-series sed you want to use cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations @@ -881,18 +981,28 @@

Args

- 'obj_type' contains a string for the type of object. Will always be <sed_filename> here - 'sed' contains the filename of the sed used """ - if not sed: - sed = self._read_sed('seds/user/' + sed_filename) + if sed is None: + if sed_filename.startswith('seds/user/'): + attr_name = sed_filename.split('.')[0] + else: + attr_name = 'seds/user/' + sed_filename.split('.')[0] + sed_filename = 'seds/user/' + sed_filename + + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: + sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) - return self.gen_lc_from_sed(redshift, nites, sed, sed_filename, sed_filename, cosmo=cosmo) + return self.gen_lc_from_sed(redshift, nite_dict, sed, sed_filename, sed_filename, cosmo=cosmo) - def gen_kn(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_kn(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a GW170817-like light curve. Args: redshift (float): the redshift of the source - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN sed_filename (str): filename containing the time-series sed you want to use cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations @@ -905,19 +1015,23 @@

Args

""" sed_filename = 'seds/kn/kn.SED' - if not sed: - sed = self._read_sed(sed_filename) - - return self.gen_lc_from_sed(redshift, nites, sed, 'KN', sed_filename, cosmo=cosmo) + if sed is None: + attr_name = sed_filename.split('.')[0] + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: + sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) + + return self.gen_lc_from_sed(redshift, nite_dict, sed, 'KN', sed_filename, cosmo=cosmo) - def gen_ia(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_ia(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a SN-Ia light curve. - Args: redshift (float): the redshift of the source - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN sed_filename (str): filename containing the time-series sed you want to use cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations @@ -930,23 +1044,32 @@

Args

""" # Read rest-frame sed if not supplied as argument - if not sed: - if sed_filename: - sed = self._read_sed('seds/ia/' + sed_filename) - else: + if sed is None: + if sed_filename is None: sed_filename = random.choice(self.ia_sed_files) + + if sed_filename.startswith('seds/ia/'): + attr_name = sed_filename.split('.')[0] + else: + attr_name = 'seds/ia/' + sed_filename.split('.')[0] + sed_filename = 'seds/ia/' + sed_filename + + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) # Trigger the lc generation function on this sed - return self.gen_lc_from_sed(redshift, nites, sed, 'Ia', sed_filename, cosmo=cosmo) + return self.gen_lc_from_sed(redshift, nite_dict, sed, 'Ia', sed_filename, cosmo=cosmo) - def gen_cc(self, redshift, nites, sed=None, sed_filename=None, cosmo=None): + def gen_cc(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None): """ Generate a SN-CC light curve Args: redshift (float): the redshift of the source - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN sed_filename (str): filename containing the time-series sed you want to use cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations @@ -959,26 +1082,35 @@

Args

""" # If sed not specified, choose sed based on weight map - if not sed: - if sed_filename: - sed = self._read_sed('seds/cc/' + sed_filename) - else: + if sed is None: + if sed_filename is None: sed_filename = random.choices(self.cc_sed_files, weights=self.cc_weights, k=1)[0] + + if sed_filename.startswith('seds/cc/'): + attr_name = sed_filename.split('.')[0] + else: + attr_name = 'seds/cc/' + sed_filename.split('.')[0] + sed_filename = 'seds/cc/' + sed_filename + + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) # Get the type of SN-CC obj_type = self.cc_info_df['SNTYPE'].values[self.cc_info_df['SED'].values == sed_filename.split('/')[-1].split('.')[0]][0] # Trigger the lc generation function on this sed - return self.gen_lc_from_sed(redshift, nites, sed, obj_type, sed_filename, cosmo=cosmo) + return self.gen_lc_from_sed(redshift, nite_dict, sed, obj_type, sed_filename, cosmo=cosmo) - def gen_lc_from_sed(self, redshift, nites, sed, obj_type, sed_filename, cosmo=None): + def gen_lc_from_sed(self, redshift, nite_dict, sed, obj_type, sed_filename, cosmo=None): """ Generate a light curve based on a time-series sed. Args: redshift (float): the redshift of the source - nites (List[int]): a list of night relative to peak you want to obtain a magnitude for + nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN sed_filename (str): filename containing the time-series sed you want to use cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations @@ -990,15 +1122,17 @@

Args

- 'sed' contains the filename of the sed used """ - # If nite not in the sed, set nite to the closest nite in the sed - useable_nites = [] + # Adjust nites + nites = {} sed_nites = np.unique(sed['NITE'].values) - for nite in nites: - if nite not in sed_nites: - useable_nites.append(self._get_closest_nite(sed_nites, nite)) - else: - useable_nites.append(nite) - nites = useable_nites + for band, cad_nites in nite_dict.items(): + useable_nites = [] + for nite in cad_nites: + if nite not in sed_nites: + useable_nites.append(self._get_closest_nite(sed_nites, nite)) + else: + useable_nites.append(nite) + nites[band] = useable_nites # Redshift the sed frequencies and wavelengths sed['WAVELENGTH_OBS'] = (1.0 + redshift) * sed['WAVELENGTH_REST'].values @@ -1011,38 +1145,38 @@

Args

distance_modulus = self._get_distance_modulus(redshift, cosmo=cosmo) # Calculate k-correction at peak - peak_sed = sed[sed['NITE'].values == self._get_closest_nite(np.unique(sed['NITE'].values), 0)].copy().reset_index(drop=True) - k_corrections = [self._get_kcorrect(peak_sed, band, redshift) for band in self.bands] + k_corrections = self._get_kcorrections(sed, sed_filename, redshift) # On each nite, in each band, calculate the absolute mag output_data = [] output_data_cols = ['NITE', 'BAND', 'MAG'] - for nite in nites: - nite_sed = sed[sed['NITE'].values == nite].copy().reset_index(drop=True) - - # Apply factors to calculate absolute mag - nite_sed['FLUX'] = (cosmo.luminosity_distance(redshift).value * 10 ** 6 / 10) ** 2 / (1 + redshift) * nite_sed['FLUX'].values - nite_sed['FREQUENCY_REST'] = nite_sed['FREQUENCY_REST'].values / (1. + redshift) - - # Convert to AB Magnitude system - norm_sed = nite_sed.copy() - norm_sed['FLUX'] = 3631.0 + + for band, k_correction in zip(self.bands, k_corrections): - for band, k_correction in zip(self.bands, k_corrections): + for nite in nites[band]: + nite_sed = sed[sed['NITE'].values == nite].copy().reset_index(drop=True) + # Flux is zero if requested nite is noe in sed + if len(nite_sed) == 0: + output_data.append([nite, band, 99.0]) + continue + + # Apply factors to calculate absolute mag + nite_sed['FLUX'] = (cosmo.luminosity_distance(redshift).value * 10 ** 6 / 10) ** 2 / (1 + redshift) * nite_sed['FLUX'].values + nite_sed['FREQUENCY_REST'] = nite_sed['FREQUENCY_REST'].values / (1. + redshift) + # Calculate the apparent magnitude - norm = self._integrate_through_band(norm_sed, band, redshift, frame='REST') - absolute_ab_mag = self._integrate_through_band(nite_sed, band, redshift, frame='REST') / norm + absolute_ab_mag = self._integrate_through_band(nite_sed, band, redshift, frame='REST') / self.norm_dict[band] output_data.append([nite, band, -2.5 * np.log10(absolute_ab_mag) + distance_modulus + k_correction]) - return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols).replace(np.nan, 30.0, inplace=False), + return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols).replace(np.nan, 99.0, inplace=False), 'obj_type': obj_type, 'sed': sed_filename}

Methods

-def gen_cc(self, redshift, nites, sed=None, sed_filename=None, cosmo=None) +def gen_cc(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None)

Generate a SN-CC light curve

@@ -1050,8 +1184,7 @@

Args

redshift : float
the redshift of the source
-
nites : List[int]
-
a list of night relative to peak you want to obtain a magnitude for
+
nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
sed : None or pandas.DataFrame, optional, default=None
a dataframe containing the sed of the SN
sed_filename : str
@@ -1071,13 +1204,13 @@

Returns

Expand source code -
def gen_cc(self, redshift, nites, sed=None, sed_filename=None, cosmo=None):
+
def gen_cc(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None):
     """
     Generate a SN-CC light curve
     
     Args:
         redshift (float): the redshift of the source
-        nites (List[int]): a list of night relative to peak you want to obtain a magnitude for 
+        nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey 
         sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN 
         sed_filename (str): filename containing the time-series sed you want to use 
         cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations
@@ -1090,22 +1223,31 @@ 

Returns

""" # If sed not specified, choose sed based on weight map - if not sed: - if sed_filename: - sed = self._read_sed('seds/cc/' + sed_filename) - else: + if sed is None: + if sed_filename is None: sed_filename = random.choices(self.cc_sed_files, weights=self.cc_weights, k=1)[0] + + if sed_filename.startswith('seds/cc/'): + attr_name = sed_filename.split('.')[0] + else: + attr_name = 'seds/cc/' + sed_filename.split('.')[0] + sed_filename = 'seds/cc/' + sed_filename + + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) # Get the type of SN-CC obj_type = self.cc_info_df['SNTYPE'].values[self.cc_info_df['SED'].values == sed_filename.split('/')[-1].split('.')[0]][0] # Trigger the lc generation function on this sed - return self.gen_lc_from_sed(redshift, nites, sed, obj_type, sed_filename, cosmo=cosmo)
+ return self.gen_lc_from_sed(redshift, nite_dict, sed, obj_type, sed_filename, cosmo=cosmo)
-def gen_flat(self, redshift, nites, sed=None, sed_filename=None, cosmo=None) +def gen_flat(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None)

Generate a random flat light curve.

@@ -1113,8 +1255,7 @@

Args

redshift : float
ignored
-
nites : List[int]
-
a list of night relative to peak you want to obtain a magnitude for
+
nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
sed_filename : str
ignored
cosmo : astropy.cosmology
@@ -1132,13 +1273,13 @@

Returns

Expand source code -
def gen_flat(self, redshift, nites, sed=None, sed_filename=None, cosmo=None):
+
def gen_flat(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None):
     """
     Generate a random flat light curve.
     
     Args:
         redshift (float): ignored
-        nites (List[int]): a list of night relative to peak you want to obtain a magnitude for
+        nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
         sed_filename (str): ignored
         cosmo (astropy.cosmology): ignored
 
@@ -1152,8 +1293,8 @@ 

Returns

central_mag = random.uniform(12.0, 23.0) mags = {band: mag for band, mag in zip(self.bands, central_mag + np.random.uniform(low=-2.0, high=2.0, size=len(self.bands)))} output_data = [] - for nite in nites: - for band in self.bands: + for band in self.bands: + for nite in nite_dict[band]: output_data.append([nite, band, mags[band]]) return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols), @@ -1162,7 +1303,7 @@

Returns

-def gen_flatnoise(self, redshift, nites, sed=None, sed_filename=None, cosmo=None) +def gen_flatnoise(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None)

Generate a flat light curve will small random noise

@@ -1170,8 +1311,7 @@

Args

redshift : float
ignored
-
nites : List[int]
-
a list of night relative to peak you want to obtain a magnitude for
+
nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
sed_filename : str
ignored
cosmo : astropy.cosmology
@@ -1189,13 +1329,13 @@

Returns

Expand source code -
def gen_flatnoise(self, redshift, nites, sed=None, sed_filename=None, cosmo=None):
+
def gen_flatnoise(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None):
     """
     Generate a flat light curve will small random noise
 
     Args:
         redshift (float): ignored
-        nites (List[int]): a list of night relative to peak you want to obtain a magnitude for
+        nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
         sed_filename (str): ignored
         cosmo (astropy.cosmology): ignored
 
@@ -1205,7 +1345,7 @@ 

Returns

- 'obj_type' contains a string for the type of object. Will always be 'FlatNoise' here - 'sed' contains the filename of the sed used. Will always be 'FlatNoise' here """ - noiseless_lc_dict = self.gen_flat(redshift, nites) + noiseless_lc_dict = self.gen_flat(redshift, nite_dict) noise = np.random.normal(loc=0, scale=0.25, size=noiseless_lc_dict['lc'].shape[0]) noiseless_lc_dict['lc']['MAG'] = noiseless_lc_dict['lc']['MAG'].values + noise noiseless_lc_dict['obj_type'] = 'FlatNoise' @@ -1214,7 +1354,7 @@

Returns

-def gen_ia(self, redshift, nites, sed=None, sed_filename=None, cosmo=None) +def gen_ia(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None)

Generate a SN-Ia light curve.

@@ -1222,8 +1362,7 @@

Args

redshift : float
the redshift of the source
-
nites : List[int]
-
a list of night relative to peak you want to obtain a magnitude for
+
nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
sed : None or pandas.DataFrame, optional, default=None
a dataframe containing the sed of the SN
sed_filename : str
@@ -1243,14 +1382,13 @@

Returns

Expand source code -
def gen_ia(self, redshift, nites, sed=None, sed_filename=None, cosmo=None):
+
def gen_ia(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None):
     """
     Generate a SN-Ia light curve.
-    
 
     Args:
         redshift (float): the redshift of the source
-        nites (List[int]): a list of night relative to peak you want to obtain a magnitude for 
+        nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey 
         sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN 
         sed_filename (str): filename containing the time-series sed you want to use 
         cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations
@@ -1263,19 +1401,28 @@ 

Returns

""" # Read rest-frame sed if not supplied as argument - if not sed: - if sed_filename: - sed = self._read_sed('seds/ia/' + sed_filename) - else: + if sed is None: + if sed_filename is None: sed_filename = random.choice(self.ia_sed_files) + + if sed_filename.startswith('seds/ia/'): + attr_name = sed_filename.split('.')[0] + else: + attr_name = 'seds/ia/' + sed_filename.split('.')[0] + sed_filename = 'seds/ia/' + sed_filename + + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) # Trigger the lc generation function on this sed - return self.gen_lc_from_sed(redshift, nites, sed, 'Ia', sed_filename, cosmo=cosmo)
+ return self.gen_lc_from_sed(redshift, nite_dict, sed, 'Ia', sed_filename, cosmo=cosmo)
-def gen_kn(self, redshift, nites, sed=None, sed_filename=None, cosmo=None) +def gen_kn(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None)

Generate a GW170817-like light curve.

@@ -1283,8 +1430,7 @@

Args

redshift : float
the redshift of the source
-
nites : List[int]
-
a list of night relative to peak you want to obtain a magnitude for
+
nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
sed : None or pandas.DataFrame, optional, default=None
a dataframe containing the sed of the SN
sed_filename : str
@@ -1304,13 +1450,13 @@

Returns

Expand source code -
def gen_kn(self, redshift, nites, sed=None, sed_filename=None, cosmo=None):
+
def gen_kn(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None):
     """
     Generate a GW170817-like light curve.
 
     Args:
         redshift (float): the redshift of the source
-        nites (List[int]): a list of night relative to peak you want to obtain a magnitude for 
+        nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey 
         sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN 
         sed_filename (str): filename containing the time-series sed you want to use 
         cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations
@@ -1323,14 +1469,19 @@ 

Returns

""" sed_filename = 'seds/kn/kn.SED' - if not sed: - sed = self._read_sed(sed_filename) - - return self.gen_lc_from_sed(redshift, nites, sed, 'KN', sed_filename, cosmo=cosmo)
+ if sed is None: + attr_name = sed_filename.split('.')[0] + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: + sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) + + return self.gen_lc_from_sed(redshift, nite_dict, sed, 'KN', sed_filename, cosmo=cosmo)
-def gen_lc_from_sed(self, redshift, nites, sed, obj_type, sed_filename, cosmo=None) +def gen_lc_from_sed(self, redshift, nite_dict, sed, obj_type, sed_filename, cosmo=None)

Generate a light curve based on a time-series sed.

@@ -1338,8 +1489,7 @@

Args

redshift : float
the redshift of the source
-
nites : List[int]
-
a list of night relative to peak you want to obtain a magnitude for
+
nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
sed : None or pandas.DataFrame, optional, default=None
a dataframe containing the sed of the SN
sed_filename : str
@@ -1359,13 +1509,13 @@

Returns

Expand source code -
def gen_lc_from_sed(self, redshift, nites, sed, obj_type, sed_filename, cosmo=None):
+
def gen_lc_from_sed(self, redshift, nite_dict, sed, obj_type, sed_filename, cosmo=None):
     """
     Generate a light curve based on a time-series sed.
     
     Args:
         redshift (float): the redshift of the source
-        nites (List[int]): a list of night relative to peak you want to obtain a magnitude for 
+        nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey 
         sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN 
         sed_filename (str): filename containing the time-series sed you want to use 
         cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations
@@ -1377,15 +1527,17 @@ 

Returns

- 'sed' contains the filename of the sed used """ - # If nite not in the sed, set nite to the closest nite in the sed - useable_nites = [] + # Adjust nites + nites = {} sed_nites = np.unique(sed['NITE'].values) - for nite in nites: - if nite not in sed_nites: - useable_nites.append(self._get_closest_nite(sed_nites, nite)) - else: - useable_nites.append(nite) - nites = useable_nites + for band, cad_nites in nite_dict.items(): + useable_nites = [] + for nite in cad_nites: + if nite not in sed_nites: + useable_nites.append(self._get_closest_nite(sed_nites, nite)) + else: + useable_nites.append(nite) + nites[band] = useable_nites # Redshift the sed frequencies and wavelengths sed['WAVELENGTH_OBS'] = (1.0 + redshift) * sed['WAVELENGTH_REST'].values @@ -1398,37 +1550,37 @@

Returns

distance_modulus = self._get_distance_modulus(redshift, cosmo=cosmo) # Calculate k-correction at peak - peak_sed = sed[sed['NITE'].values == self._get_closest_nite(np.unique(sed['NITE'].values), 0)].copy().reset_index(drop=True) - k_corrections = [self._get_kcorrect(peak_sed, band, redshift) for band in self.bands] + k_corrections = self._get_kcorrections(sed, sed_filename, redshift) # On each nite, in each band, calculate the absolute mag output_data = [] output_data_cols = ['NITE', 'BAND', 'MAG'] - for nite in nites: - nite_sed = sed[sed['NITE'].values == nite].copy().reset_index(drop=True) - - # Apply factors to calculate absolute mag - nite_sed['FLUX'] = (cosmo.luminosity_distance(redshift).value * 10 ** 6 / 10) ** 2 / (1 + redshift) * nite_sed['FLUX'].values - nite_sed['FREQUENCY_REST'] = nite_sed['FREQUENCY_REST'].values / (1. + redshift) - - # Convert to AB Magnitude system - norm_sed = nite_sed.copy() - norm_sed['FLUX'] = 3631.0 + + for band, k_correction in zip(self.bands, k_corrections): - for band, k_correction in zip(self.bands, k_corrections): + for nite in nites[band]: + nite_sed = sed[sed['NITE'].values == nite].copy().reset_index(drop=True) + + # Flux is zero if requested nite is noe in sed + if len(nite_sed) == 0: + output_data.append([nite, band, 99.0]) + continue + # Apply factors to calculate absolute mag + nite_sed['FLUX'] = (cosmo.luminosity_distance(redshift).value * 10 ** 6 / 10) ** 2 / (1 + redshift) * nite_sed['FLUX'].values + nite_sed['FREQUENCY_REST'] = nite_sed['FREQUENCY_REST'].values / (1. + redshift) + # Calculate the apparent magnitude - norm = self._integrate_through_band(norm_sed, band, redshift, frame='REST') - absolute_ab_mag = self._integrate_through_band(nite_sed, band, redshift, frame='REST') / norm + absolute_ab_mag = self._integrate_through_band(nite_sed, band, redshift, frame='REST') / self.norm_dict[band] output_data.append([nite, band, -2.5 * np.log10(absolute_ab_mag) + distance_modulus + k_correction]) - return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols).replace(np.nan, 30.0, inplace=False), + return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols).replace(np.nan, 99.0, inplace=False), 'obj_type': obj_type, 'sed': sed_filename}
-def gen_static(self, redshift, nites, sed=None, sed_filename=None, cosmo=None) +def gen_static(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None)

Make a static source capable of having time-series data by introducing a mag=99 source @@ -1437,8 +1589,7 @@

Args

redshift : float
ignored
-
nites : List[int]
-
a list of night relative to peak you want to obtain a magnitude for
+
nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
sed_filename : str
ignored
@@ -1458,27 +1609,28 @@

Returns

Expand source code -
def gen_static(self, redshift, nites, sed=None, sed_filename=None, cosmo=None):
+
def gen_static(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None):
     """
     Make a static source capable of having time-series data by introducing a mag=99 source
     on each NITE of the simulation.
 
     Args:
         redshift (float): ignored 
-        nites (List[int]): a list of night relative to peak you want to obtain a magnitude for
+        nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
         sed_filename (str): ignored                                                                                                                                                               
         cosmo (astropy.cosmology): ignored                                                                                                                                                                                            
     Returns:
         lc_dict: a dictionary with keys ['lc, 'obj_type', 'sed']
           - 'lc' contains a dataframe of the light from the object
           - 'obj_type' contains a string for the type of object. Will always be 'Static' here
-          - 'sed' contains the filename of the sed used. Will always be 'Flat' here                                                                                                                        """
+          - 'sed' contains the filename of the sed used. Will always be 'Flat' here     
+    """
     output_data_cols = ['NITE', 'BAND', 'MAG']
     central_mag = 99.0
     mags = {band: central_mag for band in self.bands}
     output_data = []
-    for nite in nites:
-        for band in self.bands:
+    for band in self.bands:
+        for nite in nite_dict[band]:
             output_data.append([nite, band, mags[band]])
 
     return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols),
@@ -1487,7 +1639,7 @@ 

Returns

-def gen_user(self, redshift, nites, sed=None, sed_filename=None, cosmo=None) +def gen_user(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None)

Generate a light curve from a user-specidied SED

@@ -1495,8 +1647,7 @@

Args

redshift : float
the redshift of the source
-
nites : List[int]
-
a list of night relative to peak you want to obtain a magnitude for
+
nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
sed : None or pandas.DataFrame, optional, default=None
a dataframe containing the sed of the SN
sed_filename : str
@@ -1516,13 +1667,13 @@

Returns

Expand source code -
def gen_user(self, redshift, nites, sed=None, sed_filename=None, cosmo=None):
+
def gen_user(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None):
     """
     Generate a light curve from a user-specidied SED
 
     Args:
         redshift (float): the redshift of the source
-        nites (List[int]): a list of night relative to peak you want to obtain a magnitude for 
+        nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey 
         sed (None or pandas.DataFrame, optional, default=None): a dataframe containing the sed of the SN 
         sed_filename (str): filename containing the time-series sed you want to use 
         cosmo (astropy.cosmology): an astropy.cosmology instance used for distance calculations
@@ -1533,14 +1684,24 @@ 

Returns

- 'obj_type' contains a string for the type of object. Will always be <sed_filename> here - 'sed' contains the filename of the sed used """ - if not sed: - sed = self._read_sed('seds/user/' + sed_filename) + if sed is None: + if sed_filename.startswith('seds/user/'): + attr_name = sed_filename.split('.')[0] + else: + attr_name = 'seds/user/' + sed_filename.split('.')[0] + sed_filename = 'seds/user/' + sed_filename + + if hasattr(self, attr_name): + sed = getattr(self, attr_name) + else: + sed = self._read_sed(sed_filename) + setattr(self, attr_name, sed) - return self.gen_lc_from_sed(redshift, nites, sed, sed_filename, sed_filename, cosmo=cosmo)
+ return self.gen_lc_from_sed(redshift, nite_dict, sed, sed_filename, sed_filename, cosmo=cosmo)
-def gen_variable(self, redshift, nites, sed=None, sed_filename=None, cosmo=None) +def gen_variable(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None)

Generate a random variable light curve

@@ -1548,9 +1709,7 @@

Args

redshift : float
ignored
-
nites : List[int]
-
a list of night relative to peak you want to obtain a magnitude for -
+
nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
sed_filename : str
ignored
cosmo : astropy.cosmology
@@ -1569,13 +1728,13 @@

Returns

Expand source code -
def gen_variable(self, redshift, nites, sed=None, sed_filename=None, cosmo=None):
+
def gen_variable(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None):
     """
     Generate a random variable light curve
 
     Args:
         redshift (float): ignored 
-        nites (List[int]): a list of night relative to peak you want to obtain a magnitude for    
+        nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey    
         sed_filename (str): ignored
         cosmo (astropy.cosmology): ignored
 
@@ -1589,9 +1748,9 @@ 

Returns

output_data = [] central_mag = random.uniform(12.0, 23.0) colors = {band: mag for band, mag in zip(self.bands, np.random.uniform(low=-2.0, high=2.0, size=len(self.bands)))} - for nite in nites: - central_mag = random.uniform(central_mag - 1.0, central_mag + 1.0) - for band in self.bands: + for band in self.bands: + for nite in nite_dict[band]: + central_mag = random.uniform(central_mag - 1.0, central_mag + 1.0) output_data.append([nite, band, central_mag + colors[band]]) return {'lc': pd.DataFrame(data=output_data, columns=output_data_cols), @@ -1600,7 +1759,7 @@

Returns

-def gen_variablenoise(self, redshift, nites, sed=None, sed_filename=None, cosmo=None) +def gen_variablenoise(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None)

Generate a variable light curve with small random noise

@@ -1608,8 +1767,7 @@

Args

redshift : float
ignored
-
nites : List[int]
-
a list of night relative to peak you want to obtain a magnitude for
+
nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
sed_filename : str
ignored
cosmo : astropy.cosmology
@@ -1627,13 +1785,13 @@

Returns

Expand source code -
def gen_variablenoise(self, redshift, nites, sed=None, sed_filename=None, cosmo=None):
+
def gen_variablenoise(self, redshift, nite_dict, sed=None, sed_filename=None, cosmo=None):
     """ 
     Generate a variable light curve with small random noise
 
     Args:
         redshift (float): ignored
-        nites (List[int]): a list of night relative to peak you want to obtain a magnitude for
+        nite_dict (dict[str: List[int]]): (band, list of night relative to peak you want to obtain a magnitude for) pair for each band in survey
         sed_filename (str): ignored
         cosmo (astropy.cosmology): ignored
 
@@ -1643,7 +1801,7 @@ 

Returns

- 'obj_type' contains a string for the type of object. Will always be 'VariableNoise' here - 'sed' contains the filename of the sed used. Will always be 'VariableNoise' here """ - noiseless_lc_dict = self.gen_variable(redshift, nites) + noiseless_lc_dict = self.gen_variable(redshift, nite_dict) noise = np.random.normal(loc=0, scale=0.25, size=noiseless_lc_dict['lc'].shape[0]) noiseless_lc_dict['lc']['MAG'] = noiseless_lc_dict['lc']['MAG'].values + noise noiseless_lc_dict['obj_type'] = 'VariableNoise' diff --git a/docs/utils.html b/docs/utils.html index 85a1a3b..0328001 100644 --- a/docs/utils.html +++ b/docs/utils.html @@ -31,6 +31,7 @@

Module deeplenstronomy.utils

import os import sys +import yaml from astropy.io import fits import numpy as np @@ -331,7 +332,26 @@

Module deeplenstronomy.utils

image_indices = np.argmin(np.sum(np.abs(im_param_array - map_param_array) / im_stds, axis=2), axis=0) return image_indices -
+ + +def read_cadence_file(filename): + """ + Parse a cadence file. + + Args: + filename (str): Name of cadence file + + Returns: + cadence_dict: dictionary containing cadence file contents + """ + with open(filename, 'r') as f: + cadence_dict = yaml.safe_load(f) + + # Set reference mjd to the default value of 0 + if 'REFERENCE_MJD' not in cadence_dict: + cadence_dict['REFERENCE_MJD'] = 0 + + return cadence_dict
@@ -589,6 +609,45 @@

Returns

return image_indices
+
+def read_cadence_file(filename) +
+
+

Parse a cadence file.

+

Args

+
+
filename : str
+
Name of cadence file
+
+

Returns

+
+
cadence_dict
+
dictionary containing cadence file contents
+
+
+ +Expand source code + +
def read_cadence_file(filename):
+    """
+    Parse a cadence file.
+
+    Args:
+        filename (str): Name of cadence file
+
+    Returns:
+        cadence_dict: dictionary containing cadence file contents
+    """
+    with open(filename, 'r') as f:
+        cadence_dict = yaml.safe_load(f)        
+        
+        # Set reference mjd to the default value of 0
+        if 'REFERENCE_MJD' not in cadence_dict:
+            cadence_dict['REFERENCE_MJD'] = 0
+                        
+    return cadence_dict
+
+
def read_distribution_file(filename)
@@ -871,6 +930,7 @@

Index

  • dict_select_choose
  • draw_from_user_dist
  • organize_image_backgrounds
  • +
  • read_cadence_file
  • read_distribution_file
  • read_images
  • select_params
  • diff --git a/docs/visualize.html b/docs/visualize.html index f72813e..18e56e1 100644 --- a/docs/visualize.html +++ b/docs/visualize.html @@ -32,6 +32,7 @@

    Module deeplenstronomy.visualize

    from astropy.visualization import make_lupton_rgb import matplotlib.pyplot as plt import numpy as np +import pandas as pd def _no_stretch(val): return val @@ -92,7 +93,58 @@

    Module deeplenstronomy.visualize

    plt.show(block=True) plt.close() - return + return + +def view_corner(metadata, labels, hist_kwargs={}, hist2d_kwargs={}, label_kwargs={}): + """ + Show a corner plot of the columns in a DataFrame. + + Args: + metadata (pd.DataFrame): A pandas DataFrame containing the metadata to visualize + labels (dict): A dictionary mapping column names to axis labels + hist_kwargs (dict): keyword arguments to pass to matplotlib.pyplot.hist + hist2d_kwargs (dict): keyword arguments to pass to matplotlib.pyplot.hist2d + label_kwargs (dict): keyword arguments to pass to matplotlib.axes.Axes.set_xlabel (and ylabel) + + Raises: + KeyError: if one or more of the columns are not present in the metadata + TypeError: if metadata is not a pandas DataFrame + TypeError: if labels is not a dict + """ + if not isinstance(metadata, pd.DataFrame): + raise TypeError("first argument must be a pandas DataFrame") + + if not isinstance(labels, dict): + raise TypeError("second argument must be a list") + + if any([x not in metadata.columns for x in labels]): + raise KeyError("One or more passed columns is not present in the metadata") + + fig, axs = plt.subplots(len(labels), len(labels), figsize=(14,14)) + + for row, row_label in enumerate(labels.keys()): + for col, col_label in enumerate(labels.keys()): + + if row == col: + # hist + axs[row, col].hist(metadata[row_label].values, **hist_kwargs) + + elif row > col: + # hist2d + axs[row, col].hist2d(metadata[col_label].values, + metadata[row_label].values, **hist2d_kwargs) + else: + axs[row, col].set_visible(False) + + if row == len(labels) -1: + axs[row, col].set_xlabel(labels[col_label], **label_kwargs) + + if col == 0 and row != 0: + axs[row, col].set_ylabel(labels[row_label], **label_kwargs) + + fig.tight_layout() + plt.show() + plt.close()
    @@ -102,6 +154,89 @@

    Module deeplenstronomy.visualize

    Functions

    +
    +def view_corner(metadata, labels, hist_kwargs={}, hist2d_kwargs={}, label_kwargs={}) +
    +
    +

    Show a corner plot of the columns in a DataFrame.

    +

    Args

    +
    +
    metadata : pd.DataFrame
    +
    A pandas DataFrame containing the metadata to visualize
    +
    labels : dict
    +
    A dictionary mapping column names to axis labels
    +
    hist_kwargs : dict
    +
    keyword arguments to pass to matplotlib.pyplot.hist
    +
    hist2d_kwargs : dict
    +
    keyword arguments to pass to matplotlib.pyplot.hist2d
    +
    label_kwargs : dict
    +
    keyword arguments to pass to matplotlib.axes.Axes.set_xlabel (and ylabel)
    +
    +

    Raises

    +
    +
    KeyError
    +
    if one or more of the columns are not present in the metadata
    +
    TypeError
    +
    if metadata is not a pandas DataFrame
    +
    TypeError
    +
    if labels is not a dict
    +
    +
    + +Expand source code + +
    def view_corner(metadata, labels, hist_kwargs={}, hist2d_kwargs={}, label_kwargs={}):
    +    """
    +    Show a corner plot of the columns in a DataFrame.
    +    
    +    Args:
    +        metadata (pd.DataFrame): A pandas DataFrame containing the metadata to visualize
    +        labels (dict): A dictionary mapping column names to axis labels 
    +        hist_kwargs (dict): keyword arguments to pass to matplotlib.pyplot.hist
    +        hist2d_kwargs (dict): keyword arguments to pass to matplotlib.pyplot.hist2d
    +        label_kwargs (dict): keyword arguments to pass to matplotlib.axes.Axes.set_xlabel (and ylabel)
    +        
    +    Raises:
    +        KeyError: if one or more of the columns are not present in the metadata
    +        TypeError: if metadata is not a pandas DataFrame
    +        TypeError: if labels is not a dict
    +    """
    +    if not isinstance(metadata, pd.DataFrame):
    +        raise TypeError("first argument must be a pandas DataFrame")
    +        
    +    if not isinstance(labels, dict):
    +        raise TypeError("second argument must be a list")
    +    
    +    if any([x not in metadata.columns for x in labels]):
    +        raise KeyError("One or more passed columns is not present in the metadata")
    +    
    +    fig, axs = plt.subplots(len(labels), len(labels), figsize=(14,14))
    +
    +    for row, row_label in enumerate(labels.keys()):
    +        for col, col_label in enumerate(labels.keys()):
    +
    +            if row == col:
    +                # hist
    +                axs[row, col].hist(metadata[row_label].values, **hist_kwargs)
    +
    +            elif row > col:
    +                # hist2d
    +                axs[row, col].hist2d(metadata[col_label].values, 
    +                                     metadata[row_label].values, **hist2d_kwargs)
    +            else:
    +                axs[row, col].set_visible(False)
    +
    +            if row == len(labels) -1:
    +                axs[row, col].set_xlabel(labels[col_label], **label_kwargs)
    +
    +            if col == 0 and row != 0:
    +                axs[row, col].set_ylabel(labels[row_label], **label_kwargs)
    +
    +    fig.tight_layout()
    +    plt.show()
    +    plt.close()
    +
    +
    def view_image(image, stretch_func=<function _no_stretch>, **imshow_kwargs)
    @@ -215,6 +350,7 @@

    Index

  • Functions