def crop_array(opt): fp_whole = opt.fp[1::3,1::3] fp_signal_whole = opt.fp_signal[1::3,1::3] #============================================================================== #1) Calculate the maximum width (y crop) in pixels and apply crop #============================================================================== aa = fp_signal_whole.sum(axis=1).value # sum of profile in x axis jexosim_plot('y crop selection', opt.diagnostics, ydata=aa, marker='ro-', grid=True) bb = np.mean(np.vstack((aa[:5],aa[-5:]))) # average of outer 5 pixels if bb == 0: aa_ = aa[np.argwhere(aa>0).T[0]] bb = aa_.min()/np.e idx_max = np.argmax(aa) print (bb) #find where signal falls below b*npe either side for i in range(int(len(aa)/2)): s = aa[idx_max-i] if s < bb*np.e: # idx0=1+ idx_max-i #+1 so that it starts within the region of > b8npe idx0=idx_max-i #+1 so that it starts within the region of > b8npe break for i in range(int(len(aa)/2)): s = aa[idx_max+i] if s < bb*np.e: # idx1=idx_max+i idx1=1+idx_max+i break #idx0, idx1 #indexs that bound this region idx1 = int(idx1) ; idx0 = int(idx0) print (idx0, idx1) w_crop = idx1- (idx0) jexosim_msg ("width of crop chosen %s"%(w_crop ) , opt.diagnostics) jexosim_plot('y crop selection', opt.diagnostics, xdata=np.arange(idx0, idx1,1), ydata=aa[idx0:idx1], marker='bo-', grid=True) #============================================================================== #2) Calculate the maximum length (x crop) in pixels and apply crop #============================================================================== wav_sol= opt.x_wav_osr[1::3].value # wav sol in whole pixels idx = np.argwhere((wav_sol>=opt.channel.pipeline_params.start_wav.val-0.5)& (wav_sol<=opt.channel.pipeline_params.end_wav.val+0.5)) idxA = idx[0].item() idxB = idx[-1].item() return idx0, idx1, idxA, idxB
def get_psf(opt): if os.path.exists('%s/../archive/PSF/%s_psf_stack.npy' % (opt.__path__, opt.channel.instrument.val)): psf_stack = np.load('%s/../archive/PSF/%s_psf_stack.npy' % (opt.__path__, opt.channel.instrument.val)) psf_stack_wl = 1e6 * np.load( '%s/../archive/PSF/%s_psf_stack_wl.npy' % (opt.__path__, opt.channel.instrument.val)) psf = interpolate.interp1d(psf_stack_wl, psf_stack, axis=2, bounds_error=False, fill_value=0.0, kind='linear')(opt.x_wav_osr.value) psf = np.rot90(psf) psf_type = 'wfe' else: # uses airy if no psf database however this is to be avoided, as pipeline assumes the wfe database psfs. jexosim_msg('PSF files could not be found. Check psf files location.') sys.exit() # psf = jexosim_lib.Psf(opt.x_wav_osr.value, opt.channel.camera.wfno_x.val, opt.channel.camera.wfno_y.val, opt.fp_delta.value, shape='airy') # psf[np.isnan(psf)] =0 # psf_type = 'airy' jexosim_msg("PSF shape %s, %s" % (psf.shape[0], psf.shape[1]), opt.diagnostics) jexosim_plot('psf check', opt.diagnostics, image=True, image_data=psf[..., int(psf.shape[2] / 2)]) sum1 = [] for i in range(psf.shape[2]): sum1.append(psf[..., i].sum()) if psf[..., i].sum() != 0: # psf[...,i] =psf[...,i]/psf[...,i].sum() if np.round(psf[..., i].sum(), 3) != 1.0: jexosim_msg( 'error... check PSF normalisation %s %s' % (psf[..., i].sum(), opt.x_wav_osr[i]), 1) sys.exit() jexosim_plot('test7 - psf sum vs subpixel position (should be 1)', opt.diagnostics, xdata=opt.x_pix_osr, ydata=sum1, marker='bo') return psf, psf_type
def psf_fp_check(opt): # Populate focal plane with monochromatic PSFs j0 = np.arange(opt.fp.shape[1]) - int(opt.psf.shape[1] / 2) j1 = j0 + opt.psf.shape[1] idx = np.where((j0 >= 0) & (j1 < opt.fp.shape[1]))[0] i0 = np.array([opt.fp.shape[0] / 2 - opt.psf.shape[0] / 2 + opt.offs] * len(j1)).astype(np.int) i0 += 1 # variable y position (applies only to NIRISS) if opt.channel.name == 'NIRISS_SOSS_GR700XD': i0 = (opt.y_pos_osr).astype(np.int) i1 = i0 + opt.psf.shape[0] test_fp = np.zeros_like(opt.fp) # SPECIAL CASE: fix if airy psfs used if opt.channel.name == 'NIRISS_SOSS_GR700XD': # fix if airy psfs used if opt.psf_type == 'airy': original_fp = copy.deepcopy(test_fp) if i1.max( ) > test_fp.shape[0]: #psfs will fall outside fp area due to curve original_fp = copy.deepcopy(test_fp) test_fp = np.zeros( (i1.max(), test_fp.shape[1])) # temp increase in fp size for k in idx: # used for getting sat time, and sizing test_fp[i0[k]:i1[k], j0[k]:j1[k]] += opt.psf[..., k] # SPECIAL CASE: fix if airy psfs used if opt.channel.name == 'NIRISS_SOSS_GR700XD': if opt.psf_type == 'airy': # now return fp to original size if i1.max() > original_fp.shape[0]: diff = i1.max() - original_fp.shape[0] test_fp = test_fp[diff:] jexosim_plot('psf fp check', 1, ydata=test_fp.sum(axis=0)) return test_fp
def run(opt): jexosim_msg('channel check0 : %s' % (opt.star.sed.sed.max()), opt.diagnostics) tr_ = np.array([1.] * len(opt.x_wav_osr)) * u.dimensionless_unscaled opt.channel.transmissions.optical_surface = opt.channel.transmissions.optical_surface if isinstance(opt.channel.transmissions.optical_surface, list) else \ [opt.channel.transmissions.optical_surface] for op in opt.channel.transmissions.optical_surface: dtmp = np.loadtxt(op.transmission.replace('__path__', opt.__path__), delimiter=',') tr = Sed(dtmp[:, 0] * u.um, dtmp[:, 1] * u.dimensionless_unscaled) tr.rebin(opt.x_wav_osr) tr_ *= tr.sed opt.channel_transmission = Sed(opt.x_wav_osr, tr_) opt.total_transmission = Sed( opt.channel_transmission.wl, opt.telescope_transmission.sed * opt.channel_transmission.sed) jexosim_lib.sed_propagation(opt.star.sed, opt.channel_transmission) jexosim_lib.sed_propagation(opt.star.sed_it, opt.channel_transmission) # apply QE and convert to electrons dtmp = np.loadtxt(opt.channel.detector_array.qe().replace( '__path__', opt.__path__), delimiter=',') qe = Sed(dtmp[:, 0] * u.um, dtmp[:, 1] * u.dimensionless_unscaled) qe.rebin(opt.x_wav_osr) PCE = Sed(opt.total_transmission.wl, opt.total_transmission.sed * qe.sed) TotTrans = Sed(opt.total_transmission.wl, opt.total_transmission.sed) opt.PCE = PCE.sed opt.TotTrans = TotTrans.sed jexosim_plot('PCE', opt.diagnostics, xdata=PCE.wl, ydata=PCE.sed) jexosim_plot('Total transmission not including QE', opt.diagnostics, xdata=TotTrans.wl, ydata=TotTrans.sed) opt.qe_spec = qe opt.Re = qe.sed * (qe.wl).to(u.m) / (const.c.value * const.h.value * u.m) opt.star.sed.sed *= opt.Re * u.electron / u.W / u.s opt.star.sed_it.sed *= opt.Re * u.electron / u.W / u.s jexosim_plot('channel star sed check', opt.diagnostics, xdata=opt.x_wav_osr, ydata=opt.star.sed.sed, marker='-') jexosim_msg('check 1.3 - Star sed max: %s' % (opt.star.sed.sed.max()), opt.diagnostics) jexosim_plot('Wavelength solution check -oversampled pixels', opt.diagnostics, xdata=opt.x_pix_osr, ydata=opt.x_wav_osr, marker='o-') jexosim_plot('Wavelength solution check -normal pixels', opt.diagnostics, xdata=opt.x_pix_osr[1::3], ydata=opt.x_wav_osr[1::3], marker='o-') opt.d_x_wav_osr = np.zeros_like(opt.x_wav_osr) idx = np.where(opt.x_wav_osr > 0.0) opt.d_x_wav_osr[idx] = np.gradient(opt.x_wav_osr[idx]) if np.any(opt.d_x_wav_osr < 0): opt.d_x_wav_osr *= -1.0 jexosim_plot('D x wav osr check', opt.diagnostics, xdata=opt.x_pix_osr, ydata=opt.d_x_wav_osr, marker='o') jexosim_plot('D x wav osr check 2', opt.diagnostics, xdata=opt.x_wav_osr, ydata=opt.d_x_wav_osr, marker='o') jexosim_msg("check 1.4: %s" % (opt.star.sed.sed.max()), opt.diagnostics) opt.planet_sed_original = copy.deepcopy(opt.planet.sed.sed) # opt.planet.sed.sed *= opt.star.sed.sed # opt.planet.sed.sed *= opt.d_x_wav_osr jexosim_msg("check 1.5: %s" % (opt.star.sed.sed.max()), opt.diagnostics) opt.star.sed.sed *= opt.d_x_wav_osr opt.star.sed_it.sed *= opt.d_x_wav_osr jexosim_msg("check 2: %s" % (opt.star.sed.sed.max()), opt.diagnostics) jexosim_plot('star sed check 2.0', opt.diagnostics, xdata=opt.x_wav_osr, ydata=opt.star.sed.sed, marker='-') return opt
def __init__(self, opt): output_directory = opt.common.output_directory.val filename = "" self.results_dict = {} self.results_dict['simulation_mode'] = opt.simulation.sim_mode.val self.results_dict[ 'simulation_realisations'] = opt.simulation.sim_realisations.val self.results_dict['ch'] = opt.observation.obs_channel.val self.noise_dict = {} opt.pipeline.useSignal.val = 1 opt.simulation.sim_use_fast.val = 1 opt.pipeline.split = 0 opt.noise.ApplyRandomPRNU.val = 1 opt.timeline.apply_lc.val = 0 opt.timeline.useLDC.val = 0 opt.pipeline.useAllen.val = 1 opt.timeline.use_T14.val = 0 opt.timeline.obs_time.val = 0 * u.hr # 0 means n_exp overides obs_time opt.timeline.n_exp.val = 1000.0 # uses 1000 exposures # opt.timeline.n_exp.val = 400 noise_type = int(opt.noise.sim_noise_source.val) nb_dict = { 'rn': [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], 'sn': [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], 'spat': [1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0], 'spec': [1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0], 'emm_switch': [1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1], 'zodi_switch': [1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1], 'dc_switch': [1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0], 'source_switch': [1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1], 'diff': [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], 'jitter_switch': [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0], 'fano': [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 'noise_tag': [ 'All noise', 'All photon noise', 'Source photon noise', 'Dark current noise', 'Zodi noise', 'Emission noise', 'Read noise', 'Spatial jitter noise', 'Spectral jitter noise', 'Combined jitter noise', 'No noise - no background', 'No noise - all background', 'Fano noise' ], 'color': [ '0.5', 'b', 'b', 'k', 'orange', 'pink', 'y', 'g', 'purple', 'r', '0.8', 'c', 'c' ] } opt.noise.EnableReadoutNoise.val = nb_dict['rn'][noise_type] opt.noise.EnableShotNoise.val = nb_dict['sn'][noise_type] opt.noise.EnableSpatialJitter.val = nb_dict['spat'][noise_type] opt.noise.EnableSpectralJitter.val = nb_dict['spec'][noise_type] opt.noise.EnableFanoNoise.val = nb_dict['fano'][noise_type] opt.background.EnableEmission.val = nb_dict['emm_switch'][noise_type] opt.background.EnableZodi.val = nb_dict['zodi_switch'][noise_type] opt.background.EnableDC.val = nb_dict['dc_switch'][noise_type] opt.background.EnableSource.val = nb_dict['source_switch'][noise_type] opt.diff = nb_dict['diff'][noise_type] opt.noise_tag = nb_dict['noise_tag'][noise_type] opt.color = nb_dict['color'][noise_type] self.noise_dict[nb_dict['noise_tag'][noise_type]] = {} jexosim_msg("Noise type: %s" % (nb_dict['noise_tag'][noise_type]), 1) start = 0 end = int(start + opt.no_real) opt = self.run_JexoSimA(opt) if opt.observation_feasibility == 0: jexosim_msg("Observation not feasible...", opt.diagnostics) self.feasibility = 0 else: self.feasibility = 1 n_ndr0 = opt.n_ndr * 1 ndr_end_frame_number0 = opt.ndr_end_frame_number * 1 frames_per_ndr0 = opt.frames_per_ndr * 1 duration_per_ndr0 = opt.duration_per_ndr * 1 n_exp0 = opt.n_exp if n_ndr0 > 10000: opt.pipeline.split = 1 if opt.diagnostics == 1: jexosim_msg('number of NDRs > 10000: using split protocol', opt.diagnostics) else: opt.pipeline.split = 0 opt.pipeline.split = 0 for j in range(start, end): if (opt.no_real - start) > 1: jexosim_msg("", 1) jexosim_msg("============= REALIZATION %s =============" % (j), 1) jexosim_msg(opt.lab, 1) jexosim_msg("", 1) opt = self.run_JexoSimA1(opt) # set QE grid for this realization jexosim_msg("QE variations set", 1) jexosim_msg("Number of exposures %s" % (n_exp0), 1) # ============================================================================= # split simulation into chunks to permit computation - makes no difference to final results # ============================================================================= if opt.pipeline.split == 1: jexosim_msg('Splitting data series into chunks', opt.diagnostics) # uses same QE grid and jitter timeline but otherwise randomoses noise ndrs_per_round = opt.effective_multiaccum * int( 5000 / opt.multiaccum) # ndrs_per_round = opt.effective_multiaccum*int(50/opt.multiaccum) total_chunks = len(np.arange(0, n_ndr0, ndrs_per_round)) idx = np.arange(0, n_ndr0, ndrs_per_round) # list of starting ndrs for i in range(len(idx)): jexosim_msg( '=== Chunk %s / %s=====' % (i + 1, total_chunks), opt.diagnostics) if idx[i] == idx[-1]: opt.n_ndr = n_ndr0 - idx[i] opt.ndr_end_frame_number = ndr_end_frame_number0[ idx[i]:] opt.frames_per_ndr = frames_per_ndr0[idx[i]:] opt.duration_per_ndr = duration_per_ndr0[idx[i]:] else: opt.n_ndr = idx[i + 1] - idx[i] opt.ndr_end_frame_number = ndr_end_frame_number0[ idx[i]:idx[i + 1]] opt.frames_per_ndr = frames_per_ndr0[idx[i]:idx[i + 1]] opt.duration_per_ndr = duration_per_ndr0[idx[i]:idx[i + 1]] opt.n_exp = int(opt.n_ndr / opt.effective_multiaccum) if i == 0: opt.use_external_jitter = 0 opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) if opt.pipeline.pipeline_auto_ap.val == 1: opt.pipeline.pipeline_ap_factor.val = opt.AvBest if (opt.noise.EnableSpatialJitter.val == 1 or opt.noise.EnableSpectralJitter.val == 1 or opt.noise.EnableAll.val == 1) and opt.noise.DisableAll.val != 1: opt.input_yaw_jitter, opt.input_pitch_jitter, opt._input_frame_osf = opt.yaw_jitter, opt.pitch_jitter, opt.frame_osf else: opt.pipeline.pipeline_auto_ap.val = 0 opt.use_external_jitter = 1 # uses the jitter timeline from the first realization opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) jexosim_msg( 'Aperture used %s' % (opt.pipeline.pipeline_ap_factor.val), opt.diagnostics) binnedLC = opt.pipeline_stage_1.binnedLC data = opt.pipeline_stage_1.opt.data_raw #After chunks processed, now recombine if i == 0: data_stack = data binnedLC_stack = binnedLC else: data_stack = np.dstack((data_stack, data)) binnedLC_stack = np.vstack((binnedLC_stack, binnedLC)) aa = data_stack.sum(axis=0) bb = aa.sum(axis=0) jexosim_plot('test_from_sim', opt.diagnostics, ydata=bb[opt.effective_multiaccum::opt. effective_multiaccum]) aa = binnedLC_stack.sum(axis=1) jexosim_plot('test_from_pipeline', opt.diagnostics, ydata=aa) opt.n_ndr = n_ndr0 opt.ndr_end_frame_number = ndr_end_frame_number0 opt.frames_per_ndr = frames_per_ndr0 opt.duration_per_ndr = duration_per_ndr0 opt.n_exp = n_exp0 elif opt.pipeline.split == 0: opt = self.run_JexoSimB(opt) if j == start: # first realization sets the ap, then the other use the same one opt.pipeline.pipeline_auto_ap.val = 1 else: opt.pipeline.pipeline_auto_ap.val = 0 opt = self.run_pipeline_stage_1(opt) if j == start: # first realization sets the ap, then the other use the same one if opt.pipeline.pipeline_apply_mask.val == 1: opt.pipeline.pipeline_ap_factor.val = opt.AvBest binnedLC_stack = opt.pipeline_stage_1.binnedLC data_stack = opt.pipeline_stage_1.opt.data_raw jexosim_plot('testvvv', opt.diagnostics, ydata=binnedLC_stack.sum(axis=1)) aa = data_stack.sum(axis=0) import matplotlib.pyplot as plt plt.figure('data raw noise') plt.plot(opt.x_wav_osr[1::3], aa.std(axis=1)) plt.figure('binned lc noise') std = binnedLC_stack.std(axis=0) plt.plot(opt.pipeline_stage_1.binnedWav, std) #take binnedLC_stack and now complete through pipeline stage 2 opt.pipeline_stage_1.binnedLC = binnedLC_stack opt = self.run_pipeline_stage_2(opt) self.pipeline = opt.pipeline_stage_2 self.noise_dict[opt.noise_tag]['wl'] = self.pipeline.binnedWav self.results_dict['input_spec'] = opt.cr self.results_dict['input_spec_wl'] = opt.cr_wl if j == start: self.noise_dict[ opt.noise_tag]['signal_std_stack'] = self.pipeline.ootNoise self.noise_dict[opt.noise_tag][ 'signal_mean_stack'] = self.pipeline.ootSignal if opt.pipeline.useAllen.val == 1: self.noise_dict[opt.noise_tag][ 'fracNoT14_stack'] = self.pipeline.noiseAt1hr self.noise_dict[ opt.noise_tag]['signal_std_mean'] = self.pipeline.ootNoise self.noise_dict[opt.noise_tag][ 'signal_mean_mean'] = self.pipeline.ootSignal if opt.pipeline.useAllen.val == 1: self.noise_dict[opt.noise_tag][ 'fracNoT14_mean'] = self.pipeline.noiseAt1hr self.noise_dict[opt.noise_tag]['signal_std_std'] = np.zeros( len(self.pipeline.binnedWav)) self.noise_dict[opt.noise_tag]['signal_mean_std'] = np.zeros( len(self.pipeline.binnedWav)) if opt.pipeline.useAllen.val == 1: self.noise_dict[opt.noise_tag]['fracNoT14_std'] = np.zeros( len(self.pipeline.binnedWav)) else: self.noise_dict[opt.noise_tag]['signal_std_stack'] = np.vstack( (self.noise_dict[opt.noise_tag]['signal_std_stack'], self.pipeline.ootNoise)) self.noise_dict[ opt.noise_tag]['signal_mean_stack'] = np.vstack( (self.noise_dict[opt.noise_tag]['signal_mean_stack'], self.pipeline.ootSignal)) if opt.pipeline.useAllen.val == 1: self.noise_dict[ opt.noise_tag]['fracNoT14_stack'] = np.vstack( (self.noise_dict[opt.noise_tag]['fracNoT14_stack'], self.pipeline.noiseAt1hr)) self.noise_dict[ opt.noise_tag]['signal_std_mean'] = self.noise_dict[ opt.noise_tag]['signal_std_stack'].mean(axis=0) self.noise_dict[ opt.noise_tag]['signal_mean_mean'] = self.noise_dict[ opt.noise_tag]['signal_mean_stack'].mean(axis=0) if opt.pipeline.useAllen.val == 1: self.noise_dict[ opt.noise_tag]['fracNoT14_mean'] = self.noise_dict[ opt.noise_tag]['fracNoT14_stack'].mean(axis=0) self.noise_dict[ opt.noise_tag]['signal_std_std'] = self.noise_dict[ opt.noise_tag]['signal_std_stack'].std(axis=0) self.noise_dict[ opt.noise_tag]['signal_mean_std'] = self.noise_dict[ opt.noise_tag]['signal_mean_stack'].std(axis=0) if opt.pipeline.useAllen.val == 1: self.noise_dict[ opt.noise_tag]['fracNoT14_std'] = self.noise_dict[ opt.noise_tag]['fracNoT14_stack'].std(axis=0) self.noise_dict[opt.noise_tag]['bad_map'] = opt.bad_map self.noise_dict[ opt.noise_tag]['example_exposure_image'] = opt.exp_image self.noise_dict[ opt.noise_tag]['pixel wavelengths'] = opt.x_wav_osr[1::3].value self.results_dict['noise_dic'] = self.noise_dict time_tag = (datetime.now().strftime('%Y_%m_%d_%H%M_%S')) self.results_dict['time_tag'] = time_tag if j != start: os.remove(filename) # delete previous temp file txt_file = '%s.txt' % (filename) os.remove(txt_file) filename = '%s/OOT_SNR_%s_%s_TEMP.pickle' % (output_directory, opt.lab, time_tag) self.filename = 'OOT_SNR_%s_%s_TEMP.pickle' % (opt.lab, time_tag) with open(filename, 'wb') as handle: pickle.dump(self.results_dict, handle, protocol=pickle.HIGHEST_PROTOCOL) if j == end - 1: os.remove(filename) # delete previous temp file filename = '%s/OOT_SNR_%s_%s.pickle' % (output_directory, opt.lab, time_tag) with open(filename, 'wb') as handle: pickle.dump(self.results_dict, handle, protocol=pickle.HIGHEST_PROTOCOL) jexosim_msg('Results in %s' % (filename), 1) self.filename = 'OOT_SNR_%s_%s.pickle' % (opt.lab, time_tag) write_record(opt, output_directory, self.filename, opt.params_file_path)
def __init__(self, opt): output_directory = opt.common.output_directory.val filename = "" self.results_dict = {} self.results_dict['simulation_mode'] = opt.simulation.sim_mode.val self.results_dict[ 'simulation_realisations'] = opt.simulation.sim_realisations.val self.results_dict['ch'] = opt.observation.obs_channel.val opt.pipeline.useSignal.val = 0 opt.simulation.sim_use_fast.val = 1 opt.pipeline.split = 0 opt.noise.ApplyRandomPRNU.val = 1 opt.timeline.apply_lc.val = 1 opt.timeline.useLDC.val = 1 opt.pipeline.useAllen.val = 0 opt.pipeline.fit_gamma.val = 0 #keep zero for uncert on p start = 0 end = int(start + opt.no_real) if (opt.no_real - start) > 1: jexosim_msg("Monte Carlo selected", 1) opt = self.run_JexoSimA(opt) if opt.observation_feasibility == 0: jexosim_msg("Observation not feasible...", opt.diagnostics) self.feasibility = 0 else: self.feasibility = 1 n_ndr0 = opt.n_ndr * 1 lc0 = opt.lc_original * 1 ndr_end_frame_number0 = opt.ndr_end_frame_number * 1 frames_per_ndr0 = opt.frames_per_ndr * 1 duration_per_ndr0 = opt.duration_per_ndr * 1 n_exp0 = opt.n_exp if n_ndr0 > 10000: opt.pipeline.split = 1 if opt.diagnostics == 1: jexosim_msg('number of NDRs > 10000: using split protocol', opt.diagnostics) else: opt.pipeline.split = 0 for j in range(start, end): if (opt.no_real - start) > 1: jexosim_msg("", 1) jexosim_msg( "============= REALIZATION %s =============" % (j), 1) jexosim_msg(opt.lab, 1) jexosim_msg("", 1) pp = time.time() opt = self.run_JexoSimA1( opt) # set QE grid for this realization jexosim_msg("QE variations set", 1) jexosim_msg("Number of exposures %s" % (n_exp0), 1) lc0 = opt.lc_original * 1 # ============================================================================= # # split simulation into chunks to permit computation - makes no difference to final results # ============================================================================= if opt.pipeline.split == 1: jexosim_msg('Splitting data series into chunks', opt.diagnostics) # uses same QE grid and jitter timeline but otherwise randomoses noise ndrs_per_round = opt.effective_multiaccum * int( 5000 / opt.multiaccum) # ndrs_per_round = opt.effective_multiaccum*int(50/opt.multiaccum) total_chunks = len(np.arange(0, n_ndr0, ndrs_per_round)) idx = np.arange(0, n_ndr0, ndrs_per_round) # list of starting ndrs for i in range(len(idx)): jexosim_msg( '=== Chunk %s / %s=====' % (i + 1, total_chunks), opt.diagnostics) if idx[i] == idx[-1]: opt.n_ndr = n_ndr0 - idx[i] opt.lc_original = lc0[:, idx[i]:] opt.ndr_end_frame_number = ndr_end_frame_number0[ idx[i]:] opt.frames_per_ndr = frames_per_ndr0[idx[i]:] opt.duration_per_ndr = duration_per_ndr0[idx[i]:] else: opt.n_ndr = idx[i + 1] - idx[i] opt.lc_original = lc0[:, idx[i]:idx[i + 1]] opt.ndr_end_frame_number = ndr_end_frame_number0[ idx[i]:idx[i + 1]] opt.frames_per_ndr = frames_per_ndr0[idx[i]:idx[i + 1]] opt.duration_per_ndr = duration_per_ndr0[ idx[i]:idx[i + 1]] opt.n_exp = int(opt.n_ndr / opt.effective_multiaccum) if i == 0: opt.pipeline.pipeline_auto_ap.val = 1 opt.use_external_jitter = 0 opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) opt.pipeline.pipeline_ap_factor.val = opt.AvBest if (opt.noise.EnableSpatialJitter.val == 1 or opt.noise.EnableSpectralJitter.val == 1 or opt.noise.EnableAll.val == 1) and opt.noise.DisableAll.val != 1: opt.input_yaw_jitter, opt.input_pitch_jitter, opt._input_frame_osf = opt.yaw_jitter, opt.pitch_jitter, opt.frame_osf else: opt.pipeline.pipeline_auto_ap.val = 0 opt.use_external_jitter = 1 # uses the jitter timeline from the first realization opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) jexosim_msg( 'Aperture used %s' % (opt.pipeline.pipeline_ap_factor.val), opt.diagnostics) data0 = opt.pipeline_stage_1.binnedLC data = opt.pipeline_stage_1.opt.data_raw if i == 0: data_stack = data data_stack0 = data0 else: data_stack = np.dstack((data_stack, data)) data_stack0 = np.vstack((data_stack0, data0)) aa = data_stack.sum(axis=0) bb = aa.sum(axis=0) jexosim_plot('test_from_sim', opt.diagnostics, ydata=bb[opt.effective_multiaccum::opt. effective_multiaccum]) aa = data_stack0.sum(axis=1) jexosim_plot('test_from_pipeline', opt.diagnostics, ydata=aa) opt.n_ndr = n_ndr0 opt.ndr_end_frame_number = ndr_end_frame_number0 opt.frames_per_ndr = frames_per_ndr0 opt.duration_per_ndr = duration_per_ndr0 opt.n_exp = n_exp0 elif opt.pipeline.split == 0: opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) if j == start: # first realization sets the ap, then the other use the same one opt.use_auto_Ap = 1 opt.pipeline.pipeline_ap_factor.val = opt.AvBest else: opt.use_auto_Ap = 0 data_stack0 = opt.pipeline_stage_1.binnedLC jexosim_plot('testvvv', opt.diagnostics, ydata=data_stack0.sum(axis=1)) opt.pipeline_stage_1.binnedLC = data_stack0 opt = self.run_pipeline_stage_2(opt) pipeline = opt.pipeline_stage_2 p = pipeline.transitDepths if j == start: p_stack = p else: p_stack = np.vstack((p_stack, p)) jexosim_msg( "time to complete realization %s %s" % (j, time.time() - pp), opt.diagnostics) self.results_dict['wl'] = pipeline.binnedWav self.results_dict['input_spec'] = opt.cr self.results_dict['input_spec_wl'] = opt.cr_wl if j == start: # if only one realisation slightly different format self.results_dict['p_stack'] = np.array(p) self.results_dict['p_std'] = np.zeros(len(p)) self.results_dict['p_mean'] = np.array(p) else: self.results_dict['p_stack'] = np.vstack( (self.results_dict['p_stack'], p)) self.results_dict['p_std'] = self.results_dict[ 'p_stack'].std(axis=0) self.results_dict['p_mean'] = self.results_dict[ 'p_stack'].mean(axis=0) time_tag = (datetime.now().strftime('%Y_%m_%d_%H%M_%S')) self.results_dict['time_tag'] = time_tag self.results_dict['bad_map'] = opt.bad_map self.results_dict['example_exposure_image'] = opt.exp_image self.results_dict['pixel wavelengths'] = opt.x_wav_osr[ 1::3].value if j != start: os.remove(filename) # delete previous temp file filename = '%s/Full_transit_%s_TEMP.pickle' % ( output_directory, opt.lab) with open(filename, 'wb') as handle: pickle.dump(self.results_dict, handle, protocol=pickle.HIGHEST_PROTOCOL) os.remove(filename) # delete previous temp file # write final file filename = '%s/Full_transit_%s_%s.pickle' % (output_directory, opt.lab, time_tag) with open(filename, 'wb') as handle: pickle.dump(self.results_dict, handle, protocol=pickle.HIGHEST_PROTOCOL) jexosim_msg('Results in %s' % (filename), 1) self.filename = 'Full_transit_%s_%s.pickle' % (opt.lab, time_tag) write_record(opt, output_directory, self.filename, opt.params_file_path)
def run(opt): opt.observation_feasibility = 1 # this variable is currently not changed to zero under any circumstances opt.psf, opt.psf_type = instrument_lib.get_psf(opt) opt.fp, opt.fp_signal = instrument_lib.get_focal_plane(opt) opt.fp_it, opt.fp_signal_it = instrument_lib.get_focal_plane_it(opt) mask_fp = np.where(opt.fp > 0, 1, 0) mask_fp_it = np.where(opt.fp_it > 0, 1, 0) mask_fp_signal = np.where(opt.fp_signal > 0, 1, 0) mask_fp_signal_it = np.where(opt.fp_signal_it > 0, 1, 0) opt.fp, opt.fp_signal = instrument_lib.convolve_prf( opt, opt.fp, opt.fp_signal) #this step can gen some small negative values on fp opt.fp = np.where(opt.fp < 0, 0, opt.fp) opt.fp_signal = np.where(opt.fp_signal < 0, 0, opt.fp_signal) opt.fp_it, opt.fp_signal_it = instrument_lib.convolve_prf( opt, opt.fp_it, opt.fp_signal_it) #this step can gen some small negative values on fp opt.fp_it = np.where(opt.fp_it < 0, 0, opt.fp_it) opt.fp_signal_it = np.where(opt.fp_signal_it < 0, 0, opt.fp_signal_it) # mask out small values arising from the PRF convolution where there was originally zero signal opt.fp *= mask_fp opt.fp_it *= mask_fp_it opt.fp_signal *= mask_fp_signal opt.fp_signal_it *= mask_fp_signal_it opt.planet.sed = instrument_lib.get_planet_spectrum(opt) jexosim_plot( 'planet sed', opt.diagnostics, xdata=opt.planet.sed.wl, ydata=opt.planet.sed.sed, ) opt = instrument_lib.user_subarray(opt) opt = instrument_lib.crop_to_subarray(opt) opt = instrument_lib.exposure_timing(opt) jexosim_msg("Integration time - zeroth read %s" % (opt.t_int), opt.diagnostics) jexosim_msg( "Estimated integration time incl. zeroth read %s" % (opt.t_int + opt.zero_time), opt.diagnostics) jexosim_msg("Estimated TOTAL CYCLE TIME %s" % (opt.exposure_time), opt.diagnostics) jexosim_msg("CDS time estimate %s" % (opt.t_int), opt.diagnostics) jexosim_msg("FP max %s" % (opt.fp[1::3, 1::3].max()), opt.diagnostics) jexosim_msg("DC SWITCH.......%s" % (opt.background.EnableDC.val), opt.diagnostics) jexosim_msg( "DISABLE ALL SWITCH.......%s" % (opt.background.DisableAll.val), opt.diagnostics) jexosim_msg("DARK CURRENT %s" % (opt.channel.detector_pixel.Idc.val), opt.diagnostics) jexosim_plot('focal plane check', opt.diagnostics, image=True, image_data=opt.fp[1::3, 1::3], aspect='auto', interpolation=None, xlabel='x \'spectral\' pixel', ylabel='y \'spatial\' pixel') if opt.diagnostics == 1: plt.figure('focal plane check') cbar = plt.colorbar() cbar.set_label(('Count (e$^-$/s)'), rotation=270, size=15, labelpad=20) cbar.ax.tick_params(labelsize=15) ax = plt.gca() for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] + ax.get_xticklabels() + ax.get_yticklabels()): item.set_fontsize(15) opt.fp_original = copy.deepcopy(opt.fp) opt.fp_signal_original = copy.deepcopy(opt.fp_signal) opt.x_wav_osr_original = copy.deepcopy(opt.x_wav_osr) opt.x_pix_osr_original = copy.deepcopy(opt.x_pix_osr) opt.quantum_yield_original = copy.deepcopy(opt.quantum_yield) opt.qy_zodi_original = copy.deepcopy(opt.qy_zodi) opt.qy_sunshield_original = copy.deepcopy(opt.qy_sunshield) opt.qy_emission_original = copy.deepcopy(opt.qy_emission) opt.zodi_sed_original = copy.deepcopy( opt.zodi.sed ) # needed here due to possible cropping above for subarrays opt.sunshield_sed_original = copy.deepcopy(opt.sunshield.sed) opt.emission_sed_original = copy.deepcopy(opt.emission.sed) if opt.channel.instrument.val == 'NIRSpec': opt.channel.pipeline_params.wavrange_hi.val = opt.gap[3] opt.channel.pipeline_params.wavrange_lo.val = opt.gap[2] opt.channel.pipeline_params.end_wav.val = opt.gap[3] + 0.1 opt.channel.pipeline_params.start_wav.val = opt.gap[2] - 0.1 jexosim_plot('final wl solution on subarray', opt.diagnostics, ydata=opt.x_wav_osr[1::3], xlabel='x \'spectral\' pixel', ylabel='y \'spatial\' pixel', grid=True) if opt.diagnostics == 1: wl = opt.x_wav_osr wav = opt.x_wav_osr[1::3] if opt.channel.name == 'NIRSpec_BOTS_G140H_F100LP' or \ opt.channel.name == 'NIRSpec_BOTS_G235H_F170LP'\ or opt.channel.name == 'NIRSpec_BOTS_G395H_F290LP': idx0 = np.argwhere(wav == opt.wav_gap_start)[0].item( ) #recover the start of the gap idx1 = idx0 + opt.gap_len # gap of 172 pix works well for G1H and G2H, but a little off (by 0.01 microns for the other in some cases from published values) fp_1d = opt.fp_signal[1::3, 1::3].sum(axis=0) fp_1d[idx0:idx1] = 0 idx0 = np.argwhere(wl == opt.wav_gap_start)[0].item( ) #recover the start of the gap idx1 = idx0 + opt.gap_len * 3 # gap of 172 p opt.PCE[idx0:idx1] = 0 opt.TotTrans[idx0:idx1] = 0 opt.R.sed[idx0:idx1] = 0 else: fp_1d = opt.fp_signal[1::3, 1::3].sum(axis=0) plt.figure('Focal plane pixel count rate') plt.plot(wav, fp_1d, 'r-') plt.grid() plt.figure('Final PCE and transmission on subarray') plt.plot(wl, opt.PCE, '-') plt.plot(wl, opt.TotTrans, '--') plt.figure('R power') plt.plot(wl, opt.R.sed, '-') instrument_lib.sanity_check(opt) return opt
def __init__(self, opt): output_directory = opt.common.output_directory.val filename="" self.results_dict ={} self.results_dict['simulation_mode'] = opt.simulation.sim_mode.val self.results_dict['simulation_realisations'] = opt.simulation.sim_realisations.val self.results_dict['ch'] = opt.observation.obs_channel.val self.noise_dict ={} self.feasibility =1 opt.pipeline.useSignal.val=1 opt.simulation.sim_use_fast.val =1 opt.pipeline.split = 0 opt.noise.ApplyRandomPRNU.val=1 opt.timeline.apply_lc.val = 0 opt.timeline.useLDC.val = 0 opt.pipeline.useAllen.val =1 opt.pipeline.pipeline_auto_ap.val = 0 # for noise budget keep this to a fixed value (i.e. choose 0) so same for all sims opt.timeline.obs_time.val = 0*u.hr opt.timeline.n_exp.val = 1000.0 noise_list = [0,2,3,4,5,6,7,8,9,12,13] # noise_list = [0,2,3,4,5,6,7,8,9] # noise_list = [2,9,12] start = 0 end = int(start + opt.no_real) nb_dict = {'rn' :[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], 'sn' :[1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1], 'spat' :[1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0], 'spec' :[1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], 'emm_switch' :[1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0], 'zodi_switch' :[1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0], 'dc_switch' :[1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], 'source_switch' :[1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0], 'diff' :[0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1], 'jitter_switch' :[1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 'fano' :[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], 'sunshield_switch' :[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1], 'noise_tag': [ 'All noise','All photon noise','Source photon noise','Dark current noise', 'Zodi noise','Emission noise','Read noise','Spatial jitter noise', 'Spectral jitter noise','Combined jitter noise','No noise - no background','No noise - all background', 'Fano noise', 'Sunshield noise'], 'color': ['0.5','b', 'b','k','orange','pink', 'y','g','purple','r', '0.8','c', 'c','brown'] } for i in noise_list: self.noise_dict[nb_dict['noise_tag'][i]] ={} for j in range(start,end): seed = np.random.randint(100000000) for i in noise_list: opt.noise.EnableReadoutNoise.val = nb_dict['rn'][i] opt.noise.EnableShotNoise.val = nb_dict['sn'][i] opt.noise.EnableSpatialJitter.val= nb_dict['spat'][i] opt.noise.EnableSpectralJitter.val= nb_dict['spec'][i] opt.noise.EnableFanoNoise.val= nb_dict['fano'][i] opt.background.EnableEmission.val = nb_dict['emm_switch'][i] opt.background.EnableZodi.val = nb_dict['zodi_switch'][i] opt.background.EnableSunshield.val = nb_dict['sunshield_switch'][i] opt.background.EnableDC.val = nb_dict['dc_switch'][i] opt.background.EnableSource.val = nb_dict['source_switch'][i] opt.diff = nb_dict['diff'][i] opt.noise_tag = nb_dict['noise_tag'][i] opt.color = nb_dict['color'][i] jexosim_msg('==========================================', 1) jexosim_msg('Noise source:%s'%(opt.noise_tag), 1) np.random.seed(seed) opt = self.run_JexoSimA(opt) opt = self.run_JexoSimA1(opt) n_ndr0 = opt.n_ndr*1 ndr_end_frame_number0 = opt.ndr_end_frame_number*1 frames_per_ndr0 = opt.frames_per_ndr*1 duration_per_ndr0 = opt.duration_per_ndr*1 n_exp0 = opt.n_exp if n_ndr0 > 10000: opt.pipeline.split = 1 if opt.diagnostics ==1 : jexosim_msg ('number of NDRs > 10000: using split protocol', opt.diagnostics) else: opt.pipeline.split = 0 opt.pipeline.split = 1 # ============================================================================= # split simulation into chunks to permit computation - makes no difference to final results # ============================================================================= if opt.pipeline.split ==1: jexosim_msg('Splitting data series into chunks', opt.diagnostics) # uses same QE grid and jitter timeline but otherwise randomoses noise ndrs_per_round = opt.effective_multiaccum*int(5000/opt.multiaccum) ndrs_per_round = opt.effective_multiaccum*int(50/opt.multiaccum) total_chunks = len(np.arange(0, n_ndr0, ndrs_per_round)) idx = np.arange(0, n_ndr0, ndrs_per_round) # list of starting ndrs for i in range(len(idx)): jexosim_msg('=== Chunk %s / %s====='%(i+1, total_chunks), opt.diagnostics) if idx[i] == idx[-1]: opt.n_ndr = n_ndr0 - idx[i] opt.ndr_end_frame_number = ndr_end_frame_number0[idx[i]:] opt.frames_per_ndr= frames_per_ndr0[idx[i]:] opt.duration_per_ndr = duration_per_ndr0[idx[i]:] else: opt.n_ndr = idx[i+1]- idx[i] opt.ndr_end_frame_number = ndr_end_frame_number0[idx[i]: idx[i+1]] opt.frames_per_ndr= frames_per_ndr0[idx[i]: idx[i+1]] opt.duration_per_ndr = duration_per_ndr0[idx[i]: idx[i+1]] opt.n_exp = int(opt.n_ndr/opt.effective_multiaccum) if i == 0: opt.use_external_jitter = 0 opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) if opt.pipeline.pipeline_auto_ap.val == 1: opt.pipeline.pipeline_ap_factor.val= opt.AvBest if (opt.noise.EnableSpatialJitter.val ==1 or opt.noise.EnableSpectralJitter.val ==1 or opt.noise.EnableAll.val == 1) and opt.noise.DisableAll.val != 1: opt.input_yaw_jitter, opt.input_pitch_jitter, opt._input_frame_osf = opt.yaw_jitter, opt.pitch_jitter, opt.frame_osf else: opt.pipeline.pipeline_auto_ap.val = 0 opt.use_external_jitter = 1 # uses the jitter timeline from the first realization opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) jexosim_msg('Aperture used %s'%(opt.pipeline.pipeline_ap_factor.val), opt.diagnostics) binnedLC = opt.pipeline_stage_1.binnedLC data = opt.pipeline_stage_1.opt.data_raw #After chunks processed, now recombine if i ==0: data_stack = data binnedLC_stack = binnedLC else: data_stack = np.dstack((data_stack,data)) binnedLC_stack = np.vstack((binnedLC_stack, binnedLC)) aa = data_stack.sum(axis=0) bb = aa.sum(axis=0) jexosim_plot('test_from_sim', opt.diagnostics, ydata=bb[opt.effective_multiaccum::opt.effective_multiaccum] ) aa = binnedLC_stack.sum(axis=1) jexosim_plot('test_from_pipeline', opt.diagnostics, ydata=aa) opt.n_ndr = n_ndr0 opt.ndr_end_frame_number = ndr_end_frame_number0 opt.frames_per_ndr = frames_per_ndr0 opt.duration_per_ndr = duration_per_ndr0 opt.n_exp = n_exp0 elif opt.pipeline.split ==0: opt = self.run_JexoSimB(opt) if j==start: # first realization sets the ap, then the other use the same one opt.pipeline.pipeline_auto_ap.val= 1 else: opt.pipeline.pipeline_auto_ap.val= 0 opt = self.run_pipeline_stage_1(opt) if j==start: # first realization sets the ap, then the other use the same one if opt.pipeline.pipeline_apply_mask.val == 1: opt.pipeline.pipeline_ap_factor.val= opt.AvBest binnedLC_stack = opt.pipeline_stage_1.binnedLC data_stack = opt.pipeline_stage_1.opt.data_raw jexosim_plot('testvvv', opt.diagnostics, ydata=binnedLC_stack.sum(axis=1) ) #take binnedLC_stack and now complete through pipeline stage 2 opt.pipeline_stage_1.binnedLC = binnedLC_stack opt = self.run_pipeline_stage_2(opt) self.pipeline = opt.pipeline_stage_2 self.opt = opt self.noise_dict[opt.noise_tag]['wl'] = self.pipeline.binnedWav if j == start: self.noise_dict[opt.noise_tag]['signal_std_stack'] = self.pipeline.ootNoise self.noise_dict[opt.noise_tag]['signal_mean_stack'] = self.pipeline.ootSignal if opt.pipeline.useAllen.val == 1: self.noise_dict[opt.noise_tag]['fracNoT14_stack'] = self.pipeline.noiseAt1hr self.noise_dict[opt.noise_tag]['signal_std_mean'] = self.pipeline.ootNoise self.noise_dict[opt.noise_tag]['signal_mean_mean'] = self.pipeline.ootSignal if opt.pipeline.useAllen.val == 1: self.noise_dict[opt.noise_tag]['fracNoT14_mean'] = self.pipeline.noiseAt1hr self.noise_dict[opt.noise_tag]['signal_std_std'] = np.zeros(len(self.pipeline.binnedWav)) self.noise_dict[opt.noise_tag]['signal_mean_std'] = np.zeros(len(self.pipeline.binnedWav)) if opt.pipeline.useAllen.val == 1: self.noise_dict[opt.noise_tag]['fracNoT14_std'] = np.zeros(len(self.pipeline.binnedWav)) self.noise_dict[opt.noise_tag]['bad_map'] = opt.bad_map self.noise_dict[opt.noise_tag]['example_exposure_image'] = opt.exp_image self.noise_dict[opt.noise_tag]['pixel wavelengths'] = opt.x_wav_osr[1::3].value else: self.noise_dict[opt.noise_tag]['signal_std_stack'] = np.vstack((self.noise_dict[opt.noise_tag]['signal_std_stack'], self.pipeline.ootNoise)) self.noise_dict[opt.noise_tag]['signal_mean_stack'] = np.vstack((self.noise_dict[opt.noise_tag]['signal_mean_stack'], self.pipeline.ootSignal)) if opt.pipeline.useAllen.val == 1: self.noise_dict[opt.noise_tag]['fracNoT14_stack'] = np.vstack((self.noise_dict[opt.noise_tag]['fracNoT14_stack'], self.pipeline.noiseAt1hr)) self.noise_dict[opt.noise_tag]['signal_std_mean'] = self.noise_dict[opt.noise_tag]['signal_std_stack'].mean(axis=0) self.noise_dict[opt.noise_tag]['signal_mean_mean'] = self.noise_dict[opt.noise_tag]['signal_mean_stack'].mean(axis=0) if opt.pipeline.useAllen.val == 1: self.noise_dict[opt.noise_tag]['fracNoT14_mean'] = self.noise_dict[opt.noise_tag]['fracNoT14_stack'].mean(axis=0) self.noise_dict[opt.noise_tag]['signal_std_std'] = self.noise_dict[opt.noise_tag]['signal_std_stack'].std(axis=0) self.noise_dict[opt.noise_tag]['signal_mean_std'] = self.noise_dict[opt.noise_tag]['signal_mean_stack'].std(axis=0) if opt.pipeline.useAllen.val == 1: self.noise_dict[opt.noise_tag]['fracNoT14_std'] = self.noise_dict[opt.noise_tag]['fracNoT14_stack'].std(axis=0) self.noise_dict[opt.noise_tag]['bad_map'] = opt.bad_map self.noise_dict[opt.noise_tag]['example_exposure_image'] = opt.exp_image self.noise_dict[opt.noise_tag]['pixel wavelengths'] = opt.x_wav_osr[1::3].value self.results_dict['noise_dic'] = self.noise_dict # dump pickle file at end of each cycle of noise sims if opt.simulation.sim_output_type.val == 1: time_tag = (datetime.now().strftime('%Y_%m_%d_%H%M_%S')) self.results_dict['time_tag'] = time_tag # if j != start: # os.remove(filename) # delete previous temp file # filename = '%s/Noise_budget_%s_TEMP.pickle'%(output_directory, opt.lab) # with open(filename, 'wb') as handle: # pickle.dump(self.results_dict , handle, protocol=pickle.HIGHEST_PROTOCOL) if j == end-1: # os.remove(filename) # delete previous temp file filename = '%s/Noise_budget_%s_%s.pickle'%(output_directory, opt.lab, time_tag) with open(filename, 'wb') as handle: pickle.dump(self.results_dict , handle, protocol=pickle.HIGHEST_PROTOCOL) jexosim_msg('Results in %s'%(filename), 1) self.filename = 'Noise_budget_%s_%s.pickle'%(opt.lab, time_tag) write_record(opt, output_directory, self.filename, opt.params_file_path)
def getLDC_interp(opt, planet, wl): jexosim_msg('Calculating LDC from pre-installed files', 1) T = planet.star.T.value if T < 3000.0: # temp fix as LDCs not available for T< 3000 K T = 3000.0 logg = planet.star.logg jexosim_msg("T_s, logg>>>> %s %s" % (T, logg), opt.diagnostics) folder = '%s/archive/LDC' % (opt.jexosim_path) t_base = np.int(T / 100.) * 100 if T >= t_base + 100: t1 = t_base + 100 t2 = t_base + 200 else: t1 = t_base t2 = t_base + 100 logg_base = np.int(logg) if logg >= logg_base + 0.5: logg1 = logg_base + 0.5 logg2 = logg_base + 1.0 else: logg1 = logg_base logg2 = logg_base + 0.5 logg1 = np.float(logg1) logg2 = np.float(logg2) #============================================================================== # interpolate between temperatures assuming logg1 #============================================================================== u0_a = np.loadtxt('%s/T=%s_logg=%s_z=0.txt' % (folder, t1, logg1))[:, 1] u0_b = np.loadtxt('%s/T=%s_logg=%s_z=0.txt' % (folder, t2, logg1))[:, 1] w2 = 1.0 - abs(t2 - T) / 100. w1 = 1.0 - abs(t1 - T) / 100. u0_1 = w1 * u0_a + w2 * u0_b u1_a = np.loadtxt('%s/T=%s_logg=%s_z=0.txt' % (folder, t1, logg1))[:, 2] u1_b = np.loadtxt('%s/T=%s_logg=%s_z=0.txt' % (folder, t2, logg1))[:, 2] w2 = 1.0 - abs(t2 - T) / 100. w1 = 1.0 - abs(t1 - T) / 100. u1_1 = w1 * u1_a + w2 * u1_b jexosim_plot('ldc interp logg1', opt.diagnostics, ydata=u0_a, marker='b-') jexosim_plot('ldc interp logg1', opt.diagnostics, ydata=u0_b, marker='r-') jexosim_plot('ldc interp logg1', opt.diagnostics, ydata=u0_1, marker='g-') jexosim_plot('ldc interp logg1', opt.diagnostics, ydata=u1_a, marker='b-') jexosim_plot('ldc interp logg1', opt.diagnostics, ydata=u1_b, marker='r-') jexosim_plot('ldc interp logg1', opt.diagnostics, ydata=u1_1, marker='g-') ldc_wl = np.loadtxt('%s/T=%s_logg=%s_z=0.txt' % (folder, t1, logg1))[:, 0] #============================================================================== # interpolate between temperatures assuming logg2 #============================================================================== u0_a = np.loadtxt('%s/T=%s_logg=%s_z=0.txt' % (folder, t1, logg2))[:, 1] u0_b = np.loadtxt('%s/T=%s_logg=%s_z=0.txt' % (folder, t2, logg2))[:, 1] w2 = 1.0 - abs(t2 - T) / 100. w1 = 1.0 - abs(t1 - T) / 100. u0_2 = w1 * u0_a + w2 * u0_b u1_a = np.loadtxt('%s/T=%s_logg=%s_z=0.txt' % (folder, t1, logg2))[:, 2] u1_b = np.loadtxt('%s/T=%s_logg=%s_z=0.txt' % (folder, t2, logg2))[:, 2] w2 = 1.0 - abs(t2 - T) / 100. w1 = 1.0 - abs(t1 - T) / 100. u1_2 = w1 * u1_a + w2 * u1_b jexosim_plot('ldc interp logg2', opt.diagnostics, ydata=u0_a, marker='b-') jexosim_plot('ldc interp logg2', opt.diagnostics, ydata=u0_b, marker='r-') jexosim_plot('ldc interp logg2', opt.diagnostics, ydata=u0_2, marker='g-') jexosim_plot('ldc interp logg2', opt.diagnostics, ydata=u1_a, marker='b-') jexosim_plot('ldc interp logg2', opt.diagnostics, ydata=u1_b, marker='r-') jexosim_plot('ldc interp logg2', opt.diagnostics, ydata=u1_2, marker='g-') #============================================================================== # interpolate between logg #============================================================================== w2 = 1.0 - abs(logg2 - logg) / .5 w1 = 1.0 - abs(logg1 - logg) / .5 u0 = w1 * u0_1 + w2 * u0_2 u1 = w1 * u1_1 + w2 * u1_2 jexosim_plot('ldc interp', opt.diagnostics, ydata=u0_1, marker='b-') jexosim_plot('ldc interp', opt.diagnostics, ydata=u0_2, marker='r-') jexosim_plot('ldc interp', opt.diagnostics, ydata=u0, marker='g-') jexosim_plot('ldc interp', opt.diagnostics, ydata=u1_1, marker='b-') jexosim_plot('ldc interp', opt.diagnostics, ydata=u1_2, marker='r-') jexosim_plot('ldc interp', opt.diagnostics, ydata=u1, marker='g-') #============================================================================== # interpolate to new wl grid #============================================================================== u0_final = np.interp(wl, ldc_wl, u0) u1_final = np.interp(wl, ldc_wl, u1) jexosim_plot('ldc final', opt.diagnostics, xdata=ldc_wl, ydata=u0, marker='ro', alpha=0.1) jexosim_plot('ldc final', opt.diagnostics, xdata=ldc_wl, ydata=u1, marker='bo', alpha=0.1) jexosim_plot('ldc final', opt.diagnostics, xdata=wl, ydata=u0_final, marker='rx') jexosim_plot('ldc final', opt.diagnostics, xdata=wl, ydata=u1_final, marker='bx') return u0_final, u1_final
def read_phoenix_spectrum_interp(self): jexosim_msg ("Star... star_temperature %s, star_logg %s, star_f_h %s"%(self.star_temperature, self.star_logg, self.star_f_h) , self.opt.diagnostics) if self.star_temperature.value >= 2400: t0 = np.round(self.star_temperature,-2)/100. else: t0= np.round(np.round(self.star_temperature,-1)/100./0.5)*0.5 t0 = t0.value if t0*100 != self.star_temperature.value: cond_1 = 1 if t0*100 > self.star_temperature.value: if self.star_temperature.value >= 2400: t1 = t0-1 else: t1 = t0-0.5 elif t0*100 < self.star_temperature.value: if self.star_temperature.value >= 2400: t1= t0+1 else: t1 = t0+0.5 print (t0,t1, self.star_temperature) else: cond_1 = 0 # do not interp for temp logg0 = np.round(np.round(self.star_logg,1)/0.5)*0.5 if logg0 <= 2.5: logg0 = 2.5 cond_2 = 0 # do not interp for logg elif logg0 >= 5.5: logg0 = 5.5 cond_2 = 0 elif logg0 == self.star_logg: cond_2 = 0 else: cond_2 = 1 if logg0 < self.star_logg: logg1 = logg0 + 0.5 if logg0 > self.star_logg: logg1 = logg0 - 0.5 if cond_1 == 1 and cond_2 == 0: jexosim_msg ("interpolating spectra by temperature only", self.opt.diagnostics) wav_t0_logg0, flux_t0_logg0 = self.open_Phoenix(t0,logg0, self.star_f_h, self.sed_folder) wav_t1_logg0, flux_t1_logg0 = self.open_Phoenix(t1,logg0, self.star_f_h, self.sed_folder) sed_t0_logg0 = sed.Sed(wav_t0_logg0, flux_t0_logg0) sed_t1_logg0 = sed.Sed(wav_t1_logg0, flux_t1_logg0) # bin to same wav grid sed_t1_logg0.rebin(wav_t0_logg0) wt0 = 1 - abs(t0*100 - self.star_temperature.value)/abs(t0*100 - t1*100) wt1 = 1 - abs(self.star_temperature.value - t1*100)/abs(t0*100 - t1*100) sed_final = wt0*sed_t0_logg0.sed + wt1*sed_t1_logg0.sed star_final_sed = sed_final star_final_wl = sed_t0_logg0.wl jexosim_plot('temperature interpolation', self.opt.diagnostics, xdata = wav_t0_logg0, ydata = flux_t0_logg0, marker ='r-') jexosim_plot('temperature interpolation', self.opt.diagnostics, xdata = wav_t1_logg0, ydata = flux_t1_logg0, marker ='b-') jexosim_plot('temperature interpolation', self.opt.diagnostics, xdata = star_final_wl, ydata = star_final_sed, marker ='g-') if cond_1 == 1 and cond_2 == 1: jexosim_msg ("interpolating spectra by temperature and logg", self.opt.diagnostics) #interp temp at logg0 wav_t0_logg0, flux_t0_logg0 = self.open_Phoenix(t0,logg0, self.star_f_h, self.sed_folder) wav_t1_logg0, flux_t1_logg0 = self.open_Phoenix(t1,logg0, self.star_f_h, self.sed_folder) sed_t0_logg0 = sed.Sed(wav_t0_logg0, flux_t0_logg0) sed_t1_logg0 = sed.Sed(wav_t1_logg0, flux_t1_logg0) # bin to same wav grid sed_t1_logg0.rebin(wav_t0_logg0) wt0 = 1 - abs(t0*100 - self.star_temperature.value)/abs(t0*100 - t1*100) wt1 = 1 - abs(self.star_temperature.value - t1*100)/abs(t0*100 - t1*100) sed_ = wt0*sed_t0_logg0.sed + wt1*sed_t1_logg0.sed sed_logg0 = sed.Sed(wav_t0_logg0, sed_) print (t0,t1) print (wt0,wt1) box = 1000 bbox = np.ones(box)/box jexosim_plot('temperature interpolation logg0', self.opt.diagnostics, xdata = wav_t0_logg0, \ ydata = np.convolve(flux_t0_logg0, bbox,'same'), marker ='r-') jexosim_plot('temperature interpolation logg0', self.opt.diagnostics, xdata = wav_t1_logg0, \ ydata = np.convolve(flux_t1_logg0, bbox,'same'), marker ='b-') jexosim_plot('temperature interpolation logg0', self.opt.diagnostics, xdata = sed_logg0.wl, \ ydata = np.convolve(sed_logg0.sed, bbox,'same'), marker ='g-') #interp temp at logg1 wav_t0_logg1, flux_t0_logg1 = self.open_Phoenix(t0,logg1, self.star_f_h, self.sed_folder) wav_t1_logg1, flux_t1_logg1 = self.open_Phoenix(t1,logg1, self.star_f_h, self.sed_folder) sed_t0_logg1 = sed.Sed(wav_t0_logg1, flux_t0_logg1) sed_t1_logg1 = sed.Sed(wav_t1_logg1, flux_t1_logg1) # bin to same wav grid sed_t1_logg1.rebin(wav_t0_logg1) wt0 = 1 - abs(t0*100 - self.star_temperature.value)/abs(t0*100 - t1*100) wt1 = 1 - abs(self.star_temperature.value - t1*100)/abs(t0*100 - t1*100) sed_ = wt0*sed_t0_logg1.sed + wt1*sed_t1_logg1.sed sed_logg1 = sed.Sed(wav_t0_logg1, sed_) box = 100 bbox = np.ones(box)/box jexosim_plot('temperature interpolation logg1', self.opt.diagnostics, xdata = wav_t0_logg1, \ ydata = np.convolve(flux_t0_logg1, bbox,'same'), marker ='r-') jexosim_plot('temperature interpolation logg1', self.opt.diagnostics, xdata = wav_t1_logg1, \ ydata = np.convolve(flux_t1_logg1, bbox,'same'), marker ='b-') jexosim_plot('temperature interpolation logg1', self.opt.diagnostics, xdata = sed_logg1.wl, \ ydata = np.convolve(sed_logg1.sed, bbox,'same'), marker ='g-') # now interp logg sed_logg1.rebin(sed_logg0.wl) wt0 = 1 - abs(logg0 - self.star_logg)/abs(logg0 - logg1) wt1 = 1 - abs(self.star_logg - logg1)/abs(logg0 - logg1) print (wt0,wt1) print (logg0,logg1) sed_final = wt0*sed_logg0.sed + wt1*sed_logg1.sed star_final_sed = sed_final star_final_wl = sed_logg0.wl box = 100 bbox = np.ones(box)/box jexosim_plot('interpolation between logg', self.opt.diagnostics, xdata = sed_logg0.wl, \ ydata = np.convolve(sed_logg0.sed, bbox,'same'), marker ='r-') jexosim_plot('interpolation between logg', self.opt.diagnostics, xdata = sed_logg1.wl, \ ydata = np.convolve(sed_logg1.sed, bbox,'same'), marker ='b-') jexosim_plot('interpolation between logg', self.opt.diagnostics, xdata = star_final_wl, \ ydata = np.convolve(star_final_sed, bbox,'same'), marker ='g-') if cond_1 == 0 and cond_2 == 1: jexosim_msg ("interpolating spectra by logg only", self.opt.diagnostics) #interp logg at t0 wav_t0_logg0, flux_t0_logg0 = self.open_Phoenix(t0,logg0, self.star_f_h, self.sed_folder) wav_t0_logg1, flux_t0_logg1 = self.open_Phoenix(t0,logg1, self.star_f_h, self.sed_folder) sed_t0_logg0 = sed.Sed(wav_t0_logg0, flux_t0_logg0) sed_t0_logg1 = sed.Sed(wav_t0_logg1, flux_t0_logg1) # bin to same wav grid sed_t0_logg1.rebin(wav_t0_logg0) wt0 = 1 - abs(logg0 - self.star_logg)/abs(logg0 - logg1) wt1 = 1 - abs(self.star_logg - logg1)/abs(logg0 - logg1) sed_final = wt0*sed_logg0.sed + wt1*sed_logg1.sed star_final_sed = sed_final star_final_wl = sed_t0_logg0.wl box = 100 bbox = np.ones(box)/box jexosim_plot('interpolation between logg', self.opt.diagnostics, xdata = sed_t0_logg0.wl, \ ydata = np.convolve(sed_t0_logg0.sed, bbox,'same'), marker ='r-') jexosim_plot('interpolation between logg', self.opt.diagnostics, xdata = sed_t0_logg1.wl, \ ydata = np.convolve(sed_t0_logg1.sed, bbox,'same'), marker ='b-') jexosim_plot('interpolation between logg', self.opt.diagnostics, xdata = star_final_wl, \ ydata = np.convolve(star_final_sed, bbox,'same'), marker ='g-') if cond_1 == 0 and cond_2 == 0: star_final_wl, star_final_sed = self.open_Phoenix(t0,logg0, self.star_f_h, self.sed_folder) return star_final_wl, star_final_sed
def extractSpec(self): jexosim_msg("extracting 1 D spectra....", self.opt.diagnostics) #============================================================================== # 1) initialise class objects a) noisy data, b) noiseless data if used, c) extraction of n_pix per bin #============================================================================== self.extractSpec = binning.extractSpec(self.opt.data, self.opt, self.opt.diff, self.ApFactor, 1) # 1 = final ap : means code knows this is the ap factor to use on noisy data and plots # final ap 0 = signal only or n_pix evals, so no figures for aperture on image plotted. if self.opt.pipeline.useSignal.val == 1: self.extractSpec_signal = binning.extractSpec( self.opt.data_signal_only, self.opt, 0, self.ApFactor, 0) #diff always 0 for signal # use a set of 3 images with 1 value for all pixels to find out no of pixels per bin self.extractSpec_nPix = binning.extractSpec( self.opt.data[..., 0:3] * 0 + 1, self.opt, 1, self.ApFactor, 0) #============================================================================== # 2) apply mask and extract 1D spectrum if apply mask selected # special case for NIRISS #============================================================================== if self.opt.pipeline.pipeline_apply_mask.val == 1: # a) noisy data jexosim_msg( "applying mask and extracting 1D spectrum from noisy data", self.opt.diagnostics) if self.opt.channel.instrument.val == 'NIRISS': self.extractSpec.applyMask_extract_1D_NIRISS() else: self.extractSpec.applyMask_extract_1D() # b) noiseless data if selected if self.opt.pipeline.useSignal.val == 1: jexosim_msg( "applying mask and extracting 1D spectrum from signal only data", self.opt.diagnostics) if self.opt.channel.instrument.val == 'NIRISS': self.extractSpec_signal.applyMask_extract_1D_NIRISS() else: self.extractSpec_signal.applyMask_extract_1D() # c) sample data to find n_pix per bin jexosim_msg( "applying mask and extracting 1D spectrum to find n_pix per bin", self.opt.diagnostics) if self.opt.channel.instrument.val == 'NIRISS': self.extractSpec_nPix.applyMask_extract_1D_NIRISS() else: jexosim_msg("extracting 1 D spectra for pixel in bin test", self.opt.diagnostics) self.extractSpec_nPix.applyMask_extract_1D() #============================================================================== # 3) extract 1D spectrum only if no mask selected #============================================================================== else: # a) noisy data jexosim_msg( "NOT applying mask and extracting 1D spectrum from noisy data", self.opt.diagnostics) self.extractSpec.extract1DSpectra() # b) noiseless data if selected if self.opt.pipeline.useSignal.val == 1: jexosim_msg( "NOT applying mask and extracting 1D spectrum from signal only data", self.opt.diagnostics) self.extractSpec_signal.extract1DSpectra() # c) sample data to find n_pix per bin jexosim_msg( "NOT applying mask and extracting 1D spectrum to find n_pix per bin", self.opt.diagnostics) self.extractSpec_nPix.extract1DSpectra() self.nPix_1 = self.extractSpec_nPix.spectra[0] jexosim_plot('n_pix per pixel column', self.opt.diagnostics, xdata=self.opt.cr_wl.value, ydata=self.nPix_1, marker='bo') #============================================================================== # 4) Now bin into spectral bins #============================================================================== # a) noisy data jexosim_msg("binning 1D spectra into spectral bins... from noisy data", self.opt.diagnostics) self.extractSpec.binSpectra() # b) noiseless data if selected if self.opt.pipeline.useSignal.val == 1: jexosim_msg( "binning 1D spectra into spectral bins... from signal only data", self.opt.diagnostics) self.extractSpec_signal.binSpectra() # c) sample data to find n_pix per bin jexosim_msg( "binning 1D spectra into spectral bins... to find n_pix per bin", self.opt.diagnostics) self.extractSpec_nPix.binSpectra() #============================================================================== # 5) Define objects from binning process #============================================================================== self.binnedLC = self.extractSpec.binnedLC self.binnedWav = self.extractSpec.binnedWav if self.opt.pipeline.useSignal.val == 1: self.binnedLC_signal = self.extractSpec_signal.binnedLC self.binnedWav_signal = self.extractSpec_signal.binnedWav else: self.binnedLC_signal = self.binnedLC self.binnedWav_signal = self.binnedWav if self.opt.timeline.apply_lc.val == 1: self.extractSpec.binGamma() self.binnedGamma = self.extractSpec.binnedGamma self.nPix_2 = self.extractSpec_nPix.binnedLC[0] jexosim_plot('n_pix per bin', self.opt.diagnostics, xdata=self.binnedWav, ydata=self.nPix_2, marker='ro')
def __init__(self, opt): self.opt = opt self.exp_end_time_grid = self.opt.ndr_end_time[ self.opt.effective_multiaccum - 1::self.opt.effective_multiaccum] self.ndr_end_time_grid = self.opt.ndr_end_time self.opt.data_raw = opt.data * 1 self.ApFactor = opt.pipeline.pipeline_ap_factor.val if opt.background.EnableSource.val == 1: self.opt.diff = 0 else: self.opt.diff = 1 self.loadData() opt.init_pix = np.zeros(opt.data[ ..., 0].shape) # placeholder - replace with initial bad pixel map self.dqInit() self.satFlag() if (opt.background.EnableDC.val == 1 or opt.background.EnableAll.val == 1) and opt.background.DisableAll.val != 1: if opt.diff == 0: self.subDark() if (opt.noise.ApplyPRNU.val == 1 or opt.noise.EnableAll.val == 1) and opt.noise.DisableAll.val != 1: jexosim_msg( "mean and standard deviation of qe grid %s %s" % (opt.qe_grid.mean(), opt.qe_grid.std()), opt.diagnostics) self.flatField() if (opt.background.EnableZodi.val == 1 or opt.background.EnableSunshield.val == 1 or opt.background.EnableEmission.val == 1 or opt.background.EnableAll.val == 1) and opt.background.DisableAll.val != 1: if opt.diff == 0: self.subBackground() jexosim_plot('sample NDR image', opt.diagnostics, image=True, image_data=self.opt.data[..., 1]) self.doUTR() # lose astropy units at this step jexosim_plot('sample exposure image', opt.diagnostics, image=True, image_data=self.opt.data[..., 1]) # currently this applies zero values to saturated pixels self.badCorr() # exp image obtained here if (opt.noise.EnableSpatialJitter.val == 1 or opt.noise.EnableSpectralJitter.val == 1 or opt.noise.EnableAll.val == 1) and opt.noise.DisableAll.val != 1: jexosim_msg("Decorrelating pointing jitter...", opt.diagnostics) self.jitterDecorr() if opt.pipeline.pipeline_apply_mask.val == 1: if opt.pipeline.pipeline_auto_ap.val == 1: self.autoSizeAp() self.extractSpec()
def autoSizeAp(self): F = self.opt.channel.camera.wfno_x.val wl_max = self.opt.channel.pipeline_params.wavrange_hi.val wl_min = self.opt.channel.pipeline_params.wavrange_lo.val wl = self.opt.cr_wl.value if self.opt.timeline.apply_lc.val == 0: x = 100 if self.opt.data.shape[2] < x: # has to use the noisy data x = self.opt.data.shape[2] sample = self.opt.data[..., 0:x] elif self.opt.timeline.apply_lc.val == 1: # must use OOT portions else the transit will contribute falsely to the stand dev if self.opt.pipeline.split == 0: # can only use the pre-transit values total_obs_time = self.opt.exposure_time * self.opt.n_exp pre_transit_time = self.opt.observation.obs_frac_t14_pre_transit.val * self.opt.T14 post_transit_time = self.opt.observation.obs_frac_t14_post_transit.val * self.opt.T14 pre_transit_exp = self.opt.n_exp * pre_transit_time / total_obs_time post_transit_exp = self.opt.n_exp * post_transit_time / total_obs_time x0 = int(pre_transit_exp * 0.75) if x0 > 20: x0 = 20 x1 = int(post_transit_exp * 0.75) if x1 > 20: x1 = 20 sample1 = self.opt.data[..., 0:x0] sample2 = self.opt.data[..., -x1:] sample = np.dstack((sample1, sample2)) if self.opt.pipeline.split == 1: # can only use the pre-transit values total_obs_time = self.opt.exposure_time * self.opt.n_exp pre_transit_time = self.opt.observation.obs_frac_t14_pre_transit.val * self.opt.T14 pre_transit_exp = pre_transit_time / self.opt.exposure_time if self.opt.n_exp < pre_transit_exp: x0 = int(self.opt.n_exp * 0.75) else: x0 = int(pre_transit_exp * 0.75) if x0 > 40: x0 = 40 sample = self.opt.data[..., 0:x0] # print (sample.shape) # zero_check = sample.sum(axis=0) # zero_check = zero_check.sum(axis=1) # idx_zero = np.argwhere(zero_check==0) # sample = np.delete(sample, idx_zero, axis=1) # print (sample.shape) # print (idx_zero) # idx_zero_0 = idx_zero[0].item() # idx_zero_1 = idx_zero[-1].item() # print (idx_zero_0, idx_zero_1) # print (zero_check[idx_zero_0], zero_check[idx_zero_1]) # import matplotlib.pyplot as plt # plt.figure('zero_check') # plt.plot(zero_check) # xxxx jexosim_msg("SAMPLE SHAPE %s %s %s" % (sample.shape), self.opt.diagnostics) pix_size = (self.opt.channel.detector_pixel.pixel_size.val).to( u.um).value y_width = self.opt.data.shape[0] * pix_size testApFactorMax = int(int(y_width / 2.) / (F * wl_max)) if (testApFactorMax * F * wl_max / pix_size) + 1 >= self.opt.data.shape[0] / 2: testApFactorMax = int( ((self.opt.data.shape[0] / 2) - 1) * pix_size / (F * wl_max)) ApList = np.arange(1.0, testApFactorMax + 1, 1.0) if self.opt.channel.instrument.val == 'NIRISS': testApFactorMax = 18.0 # set empirically ApList = np.arange(7.0, testApFactorMax + 1, 1.0) jexosim_msg("maximum test ap factor %s" % (testApFactorMax), self.opt.diagnostics) for i in ApList: testApFactor = 1.0 * i jexosim_msg("test ApFactor %s" % (testApFactor), self.opt.diagnostics) self.extractSample = binning.extractSpec(sample, self.opt, self.opt.diff, testApFactor, 2) if self.opt.channel.instrument.val == 'NIRISS': self.extractSample.applyMask_extract_1D_NIRISS() else: self.extractSample.applyMask_extract_1D() spectra = self.extractSample.spectra self.extractSample.binSpectra() binnedLC = self.extractSample.binnedLC wl = self.extractSample.binnedWav SNR = binnedLC.mean(axis=0) / binnedLC.std(axis=0) if i == ApList[0]: SNR_stack = SNR else: SNR_stack = np.vstack((SNR_stack, SNR)) jexosim_plot('test aperture SNR', self.opt.diagnostics, xdata=wl, ydata=SNR, label=testApFactor) idx = np.argwhere((wl >= wl_min) & (wl <= wl_max)) SNR_stack = SNR_stack[:, idx][..., 0] wl = wl[idx].T[0] wl0 = wl nan_check = SNR_stack.sum(axis=0) nan_idx = np.argwhere(np.isnan(nan_check)) SNR_stack = np.delete(SNR_stack, nan_idx, axis=1) wl0 = np.delete(wl, nan_idx) zero_check = SNR_stack.sum(axis=0) zero_idx = np.argwhere(zero_check == 0) SNR_stack = np.delete(SNR_stack, zero_idx, axis=1) wl0 = np.delete(wl0, zero_idx) best = [] for i in range(SNR_stack.shape[1]): aa = SNR_stack[:, i] # jexosim_msg i, np.argmax(aa), ApList[np.argmax(aa)] best.append(ApList[np.argmax(aa)]) jexosim_plot('highest SNR aperture vs wavelength', self.opt.diagnostics, xdata=wl0, ydata=best, marker='bo-') AvBest = np.round(np.mean(best), 0) jexosim_msg("average best aperture factor %s" % (AvBest), self.opt.diagnostics) self.opt.AvBest = AvBest self.ApFactor = AvBest self.opt.pipeline.pipeline_ap_factor.val = self.ApFactor
def __init__(self, opt): output_directory = opt.common.output_directory.val filename = "" runtag = int(np.random.uniform(0, 100000)) self.results_dict = {} self.results_dict['simulation_mode'] = opt.simulation.sim_mode.val self.results_dict[ 'simulation_realisations'] = opt.simulation.sim_realisations.val self.results_dict['ch'] = opt.observation.obs_channel.val opt.pipeline.useSignal.val = 0 opt.simulation.sim_use_fast.val = 1 opt.pipeline.split = 0 opt.noise.ApplyRandomPRNU.val = 1 opt.timeline.apply_lc.val = 1 opt.timeline.useLDC.val = 1 opt.pipeline.useAllen.val = 0 opt.pipeline.fit_gamma.val = 0 #keep zero for uncert on p start = 0 end = int(start + opt.no_real) if (opt.no_real - start) > 1: jexosim_msg("Monte Carlo selected", 1) opt = self.run_JexoSimA(opt) # np.save('/Users/user1/Desktop/fp_signal.npy', opt.fp_signal[1::3,1::3].value) # np.save('/Users/user1/Desktop/fp_wav.npy', opt.x_wav_osr[1::3].value) # xxxx if opt.observation_feasibility == 0: jexosim_msg("Observation not feasible...", opt.diagnostics) self.feasibility = 0 else: self.feasibility = 1 n_ndr0 = opt.n_ndr * 1 ndr_end_frame_number0 = opt.ndr_end_frame_number * 1 frames_per_ndr0 = opt.frames_per_ndr * 1 duration_per_ndr0 = opt.duration_per_ndr * 1 n_exp0 = opt.n_exp lc0 = opt.lc_original * 1 # important this happens at this stage if n_ndr0 > 10000: opt.pipeline.split = 1 if opt.diagnostics == 1: jexosim_msg('number of NDRs > 10000: using split protocol', opt.diagnostics) else: opt.pipeline.split = 0 # #delete # opt.pipeline.split = 1 for j in range(start, end): if (opt.no_real - start) > 1: jexosim_msg("", 1) jexosim_msg( "============= REALIZATION %s =============" % (j), 1) jexosim_msg(opt.lab, 1) jexosim_msg("", 1) pp = time.time() opt = self.run_JexoSimA1( opt) # set QE grid for this realization jexosim_msg("QE variations set", 1) jexosim_msg("Number of exposures %s" % (n_exp0), 1) print(opt.diagnostics) # ============================================================================= # # split simulation into chunks to permit computation - makes no difference to final results # ============================================================================= if opt.pipeline.split == 1: jexosim_msg('Splitting data series into chunks', opt.diagnostics) # uses same QE grid and jitter timeline but otherwise randomoses noise ndrs_per_round = opt.effective_multiaccum * int( 5000 / opt.multiaccum) # ndrs_per_round = opt.effective_multiaccum*int(500/opt.multiaccum) total_chunks = len(np.arange(0, n_ndr0, ndrs_per_round)) idx = np.arange(0, n_ndr0, ndrs_per_round) # list of starting ndrs for i in range(len(idx)): jexosim_msg( '=== Realisation %s Chunk %s / %s=====' % (j, i + 1, total_chunks), 1) jexosim_msg(opt.lab, 1) if idx[i] == idx[-1]: opt.n_ndr = n_ndr0 - idx[i] opt.lc_original = lc0[:, idx[i]:] opt.ndr_end_frame_number = ndr_end_frame_number0[ idx[i]:] opt.frames_per_ndr = frames_per_ndr0[idx[i]:] opt.duration_per_ndr = duration_per_ndr0[idx[i]:] else: opt.n_ndr = idx[i + 1] - idx[i] opt.lc_original = lc0[:, idx[i]:idx[i + 1]] print('idx start......', idx[i]) opt.ndr_end_frame_number = ndr_end_frame_number0[ idx[i]:idx[i + 1]] opt.frames_per_ndr = frames_per_ndr0[idx[i]:idx[i + 1]] opt.duration_per_ndr = duration_per_ndr0[ idx[i]:idx[i + 1]] opt.n_exp = int(opt.n_ndr / opt.effective_multiaccum) if i == 0: opt.pipeline.pipeline_auto_ap.val = 1 opt.use_external_jitter = 0 opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) opt.pipeline.pipeline_ap_factor.val = opt.AvBest if (opt.noise.EnableSpatialJitter.val == 1 or opt.noise.EnableSpectralJitter.val == 1 or opt.noise.EnableAll.val == 1) and opt.noise.DisableAll.val != 1: opt.input_yaw_jitter, opt.input_pitch_jitter, opt._input_frame_osf = opt.yaw_jitter, opt.pitch_jitter, opt.frame_osf else: opt.pipeline.pipeline_auto_ap.val = 0 opt.use_external_jitter = 1 # uses the jitter timeline from the first realization opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) jexosim_msg( 'Aperture used %s' % (opt.pipeline.pipeline_ap_factor.val), opt.diagnostics) binnedLC = opt.pipeline_stage_1.binnedLC data = opt.pipeline_stage_1.opt.data_raw if i == 0: data_stack = data * 1 binnedLC_stack = binnedLC * 1 else: data_stack = np.dstack((data_stack, data)) binnedLC_stack = np.vstack( (binnedLC_stack, binnedLC)) del data del binnedLC aa = data_stack.sum(axis=0) bb = aa.sum(axis=0) jexosim_plot('test_from_sim', opt.diagnostics, ydata=bb[opt.effective_multiaccum::opt. effective_multiaccum]) aa = binnedLC_stack.sum(axis=1) jexosim_plot('test_from_pipeline', opt.diagnostics, ydata=aa) opt.n_ndr = n_ndr0 opt.ndr_end_frame_number = ndr_end_frame_number0 opt.frames_per_ndr = frames_per_ndr0 opt.duration_per_ndr = duration_per_ndr0 opt.n_exp = n_exp0 elif opt.pipeline.split == 0: opt = self.run_JexoSimB(opt) if j == start: # first realization sets the ap, then the other use the same one opt.pipeline.pipeline_auto_ap.val = 1 else: opt.pipeline.pipeline_auto_ap.val = 0 opt = self.run_pipeline_stage_1(opt) if j == start: # first realization sets the ap, then the other use the same one opt.pipeline.pipeline_ap_factor.val = opt.AvBest binnedLC_stack = opt.pipeline_stage_1.binnedLC jexosim_plot('testvvv', opt.diagnostics, ydata=binnedLC_stack.sum(axis=1)) opt.pipeline_stage_1.binnedLC = binnedLC_stack opt = self.run_pipeline_stage_2(opt) pipeline = opt.pipeline_stage_2 p = pipeline.transitDepths if j == start: p_stack = p else: p_stack = np.vstack((p_stack, p)) jexosim_msg( "time to complete realization %s %s" % (j, time.time() - pp), opt.diagnostics) self.results_dict['wl'] = pipeline.binnedWav self.results_dict['input_spec'] = opt.cr self.results_dict['input_spec_wl'] = opt.cr_wl if j == start: # if only one realisation slightly different format self.results_dict['p_stack'] = np.array(p) self.results_dict['p_std'] = np.zeros(len(p)) self.results_dict['p_mean'] = np.array(p) else: self.results_dict['p_stack'] = np.vstack( (self.results_dict['p_stack'], p)) self.results_dict['p_std'] = self.results_dict[ 'p_stack'].std(axis=0) self.results_dict['p_mean'] = self.results_dict[ 'p_stack'].mean(axis=0) time_tag = (datetime.now().strftime('%Y_%m_%d_%H%M_%S')) self.results_dict['time_tag'] = time_tag self.results_dict['bad_map'] = opt.bad_map self.results_dict['example_exposure_image'] = opt.exp_image self.results_dict['pixel wavelengths'] = opt.x_wav_osr[ 1::3].value self.results_dict['focal_plane_star_signal'] = opt.fp_signal[ 1::3, 1::3].value # fq = '/Users/user1/Desktop/tempGit/JexoSim_A/output/Full_eclipse_MIRI_LRS_slitless_SLITLESSPRISM_FAST_HD_209458_b_2021_07_18_0852_28.pickle' # with open(fq, 'rb') as handle: # rd = pickle.load(handle) # rd['focal_plane_star_signal'] = opt.fp_signal[1::3,1::3] # rd['pixel wavelengths'] = opt.x_wav_osr[1::3].value # with open(fq, 'wb') as handle: # pickle.dump(rd , handle, protocol=pickle.HIGHEST_PROTOCOL) # run('Full_transit_NIRSpec_BOTS_G140M_F100LP_SUB2048_NRSRAPID_K2-18_b_2021_07_18_1402_38.pickle',0) # run('Full_transit_NIRSpec_BOTS_G235M_F170LP_SUB2048_NRSRAPID_K2-18_b_2021_07_18_0709_24.pickle', 2) # run('Full_transit_NIRSpec_BOTS_G395M_F290LP_SUB2048_NRSRAPID_K2-18_b_2021_07_17_2339_51.pickle',4) # run('Full_eclipse_NIRCam_TSGRISM_F444W_SUBGRISM64_4_output_RAPID_HD_209458_b_2021_07_19_0654_29.pickle',0) # run('Full_eclipse_NIRCam_TSGRISM_F322W2_SUBGRISM64_4_output_RAPID_HD_209458_b_2021_07_19_0359_08.pickle',1) # run('Full_eclipse_MIRI_LRS_slitless_SLITLESSPRISM_FAST_HD_209458_b_2021_07_18_0852_28.pickle', 2) if j != start: os.remove(filename) # delete previous temp file filename = '%s/Full_transit_%s_TEMP%s.pickle' % ( output_directory, opt.lab, runtag) if opt.observation.obs_type.val == 2: filename = '%s/Full_eclipse_%s_TEMP%s.pickle' % ( output_directory, opt.lab, runtag) with open(filename, 'wb') as handle: pickle.dump(self.results_dict, handle, protocol=pickle.HIGHEST_PROTOCOL) del pipeline del binnedLC_stack gc.collect() os.remove(filename) # delete previous temp file # write final file filename = '%s/Full_transit_%s_%s.pickle' % (output_directory, opt.lab, time_tag) if opt.observation.obs_type.val == 2: filename = '%s/Full_eclipse_%s_%s.pickle' % (output_directory, opt.lab, time_tag) with open(filename, 'wb') as handle: pickle.dump(self.results_dict, handle, protocol=pickle.HIGHEST_PROTOCOL) jexosim_msg('Results in %s' % (filename), 1) self.filename = 'Full_transit_%s_%s.pickle' % (opt.lab, time_tag) if opt.observation.obs_type.val == 2: self.filename = 'Full_eclipse_%s_%s.pickle' % (opt.lab, time_tag) write_record(opt, output_directory, self.filename, opt.params_file_path)
def run(opt): jexosim_msg('Running backgrounds module ...\n ', opt.diagnostics) opt.zodi, zodi_transmission = backgrounds_lib.zodical_light(opt) opt.emission = backgrounds_lib.optical_emission(opt) opt.sunshield = backgrounds_lib.sunshield_emission(opt) # import matplotlib.pyplot as plt # plt.figure ('backgrounds 1') # plt.plot(opt.sunshield.wl, opt.sunshield.sed, 'r', label='sunshield before transmission') # plt.plot(opt.zodi.wl, opt.zodi.sed, 'g--', label='zodi before transmission') # plt.plot(opt.emission.wl, opt.emission.sed ,'bx', label = 'optical after transmission') # plt.grid() # plt.legend() # propagate star through zodi transmission jexosim_lib.sed_propagation(opt.star.sed, zodi_transmission) ch = opt.channel Omega_pix = 2.0 * np.pi * ( 1.0 - np.cos(np.arctan(0.5 / ch.camera.wfno_x()))) * u.sr Apix = ((ch.detector_pixel.pixel_size.val).to(u.m))**2 opt.zodi.sed *= Apix * Omega_pix * opt.Re * u.electron / u.W / u.s opt.sunshield.sed *= Apix * Omega_pix * opt.Re * u.electron / u.W / u.s opt.emission.sed *= Apix * Omega_pix * opt.Re * u.electron / u.W / u.s # apply transmission to zodi and sunshield (not to optical emission -alreay applied) jexosim_lib.sed_propagation(opt.zodi, opt.total_transmission) jexosim_lib.sed_propagation(opt.sunshield, opt.total_transmission) opt.zodi.sed[np.isnan(opt.zodi.sed)] = 0 opt.sunshield.sed[np.isnan(opt.sunshield.sed)] = 0 opt.emission.sed[np.isnan(opt.emission.sed)] = 0 opt.zodi.sed *= opt.d_x_wav_osr opt.sunshield.sed *= opt.d_x_wav_osr opt.emission.sed *= opt.d_x_wav_osr zodi_photons_sed = copy.deepcopy(opt.zodi.sed) sunshield_photons_sed = copy.deepcopy(opt.sunshield.sed) emission_photons_sed = copy.deepcopy(opt.emission.sed) if ch.camera.slit_width.val == 0: slit_size = opt.fpn[ 1] * 2 # to ensure all wavelengths convolved onto all pixels in slitless case else: slit_size = ch.camera.slit_width.val # import matplotlib.pyplot as plt # plt.figure ('backgrounds 2') # plt.plot(opt.zodi.wl, opt.zodi.sed, 'bo-') # print (opt.zodi.sed) # need to work on this to make more accurate : filter wavelength range might not correspond to wl sol on the detector, i.e. some wavelengths not being included that should be opt.zodi.sed = scipy.signal.convolve( opt.zodi.sed, np.ones(np.int(slit_size * ch.simulation_factors.osf())), 'same') * opt.zodi.sed.unit opt.sunshield.sed = scipy.signal.convolve( opt.sunshield.sed, np.ones(np.int(slit_size * ch.simulation_factors.osf())), 'same') * opt.sunshield.sed.unit opt.emission.sed = scipy.signal.convolve( opt.emission.sed.value, np.ones(np.int(slit_size * ch.simulation_factors.osf())), 'same') * opt.emission.sed.unit # print (opt.zodi.sed) # import matplotlib.pyplot as plt # plt.figure ('backgrounds 2') # plt.plot(opt.zodi.wl, opt.zodi.sed, 'ro-') # xxxx opt.zodi_sed_original = copy.deepcopy(opt.zodi.sed) opt.sunshield_sed_original = copy.deepcopy(opt.sunshield.sed) opt.emission_sed_original = copy.deepcopy(opt.emission.sed) jexosim_plot('zodi spectrum', opt.diagnostics, xdata=opt.zodi.wl, ydata=opt.zodi.sed) jexosim_plot('sunshield spectrum', opt.diagnostics, xdata=opt.sunshield.wl, ydata=opt.sunshield.sed) jexosim_plot('emission spectrum', opt.diagnostics, xdata=opt.emission.wl, ydata=opt.emission.sed) # ====Now work out quantum yield ============================================== # weight the qy by relative number of photons zodi_w_qy = zodi_photons_sed * opt.quantum_yield.sed # convolve this with slit zodi_w_qy = scipy.signal.convolve( zodi_w_qy, np.ones(np.int(slit_size * ch.simulation_factors.osf())), 'same') * opt.zodi.sed.unit # divide by convolved spectrum.... thus this factor will return the expected qy opt.qy_zodi = zodi_w_qy / opt.zodi.sed # (Ph conv. slit )x Qy' = (Ph x Qy) conv. slit # thus Qy' is the needed Qy per pixel applied to the convolve Ph spectrum. sunshield_w_qy = sunshield_photons_sed * opt.quantum_yield.sed sunshield_w_qy = scipy.signal.convolve( sunshield_w_qy, np.ones(np.int( slit_size * ch.simulation_factors.osf())), 'same') * opt.sunshield.sed.unit opt.qy_sunshield = sunshield_w_qy / opt.sunshield.sed emission_w_qy = emission_photons_sed * opt.quantum_yield.sed emission_w_qy = scipy.signal.convolve( emission_w_qy, np.ones(np.int( slit_size * ch.simulation_factors.osf())), 'same') * opt.emission.sed.unit opt.qy_emission = emission_w_qy / opt.emission.sed opt.qy_zodi[np.isnan(opt.qy_zodi)] = 1 opt.qy_sunshield[np.isnan(opt.qy_sunshield)] = 1 opt.qy_emission[np.isnan(opt.qy_emission)] = 1 return opt
def run(opt): opt.fp = copy.deepcopy( opt.fp_original ) # needed to reuse if cropped fp is used and monte carlo mode used opt.fp_signal = copy.deepcopy(opt.fp_signal_original) # " opt.zodi.sed = copy.deepcopy(opt.zodi_sed_original) # " opt.sunshield.sed = copy.deepcopy(opt.sunshield_sed_original) # " opt.emission.sed = copy.deepcopy(opt.emission_sed_original) # " opt.lc = copy.deepcopy(opt.lc_original) opt.ldc = copy.deepcopy(opt.ldc_original) opt.cr_wl = copy.deepcopy(opt.cr_wl_original) opt.cr = copy.deepcopy(opt.cr_original) opt.x_wav_osr = copy.deepcopy(opt.x_wav_osr_original) opt.x_pix_osr = copy.deepcopy(opt.x_pix_osr_original) opt.qe = copy.deepcopy(opt.qe_original) opt.qe_uncert = copy.deepcopy(opt.qe_uncert_original) opt.quantum_yield = copy.deepcopy(opt.quantum_yield_original) opt.qy_zodi = copy.deepcopy(opt.qy_zodi_original) opt.qy_sunshield = copy.deepcopy(opt.qy_sunshield_original) opt.qy_emission = copy.deepcopy(opt.qy_emission_original) opt.syst_grid = copy.deepcopy(opt.syst_grid_original) opt = signal_lib.initiate_signal(opt) opt = signal_lib.apply_jitter(opt) # opt.signal iniatated here opt = signal_lib.apply_lc(opt) opt = signal_lib.initiate_noise(opt) opt = signal_lib.apply_non_stellar_photons(opt) opt = signal_lib.apply_prnu(opt) opt = signal_lib.apply_dc(opt) opt = signal_lib.apply_poisson_noise(opt) opt = signal_lib.apply_quantum_yield(opt) opt = signal_lib.apply_fano(opt) opt = signal_lib.apply_utr_correction(opt) opt = signal_lib.apply_combined_noise(opt) opt = signal_lib.make_ramps(opt) opt = signal_lib.apply_ipc(opt) opt = signal_lib.apply_read_noise(opt) opt = signal_lib.apply_gaps(opt) opt.data = opt.signal opt.data_signal_only = opt.signal_only jexosim_plot('focal plane check1', opt.diagnostics, image=True, image_data=opt.fp_signal[1::3, 1::3], aspect='auto', interpolation=None, xlabel='x \'spectral\' pixel', ylabel='y \'spatial\' pixel') jexosim_plot('test - check NDR0', opt.diagnostics, image=True, image_data=opt.data[..., 0]) jexosim_plot('test - check NDR1', opt.diagnostics, image=True, image_data=opt.data[..., 1]) return opt
def get_light_curve(opt, planet_sed, wavelength, obs_type): wavelength = wavelength.value timegrid = opt.z_params[0] t0 = opt.z_params[1] per = opt.z_params[2] ars = opt.z_params[3] inc = opt.z_params[4] ecc = opt.z_params[5] omega = opt.z_params[6] if opt.observation.obs_type.val == 2: opt.timeline.useLDC.val = 0 if opt.timeline.useLDC.val == 0: # linear ldc jexosim_msg('LDCs set to zero', 1) u0 = np.zeros(len(wavelength)) u1 = np.zeros(len(wavelength)) ldc = np.vstack((wavelength, u0, u1)) elif opt.timeline.useLDC.val == 1: # use to get ldc from filed values u0, u1 = getLDC_interp(opt, opt.planet.planet, wavelength) ldc = np.vstack((wavelength, u0, u1)) gamma = np.zeros((ldc.shape[1], 2)) gamma[:, 0] = ldc[1] gamma[:, 1] = ldc[2] jexosim_plot('ldc', opt.diagnostics, ydata=ldc[1]) jexosim_plot('ldc', opt.diagnostics, ydata=ldc[2]) tm = QuadraticModel(interpolate=False) tm.set_data(timegrid) lc = np.zeros((len(planet_sed), len(timegrid))) if obs_type == 1: #primary transit for i in range(len(planet_sed)): k = np.sqrt(planet_sed[i]).value lc[i, ...] = tm.evaluate(k=k, ldc=gamma[i, ...], t0=t0, p=per, a=ars, i=inc, e=ecc, w=omega) jexosim_plot('light curve check', opt.diagnostics, ydata=lc[i, ...]) elif obs_type == 2: # secondary eclipse for i in range(len(planet_sed)): k = np.sqrt(planet_sed[i]) # planet star radius ratio lc_base = tm.evaluate(k=k, ldc=[0, 0], t0=t0, p=per, a=ars, i=inc, e=ecc, w=omega) jexosim_plot('light curve check', opt.diagnostics, ydata=lc_base) # f_e = (planet_sed[i] + ( lc_base -1.0))/planet_sed[i] # lc[i, ...] = 1.0 + f_e*(planet_sed[i]) lc[i, ...] = lc_base + planet_sed[i] jexosim_plot('light curve check', opt.diagnostics, ydata=lc[i, ...]) return lc, ldc
def __init__(self, opt): output_directory = opt.common.output_directory.val filename = "" self.results_dict = {} self.results_dict['simulation_mode'] = opt.simulation.sim_mode.val self.results_dict[ 'simulation_realisations'] = opt.simulation.sim_realisations.val self.results_dict['ch'] = opt.observation.obs_channel.val opt.pipeline.useSignal.val = 0 opt.simulation.sim_use_fast.val = 1 opt.pipeline.split = 0 opt.noise.ApplyRandomPRNU.val = 1 opt.timeline.apply_lc.val = 1 opt.timeline.useLDC.val = 1 opt.pipeline.useAllen.val = 0 opt.pipeline.fit_gamma.val = 0 #keep zero for uncert on p start = 0 end = int(start + opt.no_real) if (opt.no_real - start) > 1: jexosim_msg("Monte Carlo selected", 1) opt = self.run_JexoSimA(opt) if opt.observation_feasibility == 0: jexosim_msg("Observation not feasible...", opt.diagnostics) self.feasibility = 0 else: self.feasibility = 1 n_ndr0 = opt.n_ndr * 1 ndr_end_frame_number0 = opt.ndr_end_frame_number * 1 frames_per_ndr0 = opt.frames_per_ndr * 1 duration_per_ndr0 = opt.duration_per_ndr * 1 n_exp0 = opt.n_exp lc0 = opt.lc_original * 1 # important this happens at this stage if n_ndr0 > 10000: opt.pipeline.split = 1 if opt.diagnostics == 1: jexosim_msg('number of NDRs > 10000: using split protocol', opt.diagnostics) else: opt.pipeline.split = 0 # #delete # opt.pipeline.split = 1 for j in range(start, end): if (opt.no_real - start) > 1: jexosim_msg("", 1) jexosim_msg( "============= REALIZATION %s =============" % (j), 1) jexosim_msg(opt.lab, 1) jexosim_msg("", 1) pp = time.time() opt = self.run_JexoSimA1( opt) # set QE grid for this realization jexosim_msg("QE variations set", 1) jexosim_msg("Number of exposures %s" % (n_exp0), 1) # ============================================================================= # # split simulation into chunks to permit computation - makes no difference to final results # ============================================================================= if opt.pipeline.split == 1: jexosim_msg('Splitting data series into chunks', opt.diagnostics) # uses same QE grid and jitter timeline but otherwise randomoses noise ndrs_per_round = opt.effective_multiaccum * int( 5000 / opt.multiaccum) # ndrs_per_round = opt.effective_multiaccum*int(500/opt.multiaccum) total_chunks = len(np.arange(0, n_ndr0, ndrs_per_round)) idx = np.arange(0, n_ndr0, ndrs_per_round) # list of starting ndrs for i in range(len(idx)): jexosim_msg( '=== Realisation %s Chunk %s / %s=====' % (j, i + 1, total_chunks), opt.diagnostics) if idx[i] == idx[-1]: opt.n_ndr = n_ndr0 - idx[i] opt.lc_original = lc0[:, idx[i]:] opt.ndr_end_frame_number = ndr_end_frame_number0[ idx[i]:] opt.frames_per_ndr = frames_per_ndr0[idx[i]:] opt.duration_per_ndr = duration_per_ndr0[idx[i]:] else: opt.n_ndr = idx[i + 1] - idx[i] opt.lc_original = lc0[:, idx[i]:idx[i + 1]] print('idx start......', idx[i]) opt.ndr_end_frame_number = ndr_end_frame_number0[ idx[i]:idx[i + 1]] opt.frames_per_ndr = frames_per_ndr0[idx[i]:idx[i + 1]] opt.duration_per_ndr = duration_per_ndr0[ idx[i]:idx[i + 1]] opt.n_exp = int(opt.n_ndr / opt.effective_multiaccum) if i == 0: opt.pipeline.pipeline_auto_ap.val = 1 opt.use_external_jitter = 0 opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) opt.pipeline.pipeline_ap_factor.val = opt.AvBest if (opt.noise.EnableSpatialJitter.val == 1 or opt.noise.EnableSpectralJitter.val == 1 or opt.noise.EnableAll.val == 1) and opt.noise.DisableAll.val != 1: opt.input_yaw_jitter, opt.input_pitch_jitter, opt._input_frame_osf = opt.yaw_jitter, opt.pitch_jitter, opt.frame_osf else: opt.pipeline.pipeline_auto_ap.val = 0 opt.use_external_jitter = 1 # uses the jitter timeline from the first realization opt = self.run_JexoSimB(opt) opt = self.run_pipeline_stage_1(opt) jexosim_msg( 'Aperture used %s' % (opt.pipeline.pipeline_ap_factor.val), opt.diagnostics) binnedLC = opt.pipeline_stage_1.binnedLC data = opt.pipeline_stage_1.opt.data_raw if i == 0: data_stack = data binnedLC_stack = binnedLC else: data_stack = np.dstack((data_stack, data)) binnedLC_stack = np.vstack( (binnedLC_stack, binnedLC)) aa = data_stack.sum(axis=0) bb = aa.sum(axis=0) jexosim_plot('test_from_sim', opt.diagnostics, ydata=bb[opt.effective_multiaccum::opt. effective_multiaccum]) aa = binnedLC_stack.sum(axis=1) jexosim_plot('test_from_pipeline', opt.diagnostics, ydata=aa) opt.n_ndr = n_ndr0 opt.ndr_end_frame_number = ndr_end_frame_number0 opt.frames_per_ndr = frames_per_ndr0 opt.duration_per_ndr = duration_per_ndr0 opt.n_exp = n_exp0 elif opt.pipeline.split == 0: opt = self.run_JexoSimB(opt) if j == start: # first realization sets the ap, then the other use the same one opt.pipeline.pipeline_auto_ap.val = 1 else: opt.pipeline.pipeline_auto_ap.val = 0 opt = self.run_pipeline_stage_1(opt) if j == start: # first realization sets the ap, then the other use the same one opt.pipeline.pipeline_ap_factor.val = opt.AvBest binnedLC_stack = opt.pipeline_stage_1.binnedLC jexosim_plot('testvvv', opt.diagnostics, ydata=binnedLC_stack.sum(axis=1)) # ============================================================================= # Now put intermediate data (binned light curves) into FITS files # ============================================================================= opt.pipeline_stage_1.binnedLC *= u.electron opt.pipeline_stage_1.binnedWav *= u.um self.filename = output.run(opt) write_record(opt, output_directory, self.filename, opt.params_file_path) jexosim_msg( 'File saved as %s/%s' % (output_directory, self.filename), 1)