55the nominal flat AB spectrum of 3631 Jy. The ultimate source of this
66information is https://roman.gsfc.nasa.gov/science/WFI_technical.html .
77"""
8- import numpy as np
9- from importlib import resources
10- from scipy import integrate
11- from astropy import constants
12- from astropy .io import ascii
13- from astropy import units as u
14- from romanisim import parameters
158
16- # to go from calibrated fluxes in maggies to counts in the Roman bands
17- # we need to multiply by a constant determined by the AB magnitude
18- # system and the shape of the Roman bands.
19- # The constant is \int (3631 Jy) (1/hv) T(v) dv
20- # T(v) should be the effective area at each wavelength, I guess
21- # divided by some nominal overall effective area.
9+ import warnings
2210
11+ warnings .warn (
12+ "romanisim.bandpass is deprecated and will be removed in a future version. "
13+ "Please use 'romanisim.models.bandpass' instead." ,
14+ DeprecationWarning ,
15+ stacklevel = 2 ,
16+ )
2317
24- # provide some translation dictionaries for the mapping from
25- # the galsim bandpass names to the Roman bandpass names and vice versa.
26- # it would be nice to be agnostic about which one we use.
27- galsim_bandpasses = [
28- 'R062' , 'Z087' , 'Y106' , 'J129' , 'H158' , 'F184' , 'K213' , 'W146' ]
29- galsim2roman_bandpass = {x : 'F' + x [1 :] for x in galsim_bandpasses }
30- roman2galsim_bandpass = {v : k for k , v in galsim2roman_bandpass .items ()}
18+ def __getattr__ (name ):
19+ if name .startswith ("__" ):
20+ raise AttributeError (name )
3121
32- # provide some no-ops if we are given a key in the right bandpass
33- galsim2roman_bandpass .update (** {k : k for k in roman2galsim_bandpass })
34- roman2galsim_bandpass .update (** {k : k for k in galsim_bandpasses })
22+ from romanisim .models import bandpass
3523
36- # AB Zero Spectral Flux Density
37- ABZeroSpFluxDens = 3631e-23 * u .erg / (u .s * u .cm ** 2 * u .hertz )
38-
39-
40- def read_gsfc_effarea (sca , filename = None ):
41- """Read an effective area file from Roman.
42-
43- This just puts together the right invocation to get an Excel-converted
44- ECSV file into memory.
45-
46- Parameters
47- ----------
48- sca : int
49- the name of the detector. A number between 1-18.
50- filename : str
51- filename to read in
52-
53- Returns
54- -------
55- astropy.table.Table
56- table with effective areas for different Roman bandpasses.
57- """
58-
59- # The throughput files come as ECSV from March 2024 so the invocation changed to properly read the ECSVs.
60- if filename is None :
61- filename = str (resources .files ('romanisim' ) / 'data' / 'Roman_effarea_tables_20240327'
62- / f'Roman_effarea_v8_SCA{ sca :02} _20240301.ecsv' )
63- out = ascii .read (filename )
64- else :
65- out = ascii .read (filename )
66- return out
67-
68-
69- def compute_abflux (sca , effarea = None ):
70- """Compute the AB zero point fluxes for each filter.
71-
72- How many electrons would a zeroth magnitude AB star deposit in
73- Roman's detectors in a second?
74-
75- Parameters
76- ----------
77- sca : int
78- the name of the detector. A number between 1-18.
79- effarea : astropy.Table.table
80- Table from GSFC with effective areas for each filter.
81-
82- Returns
83- -------
84- dict[str] : float
85- lookup table of zero point fluxes for each filter (electrons / s)
86- """
87-
88- if effarea is None :
89- effarea = read_gsfc_effarea (sca )
90-
91- # get the filter names. This is a bit ugly since there's also
92- # a wavelength column 'Wave', and Excel appends a column to each line
93- # which astropy then gives a default name col12 to.
94- filter_names = [x for x in effarea .dtype .names
95- if x != 'Wave' and 'col' not in x ]
96- abfv = ABZeroSpFluxDens
97- out = dict ()
98- for bandpass in filter_names :
99- out [bandpass ] = compute_count_rate (flux = abfv , bandpass = bandpass , sca = sca , effarea = effarea )
100-
101- # Saving the SCA information to use the correct throughput curves for each detector.
102- out = {f'SCA{ sca :02} ' :out }
103- return out
104-
105-
106- def get_abflux (bandpass , sca ):
107- """Get the zero point flux for a particular bandpass.
108-
109- This is a simple wrapper for compute_abflux, caching the results.
110-
111- Parameters
112- ----------
113- bandpass : str
114- the name of the bandpass
115- sca : int
116- the name of the detector. A number between 1-18.
117- Returns
118- -------
119- float
120- the zero point flux (electrons / s)
121- """
122- bandpass = galsim2roman_bandpass .get (bandpass , bandpass )
123-
124- # If abflux for this bandpass for the specified SCA has been calculated, return the calculated
125- # value instead of rerunning an expensive calculation
126- abflux = getattr (get_abflux , 'abflux' , None )
127- if (abflux is None ) or (f'SCA{ sca :02} ' not in abflux ):
128- abflux = compute_abflux (sca )
129- get_abflux .abflux = abflux
130- return abflux [f'SCA{ sca :02} ' ][bandpass ]
131-
132-
133- def compute_count_rate (flux , bandpass , sca , filename = None , effarea = None , wavedist = None ):
134- """Compute the count rate in a given filter, for a specified SED.
135-
136- How many electrons would an object with SED given by
137- flux deposit in Roman's detectors in a second?
138-
139- Parameters
140- ----------
141- flux : float or np.ndarray with shape matching wavedist.
142- Spectral flux density in units of ergs per second * hertz * cm^2
143- bandpass : str
144- the name of the bandpass
145- sca : int
146- the name of the detector. A number between 1-18.
147- filename : str
148- filename to read in
149- effarea : astropy.Table.table
150- Table from GSFC with effective areas for each filter.
151- wavedist : numpy.ndarray
152- Array of wavelengths along which spectral flux densities are defined in microns
153-
154- Returns
155- -------
156- float
157- the total bandpass flux (electrons / s)
158- """
159- # Read in default Roman effective areas from Goddard, if areas not supplied
160- if effarea is None :
161- effarea = read_gsfc_effarea (sca , filename )
162-
163- # If wavelength distribution is supplied, interpolate flux and area
164- # over it and the effective area table layout
165- if wavedist is not None :
166- # Ensure that wavedist and flux have the same shape
167- if wavedist .shape != flux .shape :
168- raise ValueError ('wavedist and flux must have identical shapes!' )
169-
170- all_wavel = np .unique (np .concatenate ((effarea ['Wave' ], wavedist )))
171- all_flux = np .interp (all_wavel , wavedist , flux )
172- all_effarea = np .interp (all_wavel , effarea ['Wave' ], effarea [bandpass ])
173- else :
174- all_wavel = effarea ['Wave' ]
175- all_flux = flux
176- all_effarea = effarea [bandpass ]
177-
178- integrand = all_flux * constants .c / (
179- all_wavel * u .micron )** 2 # f_lambda
180- integrand /= constants .h * constants .c / (
181- all_wavel * u .micron ) # hc/lambda
182- integrand *= all_effarea * u .m ** 2 # effective area in filter
183- # integrate.simpson looks like it loses units. So convert to something
184- # we know about.
185- integrand = integrand .to (1 / (u .s * u .micron )).value
186-
187- zpflux = integrate .simpson (integrand , x = all_wavel )
188- # effarea['Wave'] is in microns, so we're left with a number of counts
189- # per second
190-
191- return zpflux
192-
193-
194- def etomjysr (bandpass , sca ):
195- """Compute factor converting e/s/pix to MJy/sr.
196-
197- Assumes a pixel scale of 0.11" (romanisim.parameters.pixel_scale)
198-
199- Parameters
200- ----------
201- bandpass : str
202- the name of the bandpass
203- sca : int
204- the name of the detector. A number between 1-18.
205- Returns
206- -------
207- float
208- the factor F such that MJy / sr = F * DN/s
209- """
210-
211- abflux = get_abflux (bandpass , sca ) # e/s corresponding to 3631 Jy
212- srpix = ((parameters .pixel_scale * u .arcsec ) ** 2 ).to (u .sr ).value
213- mjysr = 1 / abflux * 3631 / 10 ** 6 / srpix # should be ~0.3
214- return mjysr
215-
24+ warnings .warn (
25+ f"'romanisim.bandpass.{ name } ' is deprecated and will be removed in a future version."
26+ f"Please use 'romanisim.models.bandpass.{ name } ' instead." ,
27+ DeprecationWarning ,
28+ stacklevel = 2 ,
29+ )
30+ return getattr (bandpass , name )
0 commit comments