def make_matrices(): # Find all the relevant files #allfiles = [f for f in os.listdir("./") if f.startswith("RV") and f.endswith("-0.fits")] allfiles = [f for f in os.listdir("./") if f.startswith("RV") and '-0' in f and f.endswith("corrected.fits")] # Read in the measured RV data bjd, rv = np.loadtxt("psi1draa_100_120_mcomb1.dat", usecols=(0,1), unpack=True) bjd2, vbary_arr = np.loadtxt("psi1draa_100p_28_37_ASW.dat", usecols=(0,5), unpack=True) # Put all the data in one giant list alldata = [] print "Reading all data" for i, fname in enumerate(allfiles): header = fits.getheader(fname) jd = header['jd'] #vbary = GenericSearch.HelCorr(header, observatory="McDonald") idx = np.argmin(abs(bjd2 - jd)) bjd2_i = bjd2[idx] vbary = vbary_arr[idx] / 1000.0 idx = np.argmin(abs(bjd - jd)) bjd_i = bjd[idx] vstar = rv[idx]/1e3 print(fname, vbary, vstar) vel = vbary - vstar #Closest... but still not great #vel = -vbary + vstar #NO #vel = vbary + vstar #NO #vel = -vbary - vstar #NO #vel = vstar #NO #vel = -vstar #NO #vel = vbary #Surprisingly not bad... orders = HelperFunctions.ReadExtensionFits(fname)[:-2] for j in badorders[::-1]: orders.pop(j) if i == 0: template = [] for j, order in enumerate(orders): order.x *= (1.0+vel/c) orders[j] = order.copy() template.append(order.copy()) alldata.append([order]) #template = [o.copy() for o in orders] else: vel = fit_rv_shift_old(template, orders) print('RV adjustment = {}'.format(vel)) for j, order in enumerate(orders): order.x *= (1.0+vel/c) orders[j] = order.copy() if i == 0: alldata.append([order]) #template.append(order.copy()) else: alldata[j].append(order) #plt.plot(order.x, order.y/order.cont, 'g-', alpha=0.5) #plt.show() # Interpolate each order to a single wavelength grid print "Interpolating to wavelength grid" xgrids = [] c_cycler = itertools.cycle(('r', 'g', 'b', 'k')) ls_cycler = itertools.cycle(('-', '--', ':', '-.')) for i, order in enumerate(alldata): print "Order ", i+1 firstwaves = [d.x[0] for d in order] lastwaves = [d.x[-1] for d in order] size = np.mean([d.size() for d in order]) xgrid = np.linspace(max(firstwaves), min(lastwaves), size) for j, data in enumerate(order): tmp = FittingUtilities.RebinData(data, xgrid) order[j] = tmp.y/tmp.cont #if i == 20: # col = c_cycler.next() # if j%4 == 0: # ls = ls_cycler.next() # plt.plot(xgrid, order[j], color=col, ls=ls, alpha=0.8, label=allfiles[j]) #plt.plot(xgrid, order[j], 'k-', alpha=0.2) alldata[i] = np.array(order) xgrids.append(xgrid) #plt.legend(loc='best') #plt.show() return allfiles, xgrids, alldata
fitter.const_pars[j] for j in range(len(fitter.parnames)) if fitter.fitting[j] ] full_model = fitter.GenerateModel(fitpars, separate_source=False, return_resolution=False, broaden=False, nofit=True) for i, order in enumerate(orders): left = np.searchsorted(full_model.x, order.x[0] - 5) right = np.searchsorted(full_model.x, order.x[-1] + 5) if min(full_model.y[left:right]) > 0.95: model = FittingUtilities.ReduceResolution( full_model[left:right].copy(), resolution) model = FittingUtilities.RebinData(model, order.x) data = order.copy() data.cont = np.ones(data.size()) else: print "\n\nGenerating model for order %i of %i\n" % ( i, len(orders)) order.cont = FittingUtilities.Continuum(order.x, order.y, fitorder=3, lowreject=1.5, highreject=10) fitter.ImportData(order) fitter.resolution_fit_mode = "gauss" model = fitter.GenerateModel( fitpars,
def MakeModel(self, pressure=795.0, temperature=283.0, lowfreq=4000, highfreq=4600, angle=45.0, humidity=50.0, co2=368.5, o3=3.9e-2, n2o=0.32, co=0.14, ch4=1.8, o2=2.1e5, no=1.1e-19, so2=1e-4, no2=1e-4, nh3=1e-4, hno3=5.6e-4, lat=30.6, alt=2.1, wavegrid=None, resolution=None, save=False, libfile=None, vac2air=True): """ Here is the important function! All of the variables have default values, which you will want to override for any realistic use. :param pressure: Pressure at telescope altitude (hPa) :param temperature: Temperature at telescope altitude (Kelvin) :param lowfreq: The starting wavenumber (cm^-1) :param highfreq: The ending wavenumber (cm^-1) :param angle: The zenith distance of the telescope (degrees). This is related to the airmass (z) through z = sec(angle) :param humidity: Percent relative humidity at the telescope altitude. :param co2: Mixing ratio of this molecule (parts per million by volumne) :param o3: Mixing ratio of this molecule (parts per million by volumne) :param n2o: Mixing ratio of this molecule (parts per million by volumne) :param co: Mixing ratio of this molecule (parts per million by volumne) :param ch4: Mixing ratio of this molecule (parts per million by volumne) :param o2: Mixing ratio of this molecule (parts per million by volumne) :param no: Mixing ratio of this molecule (parts per million by volumne) :param so2: Mixing ratio of this molecule (parts per million by volumne) :param no2: Mixing ratio of this molecule (parts per million by volumne) :param nh3: Mixing ratio of this molecule (parts per million by volumne) :param hno3: Mixing ratio of this molecule (parts per million by volumne) :param lat: The latitude of the observatory (degrees) :param alt: The altitude of the observatory above sea level (km) :param wavegrid: If given, the model will be resampled to this grid. Should be a 1D np array :param resolution: If given, it will reduce the resolution by convolving with a gaussian of appropriate width. Should be a float with R=lam/dlam :param save: If true, the generated model is saved. The filename will be printed to the screen. :param libfile: Useful if generating a telluric library. The filename of the saved file will be written to this filename. Should be a string variable. Ignored if save==False :param vac2air: If True (default), it converts the wavelengths from vacuum to air :return: DataStructures.xypoint instance with the telluric model. The x-axis is in nanometers and the y-axis is in fractional transmission. """ self.FindWorkingDirectory() #Make the class variables local TelluricModelingDir = self.TelluricModelingDir debug = self.debug lock = self.lock layers = np.array(self.layers) ModelDir = self.ModelDir #Make a deep copy of atmosphere so that I don't repeatedly modify it Atmosphere = copy.deepcopy(self.Atmosphere) #Convert from relative humidity to concentration (ppm) h2o = humidity_to_ppmv(humidity, temperature, pressure) #Start by scaling the abundances from those at 'alt' km # (linearly interpolate) keys = sorted(Atmosphere.keys()) lower = max(0, np.searchsorted(keys, alt) - 1) upper = min(lower + 1, len(keys) - 1) if lower == upper: raise ZeroDivisionError( "Observatory altitude of %g results in the surrounding layers being the same!" % alt) scale_values = list(Atmosphere[lower]) scale_values[2] = list(Atmosphere[lower][2]) scale_values[0] = (Atmosphere[upper][0] - Atmosphere[lower][0]) / ( keys[upper] - keys[lower]) * (alt - keys[lower]) + Atmosphere[lower][0] scale_values[1] = (Atmosphere[upper][1] - Atmosphere[lower][1]) / ( keys[upper] - keys[lower]) * (alt - keys[lower]) + Atmosphere[lower][1] for mol in range(len(scale_values[2])): scale_values[2][mol] = ( Atmosphere[upper][2][mol] - Atmosphere[lower][2][mol]) / (keys[upper] - keys[lower]) * ( alt - keys[lower]) + Atmosphere[lower][2][mol] #Do the actual scaling pressure_scalefactor = (scale_values[0] - pressure) * np.exp( -(layers - alt)**2 / (2.0 * 10.0**2)) temperature_scalefactor = (scale_values[1] - temperature) * np.exp( -(layers - alt)**2 / (2.0 * 10.0**2)) for i, layer in enumerate(layers): # Atmosphere[layer][0] -= pressure_scalefactor[i] Atmosphere[layer][0] *= pressure / scale_values[0] Atmosphere[layer][1] -= temperature_scalefactor[i] Atmosphere[layer][2][0] *= h2o / scale_values[2][0] Atmosphere[layer][2][1] *= co2 / scale_values[2][1] Atmosphere[layer][2][2] *= o3 / scale_values[2][2] Atmosphere[layer][2][3] *= n2o / scale_values[2][3] Atmosphere[layer][2][4] *= co / scale_values[2][4] Atmosphere[layer][2][5] *= ch4 / scale_values[2][5] Atmosphere[layer][2][6] *= o2 / scale_values[2][6] Atmosphere[layer][2][7] *= no / scale_values[2][7] Atmosphere[layer][2][8] *= so2 / scale_values[2][8] Atmosphere[layer][2][9] *= no2 / scale_values[2][9] Atmosphere[layer][2][10] *= nh3 / scale_values[2][10] Atmosphere[layer][2][11] *= hno3 / scale_values[2][11] #Now, Read in the ParameterFile and edit the necessary parameters parameters = MakeTape5.ReadParFile(parameterfile=TelluricModelingDir + "ParameterFile") parameters[48] = "%.1f" % lat parameters[49] = "%.1f" % alt parameters[51] = "%.5f" % angle parameters[17] = lowfreq freq, transmission = np.array([]), np.array([]) #Need to run lblrtm several times if the wavelength range is too large. maxdiff = 1999.9 if (highfreq - lowfreq > maxdiff): while lowfreq + maxdiff <= highfreq: parameters[18] = lowfreq + maxdiff MakeTape5.WriteTape5(parameters, output=TelluricModelingDir + "TAPE5", atmosphere=Atmosphere) #Run lblrtm cmd = "cd " + TelluricModelingDir + ";sh runlblrtm_v3.sh" try: if self.print_lblrtm_output: command = subprocess.check_call(cmd, shell=True) if not self.print_lblrtm_output: command = subprocess.check_call( cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except subprocess.CalledProcessError: raise subprocess.CalledProcessError( "Error: Command '{}' failed in directory {}".format( cmd, TelluricModelingDir)) #Read in TAPE12, which is the output of LBLRTM freq, transmission = self.ReadTAPE12(TelluricModelingDir, appendto=(freq, transmission)) lowfreq = lowfreq + 2000.00001 parameters[17] = lowfreq parameters[18] = highfreq MakeTape5.WriteTape5(parameters, output=TelluricModelingDir + "TAPE5", atmosphere=Atmosphere) #Run lblrtm for the last time cmd = "cd " + TelluricModelingDir + ";sh runlblrtm_v3.sh" try: if self.print_lblrtm_output: command = subprocess.check_call(cmd, shell=True) if not self.print_lblrtm_output: command = subprocess.check_call(cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except subprocess.CalledProcessError: raise subprocess.CalledProcessError( "Error: Command '{}' failed in directory {}".format( cmd, TelluricModelingDir)) #Read in TAPE12, which is the output of LBLRTM freq, transmission = self.ReadTAPE12(TelluricModelingDir, appendto=(freq, transmission)) #Convert from frequency to wavelength units wavelength = units.cm.to(units.nm) / freq #Correct for index of refraction of air (use IAU standard conversion from # Morton, D. C. 1991, ApJS, 77, 119 if vac2air: wave_A = wavelength * units.nm.to( units.angstrom) # Wavelength in angstroms n = 1.0 + 2.735182e-4 + 131.4182 / wave_A**2 + 2.76249e8 / wave_A**4 wavelength /= n if save: #Output filename model_name = ModelDir + "transmission" + "-%.2f" % pressure + "-%.2f" % temperature + "-%.1f" % humidity + "-%.1f" % angle + "-%.2f" % ( co2) + "-%.2f" % (o3 * 100) + "-%.2f" % ch4 + "-%.2f" % (co * 10) logging.info( "All done! Output Transmission spectrum is located in the file below:\n\t\t{}" .format(model_name)) np.savetxt(model_name, np.transpose((wavelength[::-1], transmission[::-1])), fmt="%.8g") if libfile != None: infile = open(libfile, "a") infile.write(model_name + "\n") infile.close() self.Cleanup() #Un-lock the working directory if wavegrid != None: model = DataStructures.xypoint(x=wavelength[::-1], y=transmission[::-1]) return FittingUtilities.RebinData(model, wavegrid) return DataStructures.xypoint(x=wavelength[::-1], y=transmission[::-1])