def pandeia_instrument(self): if hasattr(self, "_instrument"): return self._instrument from pandeia.engine.calc_utils import build_default_calc from pandeia.engine.instrument_factory import InstrumentFactory translate_instrument = { 'wfi': 'wfirstimager', 'nircamlong': 'nircam', 'nircamshort': 'nircam', 'miri': 'miri' } conf = build_default_calc( self.TELESCOPE.lower(), translate_instrument.get(self.INSTRUMENT.lower(), self.INSTRUMENT.lower()), self.MODE)['configuration'] conf['instrument']['filter'] = self.filter.lower() self.logger.info("Creating Instrument with Configuration {}".format( conf['instrument'])) self._instrument = InstrumentFactory(config=conf) return self._instrument
def run_calc(self, b): c = build_default_calc("wfirst", "wfirstimager", "imaging") c['configuration']['detector']['nexp'] = self.nexps.value c['configuration']['detector']['ngroup'] = self.ngroups.value c['configuration']['detector']['nint'] = self.nints.value c['configuration']['detector']['readmode'] = self.readmode.value c['configuration']['detector']['subarray'] = self.subarray.value c['configuration']['instrument']['filter'] = self.filt.value src = c['scene'][0] if self.src_select.value == "extended": src['shape']['geometry'] = 'sersic' a = self.ext_scale.value e = self.ellip.value b = (1.0 - e) * a s_idx = self.sersic_idx[self.sersic.value] # if gaussian, convert a/b to sigma if s_idx == 0.5: a *= np.sqrt(2.0) b *= np.sqrt(2.0) src['shape']['major'] = a src['shape']['minor'] = b src['shape']['sersic_index'] = s_idx src['position']['orientation'] = self.posang.value src['spectrum']['redshift'] = self.redshift.value src['spectrum']['normalization']['norm_flux'] = self.flux.value src['spectrum']['normalization']['norm_fluxunit'] = self.units.value src['spectrum']['normalization']['norm_wave'] = self.wave.value sed = self.sed_select.value if sed == "power-law": src['spectrum']['sed']['sed_type'] = "powerlaw" src['spectrum']['sed']['index'] = self.pl_index.value if sed == "blackbody": src['spectrum']['sed']['sed_type'] = "blackbody" src['spectrum']['sed']['temp'] = self.bb_temp.value if sed == "star": src['spectrum']['sed']['sed_type'] = "phoenix" src['spectrum']['sed']['key'] = self.star_config[self.stars.value] if sed == "extragalactic": src['spectrum']['sed']['sed_type'] = "brown" src['spectrum']['sed']['key'] = self.gal_config[self.galaxies.value] c['strategy']['aperture_size'] = self.ap_size.value ann = [self.ann_inner.value, self.ann_outer.value] c['strategy']['sky_annulus'] = ann self.r = perform_calculation(c, dict_report=True) self.calc_input = c self.plot_form.visible = True self.esn.value = "%.2f" % self.r['scalar']['sn'] self.eflux.value = "%.2f" % self.r['scalar']['flux'] self.etime.value = "%.2f" % self.r['scalar']['on_source_time'] self.tab_form.visible = True self.update_plots()
def target_acq(instrument, both_spec, warning): """Contains functionality to compute optimal TA strategy Takes pandexo normalized flux from create_input and checks for saturation, or if SNR is below the minimum requirement for each. Then adds warnings and 2d displays and target acq info to final output dict Parameters ---------- instrument : str possible options are niriss, nirspec, miri and nircam both_spec : dict output dictionary from **create_input** warning : dict output dictionary from **add_warnings** Retruns ------- """ out_spectrum = np.array([both_spec['wave'], both_spec['flux_out_trans']]) #this automatically builds a default calculation #I got reasonable answers for everything so all you should need to do here is swap out (instrument = 'niriss', 'nirspec','miri' or 'nircam') c = build_default_calc(telescope='jwst', instrument=instrument, mode='target_acq', method='taphot') c['scene'][0]['spectrum']['sed'] = { 'sed_type': 'input', 'spectrum': out_spectrum } c['scene'][0]['spectrum']['normalization']['type'] = 'none' rphot = perform_calculation(c, dict_report=True) #check warnings (pandeia doesn't return values for these warnings, so try will fail if all good) try: warnings['TA Satruated?'] = rphot['warnings']['saturated'] except: warnings['TA Satruated?'] = 'All good' try: warnings['TA SNR Threshold'] = rphot['warnings']['ta_snr_threshold'] except: warnings['TA SNR Threshold'] = 'All good' #build TA dict ta = { 'sn': rphot['scalar']['sn'], 'ngroup': rphot['input']['configuration']['detector']['ngroup'], 'saturation': rphot['2d']['saturation'] }
def run_engine(self): c = build_default_calc("wfirst", "wfirstimager", "imaging") c['configuration']['detector']['nexp'] = self.nexps.value c['configuration']['detector']['ngroup'] = self.ngroups.value c['configuration']['detector']['nint'] = self.nints.value c['configuration']['detector']['readmode'] = self.readmode.value c['configuration']['detector']['subarray'] = self.subarray.value c['configuration']['instrument']['filter'] = self.filt.value src = c['scene'][0] if self.src_select.value == "extended": src['shape']['geometry'] = 'sersic' a = self.ext_scale.value e = self.ellip.value b = (1.0 - e) * a s_idx = self.sersic_idx[self.sersic.value] # if gaussian, convert a/b to sigma if s_idx == 0.5: a *= np.sqrt(2.0) b *= np.sqrt(2.0) src['shape']['major'] = a src['shape']['minor'] = b src['shape']['sersic_index'] = s_idx src['position']['orientation'] = self.posang.value src['spectrum']['redshift'] = self.redshift.value src['spectrum']['normalization']['norm_flux'] = self.flux.value src['spectrum']['normalization']['norm_fluxunit'] = self.units.value src['spectrum']['normalization']['norm_wave'] = self.wave.value sed = self.sed_select.value if sed == "power-law": src['spectrum']['sed']['sed_type'] = "powerlaw" src['spectrum']['sed']['index'] = self.pl_index.value if sed == "blackbody": src['spectrum']['sed']['sed_type'] = "blackbody" src['spectrum']['sed']['temp'] = self.bb_temp.value if sed == "star": src['spectrum']['sed']['sed_type'] = "phoenix" src['spectrum']['sed']['key'] = self.star_config[self.stars.value] if sed == "extragalactic": src['spectrum']['sed']['sed_type'] = "brown" src['spectrum']['sed']['key'] = self.gal_config[self.galaxies.value] c['strategy']['aperture_size'] = self.ap_size.value c['strategy']['sky_annulus'] = self.background_annulus.value self._calculation_result = perform_calculation(c, dict_report=True) self.calculation_input = c
def process_config(raw_config, target_scene, reference_scene): """ Process a variable that might be a file name, full JWST configuration dictionary, or instrument configuration dictionary, along with optional target and reference scenes. """ if isinstance(raw_config, str): # A JSON file. In this case, it should be a full pandeia config dictionary if os.path.isfile(raw_config): config = load_calculation(raw_config) else: error_str = "Error: File {} not found".format( configuration_dict_or_filename) raise FileNotFoundError(error_str) elif isinstance(raw_config, dict) and "configuration" in raw_config: # It's a dictionary. It contains a "configuration" key. Assume full pandeia dictionary. config = deepcopy(raw_config) elif isinstance(raw_config, dict): instrument = raw_config["instrument"]["instrument"] config = build_default_calc(jwst, instrument, "coronagraphy") config['configuration']["instrument"] = deepcopy(raw_config) if target_scene is None: print( "Warning: input configuration had no scene info, and no separate target scene was provided. Using default coronagraphy target scene." ) else: error_str = "Invalid input {}".format(configuration_dict_or_filename) raise ValueError(error_str) if target_scene is not None: if isinstance(target_scene, list): config['scene'] = deepcopy(target_scene) else: config['scene'] = [deepcopy(target_scene)] if reference_scene is not None: if isinstance(reference_scene, list): config['strategy']['psf_subtraction_source'] = deepcopy( reference_scene[0]) else: config['strategy']['psf_subtraction_source'] = deepcopy( reference_scene) return config
'background', 'extinction'): shutil.copytree(join(pandeia_refdata, folder_name), join(destination, folder_name)) # Patch the data package's config file for WFIRST WFI shutil.copy( join(dirname(__file__), 'data_patch', 'wfirstimager_config.json'), join(destination, 'wfirst', 'wfirstimager', 'config.json')) log("New data package in", destination) return destination if __name__ == "__main__": # Make package data_dir = make_data_package(log=print, overwrite=True) # Test package os.environ['pandeia_refdata'] = data_dir from pandeia.engine.perform_calculation import perform_calculation from pandeia.engine.calc_utils import build_default_calc calc = build_default_calc("wfirst", "wfirstimager", "imaging") result = perform_calculation(calc, dict_report=True) print("Successfully performed the default calculation for wfirstimager") if sys.version_info > (3, 2): archive_name = shutil.make_archive('pandeia_wfirst_data', 'gztar', root_dir=dirname(data_dir), base_dir=basename(data_dir)) print("Compressed WFIRST Pandeia data into {}".format(archive_name))
def sn_user_spec(inputs, disperser = 'prism', filt = 'clear', ngroup = 19, nint = 2, nexp = 36): wl = inputs['wl'] #in microns spec = inputs['spec'] #in mJy xoff = inputs['xoff'] yoff = inputs['yoff'] configuration=build_default_calc('jwst','nirspec','msa') configuration['configuration']['instrument']['disperser']=disperser configuration['configuration']['instrument']['filter']=filt #E - I *think* shutter location is just so that the detector gap is placed in the correct place configuration['configuration']['instrument']['shutter_location']='q3_345_20'#'q4_345_20' #exposure specifications from DEEP APT file configuration['configuration']['detector']['ngroup']=ngroup configuration['configuration']['detector']['nint']=nint #PRISM configuration['configuration']['detector']['nexp']=nexp configuration['configuration']['detector']['readmode']='nrsirs2' configuration['strategy']['dithers'][0]['on_source'] = inputs['onSource'] configuration['configuration']['instrument']['slitlet_shape'] = inputs['slitletShape'] #default configuration['configuration'] has 1x3 shutter config scene = {} if (inputs['re_circ'] > 0): sersic=inputs['sersic_n'] re = inputs['re_maj'] ellip=1.-inputs['axis_ratio'] pa=inputs['position_angle'] major_axis = re minor_axis = re*inputs['axis_ratio'] #pandeia used to use scale lengths, but now is fine with half-light radii scene['shape']={'geometry':'sersic','major': major_axis,'minor':minor_axis,'sersic_index':sersic} # #pandiea wants scale lengths not half-light radii # major_axis,minor_axis=majorminor(sersic,rc,ellip) # scene['position'] = {'x_offset':xoff, 'y_offset': yoff, 'orientation': pa, 'position_parameters':['x_offset','y_offset','orientation']} # scene['shape']={'geometry':'sersic','major': major_axis,'minor':minor_axis,'sersic_index':sersic} # print scene['shape'] else: pa=inputs['position_angle'] #this is the dummy trigger to go for a point source scene['position'] = {'x_offset':xoff, 'y_offset': yoff, 'orientation': pa, 'position_parameters':['x_offset','y_offset','orientation']} scene['shape']={'geometry':'point'} scene['spectrum'] = {} scene['spectrum']['name'] = "continuum_spectrum" scene['spectrum']['redshift'] = 0 #because otherwise it shifts the wavelength array... #it doesn't seem to do anything with the normalization of the #source spectrum, however?! tempIdx = np.where((wl >= filterWlDict[filt]['low']) & (wl <= filterWlDict[filt]['high']))[0] scene['spectrum']['sed'] = {'sed_type': 'input', 'spectrum': [wl[tempIdx], spec[tempIdx]], 'unit':'mJy'} scene['spectrum']['normalization'] = {} scene['spectrum']['normalization'] = {'type': 'none'} if args.addLines: emission_line_array = [] for i,f in enumerate(inputs['flux']): flux=f wave=inputs['wave'][i] if wave > filterWlDict[filt]['low'] and wave < filterWlDict[filt]['high']: emission_line={} emission_line['emission_or_absorption']='emission' emission_line['center']=wave #TODO: check units... emission_line['strength']=flux emission_line['profile']='gaussian' #assume the line is basically unresolved, i.e. 50 km/s (FWHM) emission_line['width']=50.#50. emission_line_array.append(emission_line) scene['spectrum']['lines']=emission_line_array configuration['scene'][0]=scene report=perform_calculation(configuration) return report
def run_calc(self, b): # notify the user that we're calculating. self.computing_notice.layout.display = 'inline' calc_mode = self.mode_select.value.lower() calc_strat = self.strat_select[calc_mode].value.lower() c = build_default_calc("wfirst", "wfirstimager", calc_mode, method=calc_strat) c['configuration']['detector']['nexp'] = self.mode_config[ calc_mode].nexps.value c['configuration']['detector']['ngroup'] = self.mode_config[ calc_mode].ngroups.value c['configuration']['detector']['nint'] = self.mode_config[ calc_mode].nints.value c['configuration']['detector']['readmode'] = self.mode_config[ calc_mode].readmode.value c['configuration']['detector']['subarray'] = self.mode_config[ calc_mode].subarray.value c['configuration']['instrument']['filter'] = self.mode_config[ calc_mode].filt.value c['scene'] = [] for source in self.sources: s = build_default_source( geometry=geom_mapping[source.src_select.value]) if source.src_select.value == "Power": s['shape']['r_core'] = source.r_core.value s['shape']['power_index'] = source.power.value elif source.src_select.value == "Flat": s['shape']['major'] = source.major.value s['shape']['minor'] = source.minor.value s['shape']['norm_method'] = norm_mapping[ source.norm_flat.value] s['position']['orientation'] = source.pos_a.value elif source.src_select.value == "2D Gaussian": s['shape']['major'] = source.major.value s['shape']['minor'] = source.minor.value s['shape']['norm_method'] = norm_mapping[source.norm.value] s['position']['orientation'] = source.pos_a.value elif source.src_select.value == "Sersic (Effective Radius)": s['shape']['major'] = source.major.value s['shape']['minor'] = source.minor.value s['shape']['norm_method'] = norm_mapping[source.norm.value] s['shape']['sersic_index'] = source.sersic.value s['position']['orientation'] = source.pos_a.value elif source.src_select.value == "Sersic (Scale Radius)": s['shape']['major'] = source.major.value s['shape']['minor'] = source.minor.value s['shape']['norm_method'] = norm_mapping[source.norm.value] s['shape']['sersic_index'] = source.sersic.value s['position']['orientation'] = source.pos_a.value else: pass s['position']['x_offset'] = source.pos_x.value s['position']['y_offset'] = source.pos_y.value s['spectrum']['redshift'] = source.redshift.value s['spectrum']['normalization']['norm_flux'] = source.flux.value s['spectrum']['normalization'][ 'norm_fluxunit'] = source.funits.value s['spectrum']['normalization']['norm_wave'] = source.wave.value sed = source.sed_select.value if sed == "power-law": s['spectrum']['sed']['sed_type'] = "powerlaw" s['spectrum']['sed']['index'] = source.pl_index.value if sed == "blackbody": s['spectrum']['sed']['sed_type'] = "blackbody" s['spectrum']['sed']['temp'] = source.bb_temp.value if sed == "phoenix": s['spectrum']['sed']['sed_type'] = "phoenix" s['spectrum']['sed']['key'] = source.phoenix_config[ source.phoenix.value] if sed == "extragalactic": s['spectrum']['sed']['sed_type'] = "brown" s['spectrum']['sed']['key'] = source.gal_config[ source.galaxies.value] if sed == "star": s['spectrum']['sed']['sed_type'] = "hst_calspec" s['spectrum']['sed']['key'] = source.star_config[ source.star.value] c['scene'].append(s) c['strategy']['aperture_size'] = self.strat_config[ calc_strat].ap_size.value ann = [ self.strat_config[calc_strat].ann_inner.value, self.strat_config[calc_strat].ann_outer.value ] c['strategy']['sky_annulus'] = ann if calc_strat == 'specapphot': c['strategy']['reference_wavelength'] = self.strat_config[ calc_strat].reference_wavelength.value self.r = perform_calculation(c, dict_report=True) self.calc_input = c self.esn.value = "%.2f" % self.r['scalar']['sn'] self.eflux.value = "%.2f" % self.r['scalar']['extracted_flux'] self.etime.value = "%.2f" % self.r['scalar']['total_exposure_time'] self.update_plots() # Now set the result form to be shown self.computing_notice.layout.display = 'none' self.result_form.layout.display = 'inline'