diff --git a/pandexo/engine/compute_noise.py b/pandexo/engine/compute_noise.py
index fda2d9d..f19ca8c 100755
--- a/pandexo/engine/compute_noise.py
+++ b/pandexo/engine/compute_noise.py
@@ -62,7 +62,6 @@ def __init__(self, inn, out, rn, extraction_area, timing):
#on source out versus in
self.exptime_per_int = self.tframe * (self.ngroups_per_int+self.frame_zero_dead )
-
self.on_source_in = self.tframe * (self.ngroups_per_int+self.frame_zero_dead) * self.nint_in
self.on_source_out = self.tframe * (self.ngroups_per_int+self.frame_zero_dead) * self.nint_out
@@ -352,27 +351,38 @@ def run_slope_method(self):
#In the following the SN is changed to incorporate number of occultations
#i.e. multiply by sqrt(n)
- sn_in = curves_inn['sn'][1]
- sn_out = curves_out['sn'][1]
+ #sn_in = curves_inn['sn'][1]*np.sqrt(self.nint_in)
+ #sn_out = curves_out['sn'][1]*np.sqrt(self.nint_out)
- extracted_flux_inn = curves_inn['extracted_flux'][1]*on_source_in
+ #extracted_flux_inn = curves_inn['extracted_flux'][1]*on_source_in
- extracted_noise_inn = curves_inn['extracted_flux'][1]/(sn_in)
+ #extracted_noise_inn = curves_inn['extracted_flux'][1]/(sn_in)
- extracted_flux_out = curves_out['extracted_flux'][1]*on_source_out
+ #extracted_flux_out = curves_out['extracted_flux'][1]*on_source_out
- extracted_noise_out = curves_out['extracted_flux'][1]/(sn_out)
+ #extracted_noise_out = curves_out['extracted_flux'][1]/(sn_out)
+
+ extracted_flux_inn = curves_inn['extracted_flux'][1] * self.nint_in
+
+ extracted_flux_out = curves_out['extracted_flux'][1] * self.nint_out
+
+ extracted_noise_inn = curves_inn['extracted_noise'][1] * np.sqrt(self.nint_in)
+
+ extracted_noise_out = curves_out['extracted_noise'][1] * np.sqrt(self.nint_out)
#units of this unconventional.. sigma/s
#because snr = extracted flux / extracted noise and
#extracted flux in units of electrons /s
- varin = (extracted_noise_inn*on_source_in)**2.0
- varout = (extracted_noise_out*on_source_out)**2.0
+ #varin = (extracted_noise_inn*on_source_in)**2.0
+ #varout = (extracted_noise_out*on_source_out)**2.0
+ varin = extracted_noise_inn**2
+ varout = extracted_noise_out**2
return {'photon_out_1d':extracted_flux_out, 'photon_in_1d':extracted_flux_inn,
'var_in_1d':varin, 'var_out_1d': varout,'on_source_in':self.on_source_in,
'on_source_out':self.on_source_out,'bkg[out,in]':[bkg_flux_out,bkg_flux_inn],
- 'rn[out,in]':[rn_var_out,rn_var_inn]}
+ 'rn[out,in]':[rn_var_out,rn_var_inn],
+ 'nint_in':self.nint_in, 'nint_out':self.nint_out}
def run_f_minus_l(self):
@@ -419,7 +429,8 @@ def run_f_minus_l(self):
return {'photon_out_1d':extracted_flux_out, 'photon_in_1d':extracted_flux_inn,
'var_in_1d':varin, 'var_out_1d': varout,'on_source_in':self.on_source_in,
'on_source_out':self.on_source_out, 'rn[out,in]':[rn_var_out,rn_var_inn],
- 'bkg[out,in]':[bkg_flux_out,bkg_flux_inn]}
+ 'bkg[out,in]':[bkg_flux_out,bkg_flux_inn],
+ 'nint_in':self.nint_in, 'nint_out':self.nint_out}
diff --git a/pandexo/engine/justdoit.py b/pandexo/engine/justdoit.py
index 7787045..2ed2467 100755
--- a/pandexo/engine/justdoit.py
+++ b/pandexo/engine/justdoit.py
@@ -25,7 +25,8 @@
"NIRSpec G395H":False,
"NIRSpec Prism":False,
"NIRCam F322W2":False,
- "NIRCam F444W":False}
+ "NIRCam F444W":False,
+ "NIRCam DHS":False}
def print_instruments(verbose=True):
diff --git a/pandexo/engine/justplotit.py b/pandexo/engine/justplotit.py
index 8c0ff2b..269ee01 100755
--- a/pandexo/engine/justplotit.py
+++ b/pandexo/engine/justplotit.py
@@ -506,6 +506,7 @@ def jwst_noise(result_dict, plot=True, output_file= 'noise.html'):
y = result_dict['FinalSpectrum']['error_w_floor']*1e6
x = x[~np.isnan(y)]
y = y[~np.isnan(y)]
+
ymed = np.median(y)
diff --git a/pandexo/engine/jwst.py b/pandexo/engine/jwst.py
index b17d58b..9561917 100755
--- a/pandexo/engine/jwst.py
+++ b/pandexo/engine/jwst.py
@@ -15,7 +15,10 @@
#constant parameters.. consider putting these into json file
#max groups in integration
-max_ngroup = 65536.0
+max_ngroup = {'nirspec':65536.0 ,
+ 'miri':65536.0 ,
+ 'niriss':65536.0 ,
+ 'nircam':30}
#minimum number of integrations
min_nint_trans = 1
@@ -72,11 +75,26 @@ def compute_full_sim(dictinput,verbose=False):
#which instrument
instrument = pandeia_input['configuration']['instrument']['instrument']
conf = pandeia_input['configuration']
-
+
+ #now fix DHS #of spectra depending on the subarray
+ if 'dhs' in conf['instrument']['aperture']:
+ substripe = pandeia_input['configuration']['detector']['subarray']
+ nspectra = 2*int(substripe[substripe.find('stripe')+6])
+ pandeia_input['configuration']['instrument']['aperture'] = f'dhs0spec{nspectra}'
+
+ #if long wave setup with dhs is asked for change to lw grism
+ if (('32' in pandeia_input['configuration']['instrument']['filter']) or
+ ('44' in pandeia_input['configuration']['instrument']['filter'])):
+ pandeia_input['configuration']['instrument']['mode']='lw_tsgrism'
+ pandeia_input['configuration']['instrument']['aperture']='lw'
+ pandeia_input['configuration']['instrument']['disperser']='grismr'
#if optimize is in the ngroups section, this will throw an error
#so create temp conf with 2 groups
if 'optimize' in str(conf['detector']['ngroup']):
conf_temp = deepcopy(conf)
+ if 'dhs' in conf['instrument']['aperture']:
+ #for DHS also need to swap to bright mode to get only the highest throughput spectra
+ conf_temp['instrument']['aperture'] = 'dhs0bright'
conf_temp['detector']['ngroup'] = 2
else:
conf_temp = conf
@@ -94,7 +112,7 @@ def compute_full_sim(dictinput,verbose=False):
exp_pars = i.the_detector.exposure_spec
tframe =exp_pars.tframe
nframe = exp_pars.nframe
- nskip = exp_pars.nsample_skip
+ nskip = exp_pars.ndrop2
sat_unit = pandexo_input['observation']['sat_unit']
@@ -160,7 +178,8 @@ def compute_full_sim(dictinput,verbose=False):
if verbose: print("Finished Duty Cycle Calc")
#calculate all timing info
- timing, flags = compute_timing(m,transit_duration,expfact_out,noccultations)
+ max_ngroup_instrument = max_ngroup[pandeia_input["configuration"]["instrument"]["instrument"]]
+ timing, flags = compute_timing(m,transit_duration,expfact_out,noccultations,max_ngroup_instrument)
#Simulate out trans and in transit
if verbose: print("Starting Out of Transit Simulation")
@@ -257,12 +276,15 @@ def compute_full_sim(dictinput,verbose=False):
timing["Zero Frame Efficiency Loss"])*tframe
ti = (timing["APT: Num Groups per Integration"]+
timing["Zero Frame Efficiency Loss"])*tframe
+ nint_in = 1
+ nint_out = 1
else:
#otherwise error propagation and account for different
#times in transit and out
to = result['on_source_out']
ti = result['on_source_in']
-
+ nint_in = result['nint_in']
+ nint_out = result['nint_out']
var_tot = (to/ti/photon_out_bin)**2.0 * var_in_bin + (photon_in_bin*to/ti/photon_out_bin**2.0)**2.0 * var_out_bin
error_spec = np.sqrt(var_tot)
@@ -293,6 +315,8 @@ def compute_full_sim(dictinput,verbose=False):
rawstuff = {
'electrons_out':photon_out_bin*nocc,
'electrons_in':photon_in_bin*nocc,
+ 'electron_per_int':photon_out_bin/nint_out,
+ 'snr_int':[out['1d']['sn'][0],out['1d']['sn'][1]],
'var_in':var_in_bin*nocc,
'var_out':var_out_bin*nocc,
'e_rate_out':photon_out_bin/to,
@@ -367,7 +391,7 @@ def compute_maxexptime_per_int(pandeia_input, sat_level):
return maxexptime_per_int
-def compute_timing(m,transit_duration,expfact_out,noccultations):
+def compute_timing(m,transit_duration,expfact_out,noccultations,max_ngroup_instrument):
"""Computes all timing info for observation
Computes all JWST specific timing info for observation including. Some pertinent
@@ -437,8 +461,8 @@ def compute_timing(m,transit_duration,expfact_out,noccultations):
#if you exceed that limit, set it to the maximum value instead.
#also set another check for saturation
- if ngroups_per_int > max_ngroup:
- ngroups_per_int = max_ngroup
+ if ngroups_per_int > max_ngroup_instrument:
+ ngroups_per_int = max_ngroup_instrument
flag_high = "Groups/int > max num of allowed groups"
if (ngroups_per_int < mingroups) | np.isnan(ngroups_per_int):
@@ -570,7 +594,7 @@ def perform_out(pandeia_input, pandexo_input,timing, both_spec):
"""
#pandeia inputs, simulate one integration at a time
pandeia_input['configuration']['detector']['ngroup'] = int(timing['APT: Num Groups per Integration'])
- pandeia_input['configuration']['detector']['nint'] = int(timing['Num Integrations Out of Transit'])
+ pandeia_input['configuration']['detector']['nint'] = 1#int(timing['Num Integrations Out of Transit'])
pandeia_input['configuration']['detector']['nexp'] = 1
report_out = perform_calculation(pandeia_input, dict_report=False)
@@ -623,7 +647,7 @@ def perform_in(pandeia_input, pandexo_input,timing, both_spec, out, calculation)
#only run pandeia a third time if doing slope method and need accurate run for the
#nint and timing
pandeia_input['configuration']['detector']['ngroup'] = int(timing['APT: Num Groups per Integration'])
- pandeia_input['configuration']['detector']['nint'] = int(timing['Num Integrations In Transit'])
+ pandeia_input['configuration']['detector']['nint'] = 1#int(timing['Num Integrations In Transit'])
pandeia_input['configuration']['detector']['nexp'] = 1
in_transit_spec = np.array([both_spec['wave'], both_spec['flux_in_trans']])
@@ -932,8 +956,11 @@ def as_dict(out, both_spec ,binned, timing, mag, sat_level, warnings, punit, unb
p=1.0
if punit == 'fp/f*': p = -1.0
+ frame_loss = timing['Zero Frame Efficiency Loss']
timing.pop("Zero Frame Efficiency Loss")
timing_div = pd.DataFrame.from_dict(timing, orient='index')
+ #add back in so its not in html, but in timing dict
+ timing["Zero Frame Efficiency Loss"]=frame_loss
timing_div.columns = ['Value']
timing_div = timing_div.to_html()
timing_div = '
\n' + timing_div[36:len(timing_div)]
@@ -944,7 +971,17 @@ def as_dict(out, both_spec ,binned, timing, mag, sat_level, warnings, punit, unb
warnings_div = warnings_div.to_html()
warnings_div = ' \n' + warnings_div[36:len(warnings_div)]
warnings_div = warnings_div.encode()
-
+
+ map_dhs_names = {'sub40stripe1_dhs':'SUB40S1_2-SPECTRA',
+ 'sub80stripe2_dhs':'SUB80S2_4-SPECTRA',
+ 'sub160stripe4_dhs':'SUB160S4_8-SPECTRA',
+ 'sub256stripe4_dhs':'SUB256S4_8-SPECTRA'
+ }
+
+ subarray = out['input']['configuration']['detector']['subarray']
+ for idhs in map_dhs_names.keys():
+ subarray = subarray.replace(idhs, f'{idhs} (ETC Name)/ {map_dhs_names[idhs]} (APT Name)')
+
input_dict = {
"Target Mag": mag ,
"Saturation Level (electons)": sat_level,
@@ -952,8 +989,8 @@ def as_dict(out, both_spec ,binned, timing, mag, sat_level, warnings, punit, unb
"Mode": out['input']['configuration']['instrument']['mode'],
"Aperture": out['input']['configuration']['instrument']['aperture'],
"Disperser": out['input']['configuration']['instrument']['disperser'],
- "Subarray": out['input']['configuration']['detector']['subarray'],
- "Readmode": out['input']['configuration']['detector']['readmode'],
+ "Subarray": subarray,
+ "Readmode": out['input']['configuration']['detector']['readout_pattern'],
"Filter": out['input']['configuration']['instrument']['filter'],
"Primary/Secondary": punit
}
diff --git a/pandexo/engine/load_modes.py b/pandexo/engine/load_modes.py
index ca9d1b5..f61c003 100755
--- a/pandexo/engine/load_modes.py
+++ b/pandexo/engine/load_modes.py
@@ -24,6 +24,7 @@ class SetDefaultModes():
- "NIRSpec Prism"
- "NIRCam F322W2"
- "NIRCam F444W"
+ - "NIRCam DHS"
- "WFC3 G102"
- "WFC3 G141"
@@ -34,8 +35,10 @@ class SetDefaultModes():
"""
def __init__(self, inst):
- self.instrument = inst[0:inst.find(' ')].lower()
- self.config = inst[inst.find(' ')+1:len(inst)].lower()
+ self.user_input=inst
+ self.instrument = inst.split(' ')[0].lower()
+ self.config =inst.split(' ')[1].lower()
+
def pick(self):
"""Points to specific instrument based on key choice
@@ -87,10 +90,17 @@ def nirspec(self):
def nircam(self):
"""Handles NIRCam template
"""
+ if 'dhs' in self.config:
+ add='dhs_'
+ else:
+ add=''
with open(os.path.join(os.path.dirname(__file__), "reference",
- "nircam_input.json")) as data_file:
+ f"nircam_{add}input.json")) as data_file:
pandeia_data = json.load(data_file)
- pandeia_data["configuration"]["instrument"]["filter"] = self.config
+
+ if 'dhs' not in self.config:
+ pandeia_data["configuration"]["instrument"]["filter"] = self.config
+
return pandeia_data
def miri(self):
diff --git a/pandexo/engine/reference/exo_input.json b/pandexo/engine/reference/exo_input.json
index 53adf7f..0935104 100755
--- a/pandexo/engine/reference/exo_input.json
+++ b/pandexo/engine/reference/exo_input.json
@@ -1,5 +1,5 @@
{
- "calculation":"fml",
+ "calculation":"slope method",
"url": null,
"url_err": null,
"star":{
diff --git a/pandexo/engine/reference/nircam_dhs_input.json b/pandexo/engine/reference/nircam_dhs_input.json
new file mode 100644
index 0000000..ee2faa3
--- /dev/null
+++ b/pandexo/engine/reference/nircam_dhs_input.json
@@ -0,0 +1,72 @@
+{
+ "telescope":"jwst",
+ "scene":[ {
+ "id": 1,
+ "target": true,
+ "position": {
+ "ang_unit": "arcsec",
+ "x_offset": 0.0,
+ "y_offset": 0.0
+ },
+ "shape": {
+ "geometry": "point"
+ },
+ "spectrum": {
+ "extinction": {
+ "bandpass": "j",
+ "law": "mw_rv_31",
+ "unit": "mag",
+ "value": 0.0
+ },
+ "normalization": {
+ "type": "none"},
+ "sed": {
+ "sed_type": "input",
+ "spectrum": []
+ },
+ "lines": []
+ }
+ }],
+
+ "background_level": "medium",
+ "background":"ecliptic",
+ "calculation":{
+ "effects": {
+ "background": true,
+ "ipc": true,
+ "saturation": true
+ },
+ "noise": {
+ "crs": true,
+ "darkcurrent": true,
+ "ffnoise": false,
+ "readnoise": true,
+ "rn_correlation": true
+ }
+ },
+ "configuration":{
+ "instrument": {
+ "instrument": "nircam",
+ "mode": "sw_tsgrism",
+ "filter": "f150w2",
+ "aperture": "dhs0spec8",
+ "disperser": "dhs0"
+ },
+ "detector": {
+ "readout_pattern":"rapid",
+ "subarray": "sub256stripe4_dhs",
+ "ngroup": "optimize",
+ "nint": 1,
+ "nexp": 10
+ }
+ },
+ "strategy": {
+ "method": "specapphot",
+ "background_subtraction":true,
+ "aperture_size": 0.7,
+ "sky_annulus": [0.8,1.6],
+ "target_xy": [0.0, 0.0],
+ "reference_wavelength":null,
+ "units":"arcsec"
+ }
+}
diff --git a/pandexo/engine/reference/nircam_input.json b/pandexo/engine/reference/nircam_input.json
index 2301cbc..a541dd0 100755
--- a/pandexo/engine/reference/nircam_input.json
+++ b/pandexo/engine/reference/nircam_input.json
@@ -47,7 +47,7 @@
"configuration":{
"instrument": {
"instrument": "nircam",
- "mode": "ssgrism",
+ "mode": "lw_tsgrism",
"filter": "f444w",
"aperture": "lw",
"disperser": "grismr"
@@ -55,7 +55,6 @@
"detector": {
"readout_pattern":"rapid",
"subarray": "subgrism64",
- "readmode": "rapid",
"ngroup": "optimize",
"nint": 1,
"nexp": 10
diff --git a/pandexo/engine/reference/wfc3_input.json b/pandexo/engine/reference/wfc3_input.json
index 4e2e490..c84ce21 100755
--- a/pandexo/engine/reference/wfc3_input.json
+++ b/pandexo/engine/reference/wfc3_input.json
@@ -17,7 +17,8 @@
"scanDirection": "Forward or Round Trip",
"schedulability":"30 or 100",
"windowSize": 20,
- "useFirstOrbit":false
+ "useFirstOrbit":false,
+ "calculateRamp":false
}
}
diff --git a/pandexo/engine/run_online.py b/pandexo/engine/run_online.py
index 8fc58f4..85401e1 100644
--- a/pandexo/engine/run_online.py
+++ b/pandexo/engine/run_online.py
@@ -517,6 +517,19 @@ def post(self):
pandata["configuration"]["instrument"]["filter"] = self.get_argument("nircammode")
pandata["configuration"]["detector"]["subarray"] = self.get_argument("nircamsubarray")
+ if instrument == "nircamdhs":
+ with open(os.path.join(os.path.dirname(__file__), "reference", "nircam_dhs_input.json")) as data_file:
+ pandata = json.load(data_file)
+ #sw or lw for display?
+ sw_or_lw = self.get_argument("nircammode")
+ filter_to_sim = f'nircam{sw_or_lw}'
+ if 'sw' in filter_to_sim:
+ pair_filter='nircamlw'
+ else:
+ pair_filter='nircamsw'
+ pandata["configuration"]["instrument"]["filter"] = self.get_argument(filter_to_sim)
+ pandata["configuration"]["instrument"]["pandexofilterpair"] = self.get_argument(pair_filter)
+ pandata["configuration"]["detector"]["subarray"] = self.get_argument("nircamsubarray")
if instrument == "niriss":
with open(os.path.join(os.path.dirname(__file__), "reference", "niriss_input.json")) as data_file:
pandata = json.load(data_file)
@@ -526,7 +539,7 @@ def post(self):
if pandata["configuration"]["detector"]["subarray"] == "substrip256":
pandata['strategy']['order'] = int(self.get_argument('nirissorders'))
- pandata['configuration']['instrument']['instrument'] = instrument
+ pandata['configuration']['instrument']['instrument'] = instrument.replace('dhs','')
# write in optimal groups or set a number
try:
diff --git a/pandexo/engine/templates/new.html b/pandexo/engine/templates/new.html
index 14121b3..a66ee75 100755
--- a/pandexo/engine/templates/new.html
+++ b/pandexo/engine/templates/new.html
@@ -313,7 +313,8 @@ JWST Instrument Modes
MIRI Low Resolution Spectroscopy
NIRSpec Bright Object Time Series
- NIRCam Grism Time Series
+ NIRCam Long Wave Only Grism Time Series
+ NIRCam Long Wave & Short Wave Grism Time Series
NIRISS Single Object Slitless Spectroscopy
@@ -376,6 +377,47 @@ JWST Instrument Modes
+
+
+
+
+ F070W, ~0.6-0.8 um
+ F090W, ~0.8-1 um
+ F115W, ~1-1.2 um
+ F150W2, ~1-1.9 um
+ F200W, ~1.7-2 um
+
+
+
+
+
+ F322W2, 2.7-4 um
+ F444W, 4-5 um
+
+
+
+
+
+ SUB40S1_2-SPECTRA (tframe=0.21)
+ SUB80S2_4-SPECTRA (tframe=0.42)
+ SUB160S4_8-SPECTRA (tframe=0.84)
+ SUB256S4_8-SPECTRA (tframe=1.3)
+
+
+
+
+
+ Short wave
+ Long wave
+
+
+
+
1) There are separate calculations for the short and long wavelength channels even though these observations occur simultaneously. Take caution to use the same Instrument Setup and Detector Setup in both the SW Grism Time Series and LW Grism Time Series calculations for a given target to correctly evaluate expected SNR.
+
2) SW Filter wavelength ranges cited in the dropdown menu are only for guidance. The exact numbers dependt on the choice of LW filter (see JDOX Table 3)
+
+
+
+
@@ -556,7 +598,7 @@ JWST Instrument Modes
/* Instrument Selection */
$("#instrument").change(function () {
$("#instrument-mode-section").removeClass("hidden");
- $("#MIRI, #NIRSpec, #NIRISS, #NIRCam").addClass("hidden");
+ $("#MIRI, #NIRSpec, #NIRISS, #NIRCam, #NIRCamDHS").addClass("hidden");
var selopt = $("#instrument").val();
switch (selopt) {
case "MIRI":
@@ -571,6 +613,9 @@ JWST Instrument Modes
case "NIRCam":
$("#NIRCam").removeClass("hidden");
break;
+ case "NIRCamDHS":
+ $("#NIRCamDHS").removeClass("hidden");
+ break;
}
});
});
diff --git a/pandexo/engine/utils/plotters.py b/pandexo/engine/utils/plotters.py
index 26b9628..a29de52 100755
--- a/pandexo/engine/utils/plotters.py
+++ b/pandexo/engine/utils/plotters.py
@@ -215,9 +215,10 @@ def create_component_jwst(result_dict):
raw = result_dict['RawData']
# Flux 1d
- x, y = raw['wave'], raw['e_rate_out']*result_dict['timing']['Seconds per Frame']*(timing["APT: Num Groups per Integration"]-1)
- x = x[~np.isnan(y)]
- y = y[~np.isnan(y)]
+ #x, y = raw['wave'], raw['e_rate_out']*result_dict['timing']['Seconds per Frame']*(timing["APT: Num Groups per Integration"]+timing["Zero Frame Efficiency Loss"])
+ #x = x[~np.isnan(y)]
+ #y = y[~np.isnan(y)]
+ x,y = raw['wave'],raw['electron_per_int']
plot_flux_1d1 = Figure(tools=TOOLS,
x_axis_label='Wavelength [microns]',
@@ -238,7 +239,7 @@ def create_component_jwst(result_dict):
#tab2 = Panel(child=plot_bg_1d1, title="Background Flux")
# SNR
- y = np.sqrt(y) #this is computing the SNR (sqrt of photons in a single integration)
+ x,y = raw['snr_int'][0],raw['snr_int'][1] #this is computing the SNR (sqrt of photons in a single integration)
plot_snr_1d1 = Figure(tools=TOOLS,