Premade Instruments¶
To ensure users don’t need to constantly redefine the same commonly used instruments, we provide a set of premade instruments. A list of these instruments can be printed using the print_premade_instruments
function.
[1]:
from synthesizer.instruments import print_premade_instruments
print_premade_instruments()
+-------------------+----------+----------+
| Instrument | NFilters | Cached? |
+-------------------+----------+----------+
| EuclidNISP | 3 | Yes |
| EuclidVIS | 1 | No |
| HSTACSWFC | 12 | No |
| HSTACSWFCMedium | 1 | No |
| HSTACSWFCNarrow | 3 | No |
| HSTACSWFCWide | 8 | No |
| HSTWFC3IR | 15 | No |
| HSTWFC3IRMedium | 4 | No |
| HSTWFC3IRNarrow | 6 | No |
| HSTWFC3IRWide | 5 | No |
| HSTWFC3UVIS | 57 | No |
| HSTWFC3UVISMedium | 7 | No |
| HSTWFC3UVISNarrow | 36 | No |
| HSTWFC3UVISWide | 14 | No |
| JWSTMIRI | 13 | No |
| JWSTNIRCam | 27 | No |
| JWSTNIRCamMedium | 12 | No |
| JWSTNIRCamNarrow | 7 | No |
| JWSTNIRCamWide | 8 | No |
| JWSTNIRSpec | N/A | No |
+-------------------+----------+----------+
Importing Premade Instruments¶
If you only need properties on an instrument that can be hard coded (filters, resolutions, wavelength ranges, etc.), you can import the premade instruments directly from the instruments
module. For example, importing JWST’s NIRCam instrument (including only the wide filters) can be done with the following code:
[2]:
from synthesizer.instruments import JWSTNIRCamWide
nircam = JWSTNIRCamWide()
print(nircam)
+------------------------------------------------------------------------------------------------------------------+
| INSTRUMENT |
+------------------------------------+-----------------------------------------------------------------------------+
| Attribute | Value |
+------------------------------------+-----------------------------------------------------------------------------+
| label | 'JWST.NIRCam.Wide' |
+------------------------------------+-----------------------------------------------------------------------------+
| filters | <synthesizer.instruments.filters.FilterCollection object at 0x7fd839b0f850> |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_imaging | True |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_noisy_imaging | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_noisy_resolved_spectroscopy | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_noisy_spectroscopy | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_photometry | True |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_psf_imaging | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_psf_spectroscopy | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_resolved_spectroscopy | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_spectroscopy | False |
+------------------------------------+-----------------------------------------------------------------------------+
| resolution | 0.031 arcsec |
+------------------------------------+-----------------------------------------------------------------------------+
Getting a subset of a premade instrument¶
You may not always want every filter defined on a premade instrument. In this case, you can pass a subset of filters during instatiation.
[3]:
# Print all available filters
print("All filters:", JWSTNIRCamWide.available_filters)
# Create an instrument with a subset of filters
nircam = JWSTNIRCamWide(
filter_subset=(
"JWST/NIRCam.F090W",
"JWST/NIRCam.F115W",
"JWST/NIRCam.F150W",
)
)
# Print which filters are to verify we got the subset
print("Subset:", nircam.filters.filter_codes)
All filters: ['JWST/NIRCam.F070W', 'JWST/NIRCam.F090W', 'JWST/NIRCam.F115W', 'JWST/NIRCam.F150W', 'JWST/NIRCam.F200W', 'JWST/NIRCam.F277W', 'JWST/NIRCam.F356W', 'JWST/NIRCam.F444W']
Subset: ['JWST/NIRCam.F090W', 'JWST/NIRCam.F115W', 'JWST/NIRCam.F150W']
Modifying premade Instruments¶
These premade models don’t define noise arrays or PSFs, in some cases these can be loaded (see below), but in all cases they can passed at instantiation.
[4]:
import numpy as np
# Define noise for each filter
noises = {
f: np.random.rand(100, 100) for f in JWSTNIRCamWide.available_filters
}
# Get the instrument with included noise
nircam = JWSTNIRCamWide(noise_maps=noises)
print(nircam)
+------------------------------------------------------------------------------------------------------------------+
| INSTRUMENT |
+------------------------------------+-----------------------------------------------------------------------------+
| Attribute | Value |
+------------------------------------+-----------------------------------------------------------------------------+
| label | 'JWST.NIRCam.Wide' |
+------------------------------------+-----------------------------------------------------------------------------+
| filters | <synthesizer.instruments.filters.FilterCollection object at 0x7fd83acf8310> |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_imaging | True |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_noisy_imaging | True |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_noisy_resolved_spectroscopy | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_noisy_spectroscopy | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_photometry | True |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_psf_imaging | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_psf_spectroscopy | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_resolved_spectroscopy | False |
+------------------------------------+-----------------------------------------------------------------------------+
| can_do_spectroscopy | False |
+------------------------------------+-----------------------------------------------------------------------------+
| resolution | 0.031 arcsec |
+------------------------------------+-----------------------------------------------------------------------------+
| noise_maps | JWST/NIRCam.F070W: ndarray |
| | JWST/NIRCam.F090W: ndarray |
| | JWST/NIRCam.F115W: ndarray |
| | JWST/NIRCam.F150W: ndarray |
| | JWST/NIRCam.F200W: ndarray |
| | JWST/NIRCam.F277W: ndarray |
| | JWST/NIRCam.F356W: ndarray |
| | JWST/NIRCam.F444W: ndarray |
+------------------------------------+-----------------------------------------------------------------------------+
The same can be done for any instrument property. Even if these are defined in the premade instrument, you can override them by passing a new value at instantiation.
Loading Premade Instruments¶
We have also generated a file for each of the premade instruments which can be downloaded and then loaded at will. These are particularly useful for instruments where we have included PSFs and other “heavier” properties which could not be stored within the classes themselves. These are also useful when running in situation where an internet connection is not available, such as on a remote cluster, or when loading the same instrument on lots of ranks in a parallel job, where downloading the instrument file once is much more efficient than downloading it on each rank.
These files are available for download with the Synthesizer download tool. To download these you can simply invoke the command line tool with the --instruments
argument and pass the name of the desired class.
synthesizer-download --instruments EuclidNISP
This will place the instrument file in the cache directory ready to be loaded whenever you need it. To load an instrument, you can simply use the load
class method.
[5]:
from synthesizer.instruments import EuclidNISP
euclid = EuclidNISP.load()
/home/runner/work/synthesizer/synthesizer/src/synthesizer/instruments/instrument.py:347: RuntimeWarning: Synthesizer versions differ between the code and FilterCollection file! This is probably fine but there is no gaurantee it won't cause errors.
filters = FilterCollection._from_hdf5(group["Filters"])
Overiding loaded properties¶
Similarly to imported instruments, you can override any of the properties defined in the loaded instrument. This is done by passing keyword arguments to the load
method.
[6]:
from unyt import arcsecond
euclid = EuclidNISP.load(resolution=0.5 * arcsecond)
As you can imagine, this extends to only loading a subset of filters.
[7]:
print(EuclidNISP.available_filters)
euclid = EuclidNISP.load(filter_subset=("Euclid/NISP.Y", "Euclid/NISP.J"))
print(euclid.filters.filter_codes)
['Euclid/NISP.Y', 'Euclid/NISP.J', 'Euclid/NISP.H']
['Euclid/NISP.Y', 'Euclid/NISP.J']