Generate a COOLEST template file#
In this notebook we use the Python interface of COOLEST to generate an example template file, by defining a hypothetical lensing system and the corresponding mass and light models.
author: @aymgal
last update: 11/07/23
import os
from coolest.template.lazy import *
from coolest.template import info
from coolest.template.standard import COOLEST
from coolest.template.json import JSONSerializer
from pprint import pprint
Create the content of the template#
Define the directory and name of the template#
TEMPLATE_NAME = 'coolest_template'
TEMPLATE_DIR = 'template_dir'
Setup the different components#
Each Python class will have an associated key in the output JSON file.
# Setup cosmology
cosmology = Cosmology(H0=73.0, Om0=0.3)
# Create a couple of source galaxies at different redshifts
source_1 = Galaxy('a source galaxy', 2.0,
light_model=LightModel('Sersic'))
source_2 = Galaxy('another source', 1.5,
light_model=LightModel('PixelatedRegularGrid'))
source_2.light_model[0].parameters['pixels'].set_grid('regul_grid_image.fits',
field_of_view_x=(-3.0, 1.0),
field_of_view_y=(-2.0, 2.0),
check_fits_file=False)
source_3 = Galaxy('a VKL source', 1.2,
light_model=LightModel('IrregularGrid'))
source_3.light_model[0].parameters['pixels'].set_grid('irreg_grid_pixels.fits',
check_fits_file=False)
# Create a lens galaxy
lens_1 = Galaxy('a lens galaxy', 0.5,
light_model=LightModel('Sersic', 'Sersic'),
mass_model=MassModel('PEMD', 'PixelatedRegularGridPotential'))
lens_1.mass_model[1].parameters['pixels'].set_grid('regul_grid_image.fits',
field_of_view_x=(-3.0, 1.0),
field_of_view_y=(-2.0, 2.0),
check_fits_file=False)
# Defines the external shear
ext_shear = MassField('my lovely external shear', lens_1.redshift,
mass_model=MassModel('ExternalShear'))
# Put them in a list, which will also create unique IDs for each profile
entity_list = LensingEntityList(ext_shear, lens_1, source_1, source_2, source_3)
# Define the origin of the coordinates system
origin = CoordinatesOrigin('00h11m20.244s', '-08d45m51.48s')
# EXAMPLE for accessing specific parameters and add priors/values/posteriors
# - add a gaussian prior to a given parameter
from coolest.template.classes.probabilities import GaussianPrior
lens_1.mass_model[0].parameters['gamma'].set_prior(GaussianPrior(mean=2.0, width=0.2))
# - add a point estimate to a given parameter
from coolest.template.classes.parameter import PointEstimate
ext_shear.mass_model[0].parameters['gamma_ext'].set_point_estimate(0.07)
lens_1.light_model[1].parameters['q'].set_point_estimate(PointEstimate(value=0.89))
# - add a posterior distribution (as 0th and 1st order statistics)
from coolest.template.classes.probabilities import PosteriorStatistics
source_1.light_model[0].parameters['theta_eff'].set_posterior(PosteriorStatistics(mean=0.11, median=0.15,
percentile_16th=0.03, percentile_84th=0.05))
# Provide data file
obs_pixels = PixelatedRegularGrid('obs.fits')
# Select the type of noise
from coolest.template.classes.noise import InstrumentalNoise, UniformGaussianNoise
noise = InstrumentalNoise()
# noise = UniformGaussianNoise(std_dev=0.004)
observation = Observation(pixels=obs_pixels, noise=noise)
# Defines the instrument
from coolest.template.classes.psf import PixelatedPSF, GaussianPSF
psf = PixelatedPSF(PixelatedRegularGrid('psf_kernel.fits'))
#psf = GaussianPSF(0.2)
instrument = Instrument(0.08, # pixel size
name='some instrument',
readout_noise=4,
band='F160W',
psf=psf)
Group all instances above into a “master” COOLEST object#
# Master object for the standard
coolest = COOLEST('MAP',
origin,
entity_list,
observation,
instrument,
cosmology)
Export it as the COOLEST template (JSON format)#
Here we use the default "MAP" (maximum a posterior) mode, so that the template files contains placeholders for best-fit, prior and posterior distributions.
# export as JSON file
template_path = os.path.join(os.getcwd(), TEMPLATE_DIR, TEMPLATE_NAME)
serializer = JSONSerializer(template_path, obj=coolest,
check_external_files=True)
# you can either dump it using jsonpickle (faster to load afterwards)
serializer.dump_jsonpickle() # NOTE: this will add a '_pyAPI' suffix to the template file name
# or using pure JSON (more human-readable)
serializer.dump_simple()
You can easily load a COOLEST instance from the template as follows
coolest_2 = serializer.load()
pprint(coolest_2.lensing_entities)
[<coolest.template.classes.mass_field.MassField object at 0x1304da520>,
<coolest.template.classes.galaxy.Galaxy object at 0x1304daa60>,
<coolest.template.classes.galaxy.Galaxy object at 0x13048fd30>,
<coolest.template.classes.galaxy.Galaxy object at 0x1304f1220>,
<coolest.template.classes.galaxy.Galaxy object at 0x13051a8b0>]
You can have a look at the unique IDs that profiles and parameters have
A given profile has a unique ID with the following pattern:
{entity index}-{{massfield} or {galaxy}}-{{mass} or {light}}-{profile index}_{profile name}
A given parameter has the same ID as above, just with the parameter name at the end:
{entity index}-{{massfield} or {galaxy}}-{{mass} or {light}}-{profile index}_{profile name}-{parameter name}
# access a profile ID
print(coolest_2.lensing_entities[0].mass_model[0].id)
print(coolest_2.lensing_entities[1].light_model[-1].id)
# access a parameter ID (the profile ID + parameter name)
print(coolest_2.lensing_entities[0].mass_model[0].parameters['gamma_ext'].id)
print(coolest_2.lensing_entities[1].light_model[-1].parameters['theta_eff'].id)
0-massfield-mass-0-ExternalShear
1-galaxy-light-1-Sersic
0-massfield-mass-0-ExternalShear-gamma_ext
1-galaxy-light-1-Sersic-theta_eff
You can retrieve the list of all, or a subset of, parameter IDs via the lensing_entity list
# either all IDs at once
print("All parameter IDs:")
print(coolest_2.lensing_entities.get_parameter_ids())
print("")
# or only those with a given parameter name
print("Subset of parameter IDs:")
print(coolest_2.lensing_entities.get_parameter_ids(with_name='q'))
print(coolest_2.lensing_entities.get_parameter_ids(with_name='theta_E'))
All parameter IDs:
['0-massfield-mass-0-ExternalShear-gamma_ext', '0-massfield-mass-0-ExternalShear-phi_ext', '1-galaxy-light-0-Sersic-I_eff', '1-galaxy-light-0-Sersic-theta_eff', '1-galaxy-light-0-Sersic-n', '1-galaxy-light-0-Sersic-q', '1-galaxy-light-0-Sersic-phi', '1-galaxy-light-0-Sersic-center_x', '1-galaxy-light-0-Sersic-center_y', '1-galaxy-light-1-Sersic-I_eff', '1-galaxy-light-1-Sersic-theta_eff', '1-galaxy-light-1-Sersic-n', '1-galaxy-light-1-Sersic-q', '1-galaxy-light-1-Sersic-phi', '1-galaxy-light-1-Sersic-center_x', '1-galaxy-light-1-Sersic-center_y', '1-galaxy-mass-0-PEMD-gamma', '1-galaxy-mass-0-PEMD-theta_E', '1-galaxy-mass-0-PEMD-q', '1-galaxy-mass-0-PEMD-phi', '1-galaxy-mass-0-PEMD-center_x', '1-galaxy-mass-0-PEMD-center_y', '1-galaxy-mass-1-PixelatedRegularGridPotential-pixels', '2-galaxy-light-0-Sersic-I_eff', '2-galaxy-light-0-Sersic-theta_eff', '2-galaxy-light-0-Sersic-n', '2-galaxy-light-0-Sersic-q', '2-galaxy-light-0-Sersic-phi', '2-galaxy-light-0-Sersic-center_x', '2-galaxy-light-0-Sersic-center_y', '3-galaxy-light-0-PixelatedRegularGrid-pixels', '4-galaxy-light-0-IrregularGrid-pixels']
Subset of parameter IDs:
['1-galaxy-light-0-Sersic-q', '1-galaxy-light-1-Sersic-q', '1-galaxy-mass-0-PEMD-q', '2-galaxy-light-0-Sersic-q']
['1-galaxy-mass-0-PEMD-theta_E']
You can also retrieve the list of all Parameter instances
# or you can als get Parameters objects
print("All parameters with name 'q' that are not fixed:")
print(coolest_2.lensing_entities.get_parameters(with_fixed=False, with_name='q'))
print("")
All parameters with name 'q' that are not fixed:
[<coolest.template.classes.parameter.NonLinearParameter object at 0x1304f4940>, <coolest.template.classes.parameter.NonLinearParameter object at 0x13051a280>, <coolest.template.classes.parameter.NonLinearParameter object at 0x13048fee0>, <coolest.template.classes.parameter.NonLinearParameter object at 0x13051b5e0>]
Using different template modes that hide or add template fields#
Here we use the mode "MOCK", so that some keys, such as prior and posterior information, are not output in the JSON file. This file can then be directly as an input to a lens simulator code that interfaces with COOLEST.
# Master object for the standard
coolest_mock = COOLEST('MOCK',
origin,
entity_list,
observation,
instrument,
cosmology)
# output to JSON
template_path_mock = os.path.join(os.getcwd(), TEMPLATE_DIR, TEMPLATE_NAME+"_mock")
serializer_mock = JSONSerializer(template_path_mock, obj=coolest_mock,
check_external_files=True)
serializer_mock.dump_simple()
Finally, we can use the mode "DOC" to output significantly more information about each components of the COOLEST template. For instance, it includes the documentation related to each fields, LaTeX strings of parameters, their units, etc.
# Master object for the standard
coolest_doc = COOLEST('DOC',
origin,
entity_list,
observation,
instrument,
cosmology)
# output to JSON
template_path_doc = os.path.join(os.getcwd(), TEMPLATE_DIR, TEMPLATE_NAME+"_doc")
serializer_doc = JSONSerializer(template_path_doc, obj=coolest_doc,
check_external_files=True)
serializer_doc.dump_simple()