From b5500b685907514576991e07360fbb575d6f59c3 Mon Sep 17 00:00:00 2001 From: "Maxwell A. Millar-Blanchaer" Date: Wed, 5 Jun 2019 12:07:08 -0700 Subject: [PATCH] Max is confused by git. --- Tutorials/example_thermal_yield.py | 94 +++++++++++++++++++ .../example_yield_calculation.py | 15 ++- .../example_yield_calculation_pol.py | 0 .../forBruceandDimitri_EXOCAT1.json | 0 psisim/instrument.py | 2 +- psisim/observation.py | 14 ++- psisim/spectrum.py | 40 +++++--- 7 files changed, 141 insertions(+), 24 deletions(-) create mode 100644 Tutorials/example_thermal_yield.py rename {psisim/Tutorials => Tutorials}/example_yield_calculation.py (92%) rename {psisim/Tutorials => Tutorials}/example_yield_calculation_pol.py (100%) rename {psisim/Tutorials => Tutorials}/forBruceandDimitri_EXOCAT1.json (100%) diff --git a/Tutorials/example_thermal_yield.py b/Tutorials/example_thermal_yield.py new file mode 100644 index 0000000..71940eb --- /dev/null +++ b/Tutorials/example_thermal_yield.py @@ -0,0 +1,94 @@ +from psisim import telescope,instrument,observation,spectrum,universe,plots +import numpy as np +import matplotlib.pylab as plt + +import time + +tmt = telescope.TMT() +psi_red = instrument.PSI_Red() +psi_red.set_observing_mode(3600,2,'M',10, np.linspace(4.2,4.8,3)) #60s, 40 exposures,z-band, R of 10 + +exosims_config_filename = "forBruceandDimitri_EXOCAT1.json" #Some filename here +uni = universe.ExoSims_Universe(exosims_config_filename) +uni.simulate_EXOSIMS_Universe() + +planet_table = uni.planets +planet_table = planet_table[np.where(planet_table['PlanetMass'] > 10)] +n_planets = len(planet_table) + +planet_types = [] +planet_spectra = [] +planet_ages = [] + +n_planets_now = 100 +rand_planets = np.random.randint(0, n_planets, n_planets_now) + +########### Model spectrum wavelength choice ############# +# We're going to generate a model spectrum at a resolution twice the +# requested resolution +intermediate_R = psi_red.current_R*2 +#Choose the model wavelength range to be just a little bigger than +#the observation wavelengths +model_wv_low = 0.9*np.min(psi_red.current_wvs) +model_wv_high = 1.1*np.max(psi_red.current_wvs) + +#Figure out a good wavelength spacing for the model +wv_c = 0.5*(model_wv_low+model_wv_high) #Central wavelength of the model +dwv_c = wv_c/intermediate_R #The delta_lambda at the central wavelength +#The number of wavelengths to generate. Divide by two for nyquist in the d_wv. +#Multiply the final number by 2 just to be safe. +n_model_wv = int((model_wv_high-model_wv_low)/(dwv_c/2))*2 +#Generate the model wavelenths +model_wvs = np.linspace(model_wv_low, model_wv_high, n_model_wv) #Choose some wavelengths + +print("\n Starting to generate planet spectra") +for planet in planet_table[rand_planets]: + #INSERT PLANET SELECTION RULES HERE + planet_type = "Gas" + planet_types.append(planet_type) + + age = np.random.random() * 5e9 # between 0 and 5 Gyr + planet_ages.append(age) + + time1 = time.time() + #Generate the spectrum and downsample to intermediate resolution + atmospheric_parameters = age, 'M', True + planet_spectrum = spectrum.simulate_spectrum(planet, model_wvs, intermediate_R, atmospheric_parameters, package='bex-cooling') + planet_spectra.append(planet_spectrum) + + time2 = time.time() + print('Spectrum took {0:.3f} s'.format((time2-time1))) + +print("Done generating planet spectra") +print("\n Starting to simulate observations") + +post_processing_gain=10 +sim_F_lambda, sim_F_lambda_errs,sim_F_lambda_stellar, noise_components = observation.simulate_observation_set(tmt, psi_red, + planet_table[rand_planets], planet_spectra, model_wvs, intermediate_R, inject_noise=False, + post_processing_gain=post_processing_gain,return_noise_components=True) + +speckle_noises = np.array([s[0] for s in noise_components]) +photon_noises = np.array([s[3] for s in noise_components]) + +flux_ratios = sim_F_lambda/sim_F_lambda_stellar +detection_limits = sim_F_lambda_errs/sim_F_lambda_stellar +snrs = sim_F_lambda/sim_F_lambda_errs + +detected = psi_red.detect_planets(planet_table[rand_planets],snrs,tmt) + +#Choose which wavelength you want to plot the detections at: +wv_index = 1 +fig, ax = plots.plot_detected_planet_contrasts(planet_table[rand_planets],wv_index, + detected,flux_ratios,psi_red,tmt,ymin=1e-13,alt_data=5*detection_limits,alt_label=r"5-$\sigma$ Detection Limits", show=False) + +#The user can now adjust the plot as they see fit. +#e.g. Annotate the plot +ax.text(4e-2,1e-5,"Planets detected: {}".format(len(np.where(detected[:,wv_index])[0])),color='k') +ax.text(4e-2,0.5e-5,"Planets not detected: {}".format(len(np.where(~detected[:,wv_index])[0])),color='k') +ax.text(4e-2,0.25e-5,"Post-processing gain: {}".format(post_processing_gain),color='k') + + + +plt.show() + +import pdb; pdb.set_trace() \ No newline at end of file diff --git a/psisim/Tutorials/example_yield_calculation.py b/Tutorials/example_yield_calculation.py similarity index 92% rename from psisim/Tutorials/example_yield_calculation.py rename to Tutorials/example_yield_calculation.py index f0e486f..c57ded5 100644 --- a/psisim/Tutorials/example_yield_calculation.py +++ b/Tutorials/example_yield_calculation.py @@ -2,6 +2,8 @@ import numpy as np import matplotlib.pylab as plt +import time + tmt = telescope.TMT() psi_blue = instrument.PSI_Blue() psi_blue.set_observing_mode(3600,10,'z',50, np.linspace(0.60,0.85,40)) #60s, 40 exposures,z-band, R of 10 @@ -45,10 +47,14 @@ planet_type = "Gas" planet_types.append(planet_type) + time1 = time.time() #Generate the spectrum and downsample to intermediate resolution atmospheric_parameters = spectrum.generate_picaso_inputs(planet,planet_type, clouds=True) planet_spectrum = spectrum.simulate_spectrum(planet, model_wvs, intermediate_R, atmospheric_parameters) planet_spectra.append(planet_spectrum) + + time2 = time.time() + print('Spectrum took {0:.3f} s'.format((time2-time1))) print("Done generating planet spectra") print("\n Starting to simulate observations") @@ -102,8 +108,12 @@ fig = plt.figure() -plt.errorbar(psi_blue.current_wvs*1000, clear_F_lambda, yerr=clear_F_lambda_errs, color='Blue', marker='o', linestyle='none', label="Clear") -plt.errorbar(psi_blue.current_wvs*1000, cloudy_F_lambda, yerr=cloudy_F_lambda_errs, color='Gray', marker='o', linestyle='none', label="Cloudy") +plt.errorbar(psi_blue.current_wvs*1000, clear_F_lambda, yerr=clear_F_lambda_errs, color='Blue', marker='o', linestyle='none', label="Clear", zorder=1) +plt.errorbar(psi_blue.current_wvs*1000, cloudy_F_lambda, yerr=cloudy_F_lambda_errs, color='Gray', marker='o', linestyle='none', label="Cloudy", zorder=1) + +plt.plot(model_wvs*1000, planet_spectrum_clear, color='Blue', linestyle='-', alpha=0.5, zorder=0) +plt.plot(model_wvs*1000, planet_spectra[bestsnr], color='Gray', linestyle='-', alpha=0.5, zorder=0) + plt.grid() plt.xlabel("Wavelength (nm)") @@ -113,3 +123,4 @@ plt.show() +import pdb; pdb.set_trace() \ No newline at end of file diff --git a/psisim/Tutorials/example_yield_calculation_pol.py b/Tutorials/example_yield_calculation_pol.py similarity index 100% rename from psisim/Tutorials/example_yield_calculation_pol.py rename to Tutorials/example_yield_calculation_pol.py diff --git a/psisim/Tutorials/forBruceandDimitri_EXOCAT1.json b/Tutorials/forBruceandDimitri_EXOCAT1.json similarity index 100% rename from psisim/Tutorials/forBruceandDimitri_EXOCAT1.json rename to Tutorials/forBruceandDimitri_EXOCAT1.json diff --git a/psisim/instrument.py b/psisim/instrument.py index 22f9c35..81528f7 100644 --- a/psisim/instrument.py +++ b/psisim/instrument.py @@ -285,7 +285,7 @@ def __init__(self): self.dark_current = 0. self.qe = 1. - self.filters = ['L', 'M'] + self.filters = ['K', 'L', 'M'] self.ao_filter = ['i'] self.ao_filter2 = ['H'] diff --git a/psisim/observation.py b/psisim/observation.py index 0ade7c2..317f5f9 100644 --- a/psisim/observation.py +++ b/psisim/observation.py @@ -32,7 +32,7 @@ def simulate_observation(telescope,instrument,planet_table_entry,planet_spectrum #Get the stellar spectrum at the wavelengths of interest. #The stellar spectrum will be in units of photons/s/cm^2/angstrom stellar_spectrum = spectrum.get_stellar_spectrum(planet_table_entry,wvs,instrument.current_R, - model='pickles',verbose=verbose) + verbose=verbose) #Multiply the stellar spectrum by the collecting area and a factor of 10,000 #to convert from m^2 to cm^2 and get the stellar spectrum in units of photons/s @@ -98,15 +98,13 @@ def simulate_observation(telescope,instrument,planet_table_entry,planet_spectrum ##### Now get the various noise sources: speckle_noise,read_noise,dark_noise,photon_noise = get_noise_components(separation,star_imag,instrument, - instrument.current_wvs,star_spt,detector_stellar_spectrum,detector_spectrum) - - thermal_noise = np.sqrt(detector_thermal_flux) + instrument.current_wvs,star_spt,detector_stellar_spectrum,detector_spectrum,detector_thermal_flux) #Apply a post-processing gain speckle_noise /= post_processing_gain ## Sum it all up - total_noise = np.sqrt(speckle_noise**2+read_noise**2+dark_noise**2+photon_noise**2+thermal_noise**2) + total_noise = np.sqrt(speckle_noise**2+read_noise**2+dark_noise**2+photon_noise**2) # Inject noise into spectrum if inject_noise: @@ -120,11 +118,11 @@ def simulate_observation(telescope,instrument,planet_table_entry,planet_spectrum #TODO: Currently everything is in e-. We likely want it in a different unit at the end. if return_noise_components: - return detector_spectrum, total_noise, detector_stellar_spectrum,(speckle_noise,read_noise,dark_noise,photon_noise,thermal_noise) + return detector_spectrum, total_noise, detector_stellar_spectrum,(speckle_noise,read_noise,dark_noise,photon_noise) else: return detector_spectrum, total_noise, detector_stellar_spectrum -def get_noise_components(separation,star_imag,instrument,wvs,star_spt,stellar_spectrum,detector_spectrum): +def get_noise_components(separation,star_imag,instrument,wvs,star_spt,stellar_spectrum,detector_spectrum,thermal_spectrum): ''' Calculate all of the different noise contributions ''' @@ -149,7 +147,7 @@ def get_noise_components(separation,star_imag,instrument,wvs,star_spt,stellar_sp #TODO:Add the background noise #Photon noise. Detector_spectrum should be in total of e- now. - photon_noise = np.sqrt(detector_spectrum+speckle_noise) + photon_noise = np.sqrt(detector_spectrum + thermal_spectrum + speckle_noise) return speckle_noise,read_noise,dark_noise,photon_noise diff --git a/psisim/spectrum.py b/psisim/spectrum.py index 9c549a9..9fabb40 100644 --- a/psisim/spectrum.py +++ b/psisim/spectrum.py @@ -52,9 +52,13 @@ def generate_picaso_inputs(planet_table_entry, planet_type, clouds=True,verbose= star_logG = planet_table_entry['StarLogg'] if star_logG > 5.0: star_logG = 5.0 + #The current stellar models do not like Teff < 3500, so we'll force it here for now. + star_Teff = planet_table_entry['StarTeff'] + if star_Teff < 3500: + star_Teff = 3500 #define star - params.star(opacity, planet_table_entry['StarTeff'], 0, star_logG) #opacity db, pysynphot database, temp, metallicity, logg + params.star(opacity, star_Teff, 0, star_logG) #opacity db, pysynphot database, temp, metallicity, logg # define atmosphere PT profile and mixing ratios. # Hard coded as Jupiters right now. @@ -184,7 +188,7 @@ def simulate_spectrum(planet_table_entry, wvs, R, atmospheric_parameters, packag elif band == 'L': bexlabel = 'NACOLp' starlabel = 'StarKmag' - elif band == 'K': + elif band == 'M': bexlabel = 'NACOMp' starlabel = 'StarKmag' else: @@ -279,14 +283,26 @@ def get_stellar_spectrum(planet_table_entry,wvs,R,model='Castelli-Kurucz',verbos # For now we're assuming a metallicity of 0, because exosims doesn't # provide anything different + #The current stellar models do not like log g > 5, so we'll force it here for now. + star_logG = planet_table_entry['StarLogg'] + if star_logG > 5.0: + star_logG = 5.0 + #The current stellar models do not like Teff < 3500, so we'll force it here for now. + star_Teff = planet_table_entry['StarTeff'] + if star_Teff < 3500: + star_Teff = 3500 + # Get the Castelli-Kurucz models - sp = get_castelli_kurucz_spectrum(planet_table_entry['StarTeff'],0., - planet_table_entry['StarLogg']) + sp = get_castelli_kurucz_spectrum(star_Teff, 0., star_logG) # The flux normalization in pysynphot are all over the place, but it allows # you to renormalize, so we will do that here. We'll normalize to the Vmag # of the star, assuming Johnsons filters - sp_norm = sp.renorm(planet_table_entry['StarVmag'],'vegamag',S.Obs.Bandpass('johnson,v')) + sp_norm = sp.renorm(planet_table_entry['StarVmag'],'vegamag', ps.ObsBandpass('johnson,v')) + + # we normally want to put this in the get_castelli_kurucz_spectrum() function but the above line doens't work if we change units + sp_norm.convert("Micron") + sp_norm.convert("photlam") stellar_spectrum = [] @@ -298,17 +314,17 @@ def get_stellar_spectrum(planet_table_entry,wvs,R,model='Castelli-Kurucz',verbos for wv in wvs: #Get the wavelength sampling of the pysynphot sectrum - dwvs = sp.wave[1:]-sp.wave[:-1] - dwvs[0] = dwvs[0] + dwvs = sp_norm.wave - np.roll(sp_norm.wave, 1) + dwvs[0] = dwvs[1] #Pick the index closest to our wavelength. - ind = np.where(np.abs((sp.wave-wv)) == np.min(np.abs(sp.wave-wv)))[0] + ind = np.argsort(np.abs((sp_norm.wave-wv)))[0] dwv = dwvs[ind] R_in = wv/dwv #Down-sample the spectrum to the desired wavelength - ds = downsample_spectrum(full_stellar_spectrum,R_in,R) + ds = downsample_spectrum(sp_norm.flux, R_in, R) #Interpolate the spectrum to the wavelength we want - stellar_spectrum.append(si.interp1d(sp.wave,ds)(wv)) + stellar_spectrum.append(si.interp1d(sp_norm.wave,ds)(wv)) stellar_spectrum = np.array(stellar_spectrum) @@ -364,9 +380,7 @@ def get_castelli_kurucz_spectrum(teff,metallicity,logg): Retuns the pysynphot spectrum object with wavelength units of microns and flux units of photons/s/cm^2/Angstrom ''' - sp = psyn.Icat('ck04models',teff,metallicity,logg) - sp.convert("Micron") - sp.convert("photlam") + sp = ps.Icat('ck04models',teff,metallicity,logg) return sp