def compute_full_sim(dictinput): """Top level function to set up exoplanet obs. for JW Function to set up explanet observations for JWST only and compute simulated spectrum. It uses STScI's Pandeia to compute instrument throughputs and WebbPSF to compute PSFs. Parameters ---------- dictinput : dict dictionary containing instrument parameters and exoplanet specific parameters. {"pandeia_input":dict1, "pandexo_input":dict1} Returns ------- dict large dictionary with 1d, 2d simualtions, timing info, instrument info, warnings Examples -------- >>> from pandexo.engine.jwst import compute_full_sim >>> from pandexo.engine.justplotit import jwst_1d_spec >>> a = compute_full_sim({"pandeia_input": pandeiadict, "pandexo_input":exodict}) >>> jwst_1d_spec(a) .. image:: 1d_spec.png Notes ----- It is much easier to run simulations through either **run_online** or **justdoit**. **justdoit** contains functions to create input dictionaries and **run_online** contains web forms to create input dictionaries. See Also -------- pandexo.engine.justdoit.run_pandexo : Best function for running pandexo runs pandexo.engine.run_online : Allows running functions through online interface """ pandeia_input = dictinput['pandeia_input'] pandexo_input = dictinput['pandexo_input'] #define the calculation we'll be doing if pandexo_input['planet']['w_unit'] == 'sec': calculation = 'phase_spec' else: calculation = pandexo_input['calculation'].lower() #which instrument instrument = pandeia_input['configuration']['instrument']['instrument'] conf = pandeia_input['configuration'] #if optimize is in the ngroups section, this will throw an error #so create temp conf with 2 groups try: i = InstrumentFactory(config=conf) det_pars = i.get_detector_pars() exp_pars = i.get_exposure_pars() except: conf_temp = deepcopy(conf) conf_temp['detector']['ngroup'] = 2 i = InstrumentFactory(config=conf_temp) det_pars = i.get_detector_pars() exp_pars = i.get_exposure_pars() #detector parameters fullwell = det_pars['fullwell'] rn = det_pars['rn'] sat_level = pandexo_input['observation']['sat_level'] / 100.0 * fullwell mingroups = det_pars['mingroups'] #exposure parameters tframe = exp_pars.tframe nframe = exp_pars.nframe nskip = exp_pars.nskip #parameteres needed from exo_input mag = pandexo_input['star']['mag'] noccultations = pandexo_input['observation']['noccultations'] R = pandexo_input['observation']['R'] #amount of exposure time out-of-occultation, as a fraction of in-occ time expfact_out = pandexo_input['observation']['fraction'] noise_floor = pandexo_input['observation']['noise_floor'] #get stellar spectrum and in transit spec star_spec = create.outTrans(pandexo_input['star']) both_spec = create.bothTrans(star_spec, pandexo_input['planet']) out_spectrum = np.array([both_spec['wave'], both_spec['flux_out_trans']]) #get transit duration from phase curve or from input if calculation == 'phase_spec': transit_duration = max(both_spec['time']) - min(both_spec['time']) else: transit_duration = pandexo_input['planet']['transit_duration'] #add to pandeia input pandeia_input['scene'][0]['spectrum']['sed']['spectrum'] = out_spectrum if isinstance(pandeia_input["configuration"]["detector"]["ngroup"], (float, int)): m = { "ngroup": pandeia_input["configuration"]["detector"]["ngroup"], "tframe": tframe, "nframe": nframe, "mingroups": mingroups, "nskip": nskip } else: #run pandeia once to determine max exposure time per int and get exposure params print("Optimization Reqested: Computing Duty Cycle") m = { "maxexptime_per_int": compute_maxexptime_per_int(pandeia_input, sat_level), "tframe": tframe, "nframe": nframe, "mingroups": mingroups, "nskip": nskip } print("Finished Duty Cycle Calc") #calculate all timing info timing, flags = compute_timing(m, transit_duration, expfact_out, noccultations) #Simulate out trans and in transit print("Starting Out of Transit Simulation") out = perform_out(pandeia_input, pandexo_input, timing, both_spec) #extract extraction area before dict conversion extraction_area = out.extraction_area out = out.as_dict() out.pop('3d') print("End out of Transit") #this kind of redundant going to compute inn from out instead #keep perform_in but change inputs to (out, timing, both_spec) print("Starting In Transit Simulation") inn = perform_in(pandeia_input, pandexo_input, timing, both_spec, out, calculation) print("End In Transit") #compute warning flags for timing info warnings = add_warnings(out, timing, sat_level, flags, instrument) compNoise = ExtractSpec(inn, out, rn, extraction_area, timing) #slope method is pandeia's pure noise calculation (taken from SNR) #contains correlated noise, RN, dark current, sky, #uses MULTIACCUM formula so we deviated from this. #could eventually come back to this if Pandeia adopts First-Last formula if calculation == 'slope method': #Extract relevant info from pandeia output (1d curves and wavelength) #extracted flux in units of electron/s w = out['1d']['extracted_flux'][0] result = compNoise.run_slope_method() #derives noise from 2d postage stamps. Doing this results in a higher #1d flux rate than the Pandeia gets from extracting its own. #this should be used to benchmark Pandeia's 1d extraction elif calculation == '2d extract': w = out['1d']['extracted_flux'][0] result = compNoise.run_2d_extract() #this is the noise calculation that PandExo uses online. It derives #its own calculation of readnoise and does not use MULTIACUMM #noise formula elif calculation == 'fml': w = out['1d']['extracted_flux'][0] result = compNoise.run_f_minus_l() elif calculation == 'phase_spec': result = compNoise.run_phase_spec() w = result['time'] else: result = None raise Exception('WARNING: Calculation method not found.') varin = result['var_in_1d'] varout = result['var_out_1d'] extracted_flux_out = result['photon_out_1d'] extracted_flux_inn = result['photon_in_1d'] #bin the data according to user input if R != None: wbin = bin_wave_to_R(w, R) photon_out_bin = uniform_tophat_sum(wbin, w, extracted_flux_out) photon_in_bin = uniform_tophat_sum(wbin, w, extracted_flux_inn) var_in_bin = uniform_tophat_sum(wbin, w, varin) var_out_bin = uniform_tophat_sum(wbin, w, varout) else: wbin = w photon_out_bin = extracted_flux_out photon_in_bin = extracted_flux_inn var_in_bin = varin var_out_bin = varout #calculate total variance var_tot = var_in_bin + var_out_bin error = np.sqrt(var_tot) #calculate error on spectrum error_spec = error / photon_out_bin #Add in user specified noise floor error_spec_nfloor = add_noise_floor(noise_floor, wbin, error_spec) #add in random noise for the simulated spectrum rand_noise = np.sqrt( (var_in_bin + var_out_bin)) * (np.random.randn(len(wbin))) raw_spec = (photon_out_bin - photon_in_bin) / photon_out_bin sim_spec = (photon_out_bin - photon_in_bin + rand_noise) / photon_out_bin #if secondary tranist, multiply spectra by -1 if pandexo_input['planet']['f_unit'] == 'fp/f*': sim_spec = -1.0 * sim_spec raw_spec = -1.0 * raw_spec #package processed data binned = { 'wave': wbin, 'spectrum': raw_spec, 'spectrum_w_rand': sim_spec, 'error_w_floor': error_spec_nfloor } unbinned = { 'flux_out': extracted_flux_out, 'flux_in': extracted_flux_inn, 'var_in': varin, 'var_out': varout, 'wave': w, 'error_no_floor': np.sqrt(varin + varout) / extracted_flux_out } result_dict = as_dict(out, both_spec, binned, timing, mag, sat_level, warnings, pandexo_input['planet']['f_unit'], unbinned, calculation) return result_dict
def compute_full_sim(dictinput): """Top level function to set up exoplanet obs. for JW Function to set up explanet observations for JWST only and compute simulated spectrum. It uses STScI's Pandeia to compute instrument throughputs and WebbPSF to compute PSFs. Parameters ---------- dictinput : dict dictionary containing instrument parameters and exoplanet specific parameters. {"pandeia_input":dict1, "pandexo_input":dict1} Returns ------- dict large dictionary with 1d, 2d simualtions, timing info, instrument info, warnings Examples -------- >>> from .pandexo.engine.jwst import compute_full_sim >>> from .pandexo.engine.justplotit import jwst_1d_spec >>> a = compute_full_sim({"pandeia_input": pandeiadict, "pandexo_input":exodict}) >>> jwst_1d_spec(a) .. image:: 1d_spec.png Notes ----- It is much easier to run simulations through either **run_online** or **justdoit**. **justdoit** contains functions to create input dictionaries and **run_online** contains web forms to create input dictionaries. See Also -------- pandexo.engine.justdoit.run_pandexo : Best function for running pandexo runs pandexo.engine.run_online : Allows running functions through online interface """ pandeia_input = dictinput['pandeia_input'] pandexo_input = dictinput['pandexo_input'] #define the calculation we'll be doing if pandexo_input['planet']['w_unit'] == 'sec': calculation = 'phase_spec' else: calculation = pandexo_input['calculation'].lower() #which instrument instrument = pandeia_input['configuration']['instrument']['instrument'] conf = pandeia_input['configuration'] #if optimize is in the ngroups section, this will throw an error #so create temp conf with 2 groups try: i = InstrumentFactory(config=conf) det_pars = i.get_detector_pars() exp_pars = i.get_exposure_pars() except: conf_temp = deepcopy(conf) conf_temp['detector']['ngroup'] = 2 i = InstrumentFactory(config=conf_temp) det_pars = i.get_detector_pars() exp_pars = i.get_exposure_pars() #detector parameters fullwell = det_pars['fullwell'] #from pandeia data rn = det_pars['rn'] sat_unit = pandexo_input['observation']['sat_unit'] if sat_unit =='%': sat_level = pandexo_input['observation']['sat_level']/100.0*fullwell elif sat_unit =='e': sat_level = pandexo_input['observation']['sat_level'] else: raise Exception("Saturation Level Needs Units: % fullwell or Electrons ") mingroups = det_pars['mingroups'] #exposure parameters tframe = exp_pars.tframe nframe = exp_pars.nframe nskip = exp_pars.nskip #parameteres needed from exo_input mag = pandexo_input['star']['mag'] noccultations = pandexo_input['observation']['noccultations'] R = pandexo_input['observation']['R'] noise_floor = pandexo_input['observation']['noise_floor'] #get stellar spectrum and in transit spec star_spec = create.outTrans(pandexo_input['star']) #get rstar if user calling from grid both_spec = create.bothTrans(star_spec, pandexo_input['planet'], star=pandexo_input['star']) out_spectrum = np.array([both_spec['wave'], both_spec['flux_out_trans']]) #get transit duration from phase curve or from input if calculation == 'phase_spec': transit_duration = max(both_spec['time']) - min(both_spec['time']) else: #convert to seconds, then remove quantity and convert back to float transit_duration = float((pandexo_input['planet']['transit_duration']*u.Unit(pandexo_input['planet']['td_unit'])).to(u.second)/u.second) #amount of exposure time out-of-occultation, as a fraction of in-occ time try: expfact_out = pandexo_input['observation']['fraction'] print("WARNING: key input fraction has been replaced with new 'baseline option'. See notebook example") pandexo_input['observation']['baseline'] = pandexo_input['observation']['fraction'] pandexo_input['observation']['baseline_unit'] ='frac' except: if pandexo_input['observation']['baseline_unit'] =='frac': expfact_out = pandexo_input['observation']['baseline'] elif pandexo_input['observation']['baseline_unit'] =='total': expfact_out = transit_duration/( pandexo_input['observation']['baseline'] - transit_duration) elif pandexo_input['observation']['baseline_unit'] =='total_hrs': expfact_out = transit_duration/( pandexo_input['observation']['baseline']*3600.0 - transit_duration) else: raise Exception("Wrong units for baseine: either 'frac' or 'total' or 'total_hrs' accepted") #add to pandeia input pandeia_input['scene'][0]['spectrum']['sed']['spectrum'] = out_spectrum if isinstance(pandeia_input["configuration"]["detector"]["ngroup"], (float,int)): m = {"ngroup":pandeia_input["configuration"]["detector"]["ngroup"], "tframe":tframe, "nframe":nframe,"mingroups":mingroups,"nskip":nskip} else: #run pandeia once to determine max exposure time per int and get exposure params print("Optimization Reqested: Computing Duty Cycle") m = {"maxexptime_per_int":compute_maxexptime_per_int(pandeia_input, sat_level) , "tframe":tframe,"nframe":nframe,"mingroups":mingroups,"nskip":nskip} print("Finished Duty Cycle Calc") #calculate all timing info timing, flags = compute_timing(m,transit_duration,expfact_out,noccultations) #Simulate out trans and in transit print("Starting Out of Transit Simulation") out = perform_out(pandeia_input, pandexo_input,timing, both_spec) #extract extraction area before dict conversion extraction_area = out.extraction_area out = out.as_dict() out.pop('3d') print("End out of Transit") #Remove effects of Quantum Yield from shot noise out = remove_QY(out, instrument) #this kind of redundant going to compute inn from out instead #keep perform_in but change inputs to (out, timing, both_spec) print("Starting In Transit Simulation") inn = perform_in(pandeia_input, pandexo_input,timing, both_spec, out, calculation) print("End In Transit") #compute warning flags for timing info warnings = add_warnings(out, timing, sat_level/fullwell, flags, instrument) compNoise = ExtractSpec(inn, out, rn, extraction_area, timing) #slope method is pandeia's pure noise calculation (taken from SNR) #contains correlated noise, RN, dark current, sky, #uses MULTIACCUM formula so we deviated from this. #could eventually come back to this if Pandeia adopts First-Last formula if calculation == 'slope method': #Extract relevant info from pandeia output (1d curves and wavelength) #extracted flux in units of electron/s w = out['1d']['extracted_flux'][0] result = compNoise.run_slope_method() #derives noise from 2d postage stamps. Doing this results in a higher #1d flux rate than the Pandeia gets from extracting its own. #this should be used to benchmark Pandeia's 1d extraction elif calculation == '2d extract': w = out['1d']['extracted_flux'][0] result = compNoise.run_2d_extract() #this is the noise calculation that PandExo uses online. It derives #its own calculation of readnoise and does not use MULTIACUMM #noise formula elif calculation == 'fml': w = out['1d']['extracted_flux'][0] result = compNoise.run_f_minus_l() elif calculation == 'phase_spec': result = compNoise.run_phase_spec() w = result['time'] else: result = None raise Exception('WARNING: Calculation method not found.') varin = result['var_in_1d'] varout = result['var_out_1d'] extracted_flux_out = result['photon_out_1d'] extracted_flux_inn = result['photon_in_1d'] #bin the data according to user input if R != None: wbin = bin_wave_to_R(w, R) photon_out_bin = uniform_tophat_sum(wbin, w,extracted_flux_out) wbin = wbin[photon_out_bin > 0 ] photon_in_bin = uniform_tophat_sum(wbin,w, extracted_flux_inn) photon_in_bin = photon_in_bin[photon_out_bin > 0 ] var_in_bin = uniform_tophat_sum(wbin, w,varin) var_in_bin = var_in_bin[photon_out_bin > 0 ] var_out_bin = uniform_tophat_sum(wbin,w, varout) var_out_bin = var_out_bin[photon_out_bin > 0 ] photon_out_bin = photon_out_bin else: wbin = w photon_out_bin = extracted_flux_out wbin = wbin[photon_out_bin>0] photon_in_bin = extracted_flux_inn photon_in_bin = photon_in_bin[photon_out_bin>0] var_in_bin = varin var_in_bin = var_in_bin[photon_out_bin>0] var_out_bin = varout var_out_bin = var_out_bin[photon_out_bin>0] photon_out_bin = photon_out_bin[photon_out_bin>0] if calculation == 'phase_spec': to = (timing["APT: Num Groups per Integration"]-1)*tframe ti = (timing["APT: Num Groups per Integration"]-1)*tframe else: #otherwise error propagation and account for different #times in transit and out to = result['on_source_out'] ti = result['on_source_in'] 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) #factor in occultations to noise nocc = timing['Number of Transits'] error_spec = error_spec / np.sqrt(nocc) #Add in user specified noise floor error_spec_nfloor = add_noise_floor(noise_floor, wbin, error_spec) #add in random noise for the simulated spectrum np.random.seed() rand_noise= error_spec_nfloor*(np.random.randn(len(wbin))) raw_spec = (photon_out_bin/to-photon_in_bin/ti)/(photon_out_bin/to) sim_spec = raw_spec + rand_noise #if secondary tranist, multiply spectra by -1 if pandexo_input['planet']['f_unit'] == 'fp/f*': sim_spec = -1.0*sim_spec raw_spec = -1.0*raw_spec #package processed data finalspec = {'wave':wbin, 'spectrum': raw_spec, 'spectrum_w_rand':sim_spec, 'error_w_floor':error_spec_nfloor} rawstuff = { 'electrons_out':photon_out_bin*nocc, 'electrons_in':photon_in_bin*nocc, 'var_in':var_in_bin*nocc, 'var_out':var_out_bin*nocc, 'e_rate_out':photon_out_bin/to, 'e_rate_in':photon_out_bin/ti, 'wave':wbin, 'error_no_floor':error_spec, 'rn[out,in]':result['rn[out,in]'], 'bkg[out,in]':result['bkg[out,in]'] } result_dict = as_dict(out,both_spec ,finalspec, timing, mag, sat_level, warnings, pandexo_input['planet']['f_unit'], rawstuff,calculation) return result_dict
def compute_full_sim(dictinput): """Top level function to set up exoplanet obs. for JW Function to set up explanet observations for JWST only and compute simulated spectrum. It uses STScI's Pandeia to compute instrument throughputs and WebbPSF to compute PSFs. Parameters ---------- dictinput : dict dictionary containing instrument parameters and exoplanet specific parameters. {"pandeia_input":dict1, "pandexo_input":dict1} Returns ------- dict large dictionary with 1d, 2d simualtions, timing info, instrument info, warnings Examples -------- >>> from pandexo.engine.jwst import compute_full_sim >>> from pandexo.engine.justplotit import jwst_1d_spec >>> a = compute_full_sim({"pandeia_input": pandeiadict, "pandexo_input":exodict}) >>> jwst_1d_spec(a) .. image:: 1d_spec.png Notes ----- It is much easier to run simulations through either **run_online** or **justdoit**. **justdoit** contains functions to create input dictionaries and **run_online** contains web forms to create input dictionaries. See Also -------- pandexo.engine.justdoit.run_pandexo : Best function for running pandexo runs pandexo.engine.run_online : Allows running functions through online interface """ pandeia_input = dictinput['pandeia_input'] pandexo_input = dictinput['pandexo_input'] #define the calculation we'll be doing if pandexo_input['planet']['w_unit'] == 'sec': calculation = 'phase_spec' else: calculation = pandexo_input['calculation'].lower() #which instrument instrument = pandeia_input['configuration']['instrument']['instrument'] conf = pandeia_input['configuration'] #if optimize is in the ngroups section, this will throw an error #so create temp conf with 2 groups try: i = InstrumentFactory(config=conf) det_pars = i.get_detector_pars() exp_pars = i.get_exposure_pars() except: conf_temp = deepcopy(conf) conf_temp['detector']['ngroup'] = 2 i = InstrumentFactory(config=conf_temp) det_pars = i.get_detector_pars() exp_pars = i.get_exposure_pars() #detector parameters fullwell = det_pars['fullwell'] rn = det_pars['rn'] sat_level = pandexo_input['observation']['sat_level']/100.0*fullwell mingroups = det_pars['mingroups'] #exposure parameters tframe = exp_pars.tframe nframe = exp_pars.nframe nskip = exp_pars.nskip #parameteres needed from exo_input mag = pandexo_input['star']['mag'] noccultations = pandexo_input['observation']['noccultations'] R = pandexo_input['observation']['R'] #amount of exposure time out-of-occultation, as a fraction of in-occ time expfact_out = pandexo_input['observation']['fraction'] noise_floor = pandexo_input['observation']['noise_floor'] #get stellar spectrum and in transit spec star_spec = create.outTrans(pandexo_input['star']) both_spec = create.bothTrans(star_spec, pandexo_input['planet']) out_spectrum = np.array([both_spec['wave'], both_spec['flux_out_trans']]) #get transit duration from phase curve or from input if calculation == 'phase_spec': transit_duration = max(both_spec['time']) - min(both_spec['time']) else: transit_duration = pandexo_input['planet']['transit_duration'] #add to pandeia input pandeia_input['scene'][0]['spectrum']['sed']['spectrum'] = out_spectrum if isinstance(pandeia_input["configuration"]["detector"]["ngroup"], (float,int)): m = {"ngroup":pandeia_input["configuration"]["detector"]["ngroup"], "tframe":tframe, "nframe":nframe,"mingroups":mingroups,"nskip":nskip} else: #run pandeia once to determine max exposure time per int and get exposure params print("Optimization Reqested: Computing Duty Cycle") m = {"maxexptime_per_int":compute_maxexptime_per_int(pandeia_input, sat_level) , "tframe":tframe,"nframe":nframe,"mingroups":mingroups,"nskip":nskip} print("Finished Duty Cycle Calc") #calculate all timing info timing, flags = compute_timing(m,transit_duration,expfact_out,noccultations) #Simulate out trans and in transit print("Starting Out of Transit Simulation") out = perform_out(pandeia_input, pandexo_input,timing, both_spec) #extract extraction area before dict conversion extraction_area = out.extraction_area out = out.as_dict() out.pop('3d') print("End out of Transit") #Remove effects of Quantum Yield from shot noise out = remove_QY(out, instrument) #this kind of redundant going to compute inn from out instead #keep perform_in but change inputs to (out, timing, both_spec) print("Starting In Transit Simulation") inn = perform_in(pandeia_input, pandexo_input,timing, both_spec, out, calculation) print("End In Transit") #compute warning flags for timing info warnings = add_warnings(out, timing, sat_level/fullwell, flags, instrument) compNoise = ExtractSpec(inn, out, rn, extraction_area, timing) #slope method is pandeia's pure noise calculation (taken from SNR) #contains correlated noise, RN, dark current, sky, #uses MULTIACCUM formula so we deviated from this. #could eventually come back to this if Pandeia adopts First-Last formula if calculation == 'slope method': #Extract relevant info from pandeia output (1d curves and wavelength) #extracted flux in units of electron/s w = out['1d']['extracted_flux'][0] result = compNoise.run_slope_method() #derives noise from 2d postage stamps. Doing this results in a higher #1d flux rate than the Pandeia gets from extracting its own. #this should be used to benchmark Pandeia's 1d extraction elif calculation == '2d extract': w = out['1d']['extracted_flux'][0] result = compNoise.run_2d_extract() #this is the noise calculation that PandExo uses online. It derives #its own calculation of readnoise and does not use MULTIACUMM #noise formula elif calculation == 'fml': w = out['1d']['extracted_flux'][0] result = compNoise.run_f_minus_l() elif calculation == 'phase_spec': result = compNoise.run_phase_spec() w = result['time'] else: result = None raise Exception('WARNING: Calculation method not found.') varin = result['var_in_1d'] varout = result['var_out_1d'] extracted_flux_out = result['photon_out_1d'] extracted_flux_inn = result['photon_in_1d'] #bin the data according to user input if R != None: wbin = bin_wave_to_R(w, R) photon_out_bin = uniform_tophat_sum(wbin, w,extracted_flux_out) wbin = wbin[photon_out_bin > 0 ] photon_in_bin = uniform_tophat_sum(wbin,w, extracted_flux_inn) photon_in_bin = photon_in_bin[photon_out_bin > 0 ] var_in_bin = uniform_tophat_sum(wbin, w,varin) var_in_bin = var_in_bin[photon_out_bin > 0 ] var_out_bin = uniform_tophat_sum(wbin,w, varout) var_out_bin = var_out_bin[photon_out_bin > 0 ] photon_out_bin = photon_out_bin else: wbin = w photon_out_bin = extracted_flux_out wbin = wbin[photon_out_bin>0] photon_in_bin = extracted_flux_inn photon_in_bin = photon_in_bin[photon_out_bin>0] var_in_bin = varin var_in_bin = var_in_bin[photon_out_bin>0] var_out_bin = varout var_out_bin = var_out_bin[photon_out_bin>0] photon_out_bin = photon_out_bin[photon_out_bin>0] if calculation == 'phase_spec': to = timing["APT: Num Groups per Integration"]*tframe ti = timing["APT: Num Groups per Integration"]*tframe else: #otherwise error propagation and account for different #times in transit and out to = result['on_source_out'] ti = result['on_source_in'] 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) #factor in occultations to noise nocc = timing['Number of Transits'] error_spec = error_spec / np.sqrt(nocc) #Add in user specified noise floor error_spec_nfloor = add_noise_floor(noise_floor, wbin, error_spec) #add in random noise for the simulated spectrum rand_noise= error_spec_nfloor*(np.random.randn(len(wbin))) raw_spec = (photon_out_bin/to-photon_in_bin/ti)/(photon_out_bin/to) sim_spec = raw_spec + rand_noise #if secondary tranist, multiply spectra by -1 if pandexo_input['planet']['f_unit'] == 'fp/f*': sim_spec = -1.0*sim_spec raw_spec = -1.0*raw_spec #package processed data finalspec = {'wave':wbin, 'spectrum': raw_spec, 'spectrum_w_rand':sim_spec, 'error_w_floor':error_spec_nfloor} rawstuff = { 'electrons_out':photon_out_bin*nocc, 'electrons_in':photon_in_bin*nocc, 'var_in':varin*nocc, 'var_out':varout*nocc, 'e_rate_out':photon_out_bin/to, 'e_rate_in':photon_out_bin/ti, 'wave':w, 'error_no_floor':error_spec, 'rn[out,in]':result['rn[out,in]'], 'bkg[out,in]':result['bkg[out,in]'] } result_dict = as_dict(out,both_spec ,finalspec, timing, mag, sat_level, warnings, pandexo_input['planet']['f_unit'], rawstuff,calculation) return result_dict