def main(): # Read in the needed values from the command line arguments = parseArguments() # Read in the spectrum try: wlc, flux = np.loadtxt(arguments.fileName, unpack=True, skiprows=1) except IOError: print("Input spectrum " + arguments.fileName + " not found!") exit() # Resample the input spectrum to even wavelength bins of <binSize> Angstrom newWlc = np.arange(wlc[0] + binSize, wlc[-1] - binSize, binSize) flux = np.interp(newWlc, wlc, flux) wlc = newWlc # Apply instrumental broadening flux = instrBroadGaussFast(wlc, flux, arguments.res, maxsig=5.0, edgeHandling="firstlast") # Apply rotational broadening flux = rotBroad(wlc, flux, limbDark, arguments.vrot) # Apply macroturbulent broadening if arguments.vmacro != -1: flux = macroBroad(wlc, flux, arguments.vmacro) # Resample to <finalBins> Angstrom if finalBins != binSize: newWlc = np.arange(wlc[0] + finalBins, wlc[-1] - finalBins, finalBins) flux = np.interp(newWlc, wlc, flux) # Write output file out_f = open(arguments.fileName + ".fin", 'w') out_f.write("#" + str(len(wlc)) + "\t" + "#0 \n") for i in range(len(wlc) - 1): out_f.write(str(wlc[i]) + "\t" + str(flux[i]) + "\n") out_f.close() exit()
def sanity_deltaExample(self): """ The delta function example from SVD. """ import numpy as np import matplotlib.pylab as plt from PyAstronomy import pyasl # Get some "data" wvl = np.arange(5000., 5010., 0.02) template = np.ones(len(wvl)) # There are two sharp lines in the template template[100] = 0.5 template[115] = 0.3 # Apply rotational broadening to the delta spectrum nflux = pyasl.rotBroad(wvl, template, 0.5, 23.45, edgeHandling="firstlast") # Carry out decomposition svd = pyasl.SVD() svd.decompose(template, 51) # Obtain the broadening function needed to # recover "observed" spectrum. Note that the # edges (51/2 bins) will actually be neglected. b = svd.getBroadeningFunction(nflux) # Get the model, which results from the broadening # function and the template; obtain the indices # where it applies, too. m, mind = svd.getModel(b, modelIndices=True) # Plot the outcome plt.plot(b, 'bp-') plt.plot(mind, m, 'r.') plt.plot(nflux, 'g--')
def vsini_broadening(x, y, epsilon, vsini): ''' Apply rotational broadening to a spectrum assuming a linear limb darkening law. The adopted limb darkening law is the linear one, parameterize by the linear limb darkening parameter: epsilon = 0.6. The effect of rotational broadening on the spectrum is wavelength dependent, because the Doppler shift depends on wavelength. This function neglects this dependence, which is weak if the wavelength range is not too large. Code from: http://www.phoebe-project.org/2.0/ .. note:: numpy.convolve is used to carry out the convolution and "mode = same" is used. Therefore, the output will be of the same size as the input, but it will show edge effects. Input ----- wvl : The wavelength flux : The flux epsilon : Linear limb-darkening coefficient (0-1). vsini : Projected rotational velocity in km/s. effWvl : The wavelength at which the broadening kernel is evaluated. If not specified, the mean wavelength of the input will be used. Output ------ y_rot : convolved flux ''' if vsini == 0: return y else: y_rot = pyasl.rotBroad(x, y, epsilon, vsini, edgeHandling='firstlast') return y_rot
def sanity_example(self): """ Sanity of "rotBroad" example. """ import numpy as np import matplotlib.pylab as plt from PyAstronomy import funcFit as fuf from PyAstronomy import pyasl import scipy.integrate as sci # Create a spectrum with a single Gaussian # line using funcFit's GaussFit1d object. # Note that this object is not used for # fitting here, but only a calculate a # Gaussian. g = fuf.GaussFit1d() g["mu"] = 5005. g["A"] = -0.1 g["sig"] = 0.1 g["off"] = 1.0 # Evaluate the spectrum with 0.01 A bin size wvl = np.linspace(5003., 5007., 400) flux = g.evaluate(wvl) # Obtain the broadened spectrum using # vsini = 13.3 km/s and no limb-darkening rflux = pyasl.rotBroad(wvl, flux, 0.0, 13.3) # Obtain the broadened spectrum using # vsini = 13.3 km/s and strong limb-darkening lflux = pyasl.rotBroad(wvl, flux, 0.9, 13.3) # Check that the area of the line did not change # in response to the broadening print "Initional EW [A]: ", 4. - sci.trapz(flux, wvl) print "After broadening without LD: ", 4. - sci.trapz(rflux, wvl) print "After broadening with LD: ", 4. - sci.trapz(lflux, wvl) # Plot the results plt.title("Rotational broadening") plt.xlabel("Wavelength [A]") plt.ylabel("Normalized flux") plt.plot(wvl, flux, 'b-') plt.plot(wvl, rflux, 'r-') plt.plot(wvl, lflux, 'g-')
def broaden(even_wl, modelspec_interp, res, vsini=0, limb=0, plot=False): """Adds resolution, vsin(i) broadening, taking into account limb darkening. Args: even_wl (list): evenly spaced model wavelength vector modelspec_interp (list): model spectrum vector res (float): desired spectral resolution vsini (float): star vsin(i) limb (float): the limb darkening coeffecient plot (boolean): if True, plots the full input spectrum and the broadened output. Defaults to False. Returns: a tuple containing an evenly spaced wavelength vector spanning the width of the original wavelength range, and a corresponding flux vector """ #regrid by finding the smallest wavelength step mindiff = np.inf for n in range(1, len(even_wl)): if even_wl[n] - even_wl[n - 1] < mindiff: mindiff = even_wl[n] - even_wl[n - 1] #interpolate the input values it = interp1d(even_wl, modelspec_interp) #make a new wavelength array that's evenly spaced with the smallest wavelength spacing in the input wl array w = np.arange(min(even_wl), max(even_wl), mindiff) sp = it(w) #do the instrumental broadening and truncate the ends because they get messy broad = pyasl.instrBroadGaussFast(w, sp, res, maxsig=5) broad[0:5] = broad[5] broad[len(broad) - 10:len(broad)] = broad[len(broad) - 11] #if I want to impose stellar parameters of v sin(i) and limb darkening, do that here if vsini != 0 and limb != 0: rot = pyasl.rotBroad(w, broad, limb, vsini) #, edgeHandling='firstlast') #otherwise just move on else: rot = broad #Make a plotting option just in case I want to double check that this is doing what it's supposed to if plot == True: plt.figure() plt.plot(w, sp, label='model') plt.plot(w, broad, label='broadened') plt.plot(w, rot, label='rotation') plt.legend(loc='best') plt.xlabel('wavelength (angstroms)') plt.ylabel('normalized flux') plt.savefig('rotation.pdf') #return the wavelength array and the broadened flux array return w, rot
def evaluate(self, x): """ Calculates the model for current parameters. The "model" is calculated on a wavelength axis with binning specified by the `modelBinsize` parameter. The line positions are Doppler shifted and the resulting model is rotationally broadened. Finally, the entire model is multiplied by the `scale` parameter to account for a global normalization. Parameters ---------- x : array The wavelengths at which to calculate the model. Returns ------- model : array The model evaluated at the specified positions. """ if self._verbose: print("Evaluating with parameters: ", self.parameters()) # Calculate how much longer the model wavelength axis should # be to ensure that Doppler shift and rotational broadening # to not "violate" its edges. maxV = abs(self["vsini"]) + abs(self["vrad"]) deltaWvl = max(x) * (1.0 + maxV/299792.458) - max(x) # The additional summand `_modelBinsize` is needed to ensure # that the wavelength axis is long enough even if the velocities # are very small. mwvl = np.arange(min(x)-deltaWvl, max(x)+deltaWvl+self._modelBinsize, self._modelBinsize) mflux = np.ones(len(mwvl)) # Set parameters of multiGauss for i in smo.range(self._nl): p = str(i+1) # Apply global scaling of amplitudes self._mg["A"+p] = -self["A"+p] * self["lineScale"] self._mg["sig"+p] = self["sig"+p] # Apply doppler shift of lines self._mg["mu"+p] = (1.0 + self["vrad"]/299792.458) * self["mu"+p] mflux += self._mg.evaluate(mwvl) if abs(self["vsini"]) > 0.0: if self._usefastRB: mflux = pyasl.fastRotBroad(mwvl, mflux, self["eps"], np.abs(self["vsini"])) else: mflux = pyasl.rotBroad(mwvl, mflux, self["eps"], np.abs(self["vsini"])) mflux *= self["scale"] # Return model interpolated at input wavelength f = sci.interp1d(mwvl, mflux) return f(x)
def makeArtificialSlowRots(newWave, newFlux, coef): #array of velocity values for the rotational broadening routine velocities = np.arange(2.0, 65.0, 4.0) fluxList = [] #loop through the velocities and add the rotationally broadened flux to a list for i in range(len(velocities)): flux = pyasl.rotBroad(newWave, newFlux, coef, velocities[i]) fluxList.append(flux) return velocities, fluxList
def get_broad_lsf(wave0, epsilon, vsini): # create a rotation profile wave_tmp = (1 + np.arange(-np.int(vsini) - 1, np.int(vsini) + 1) / c) * wave0 * 10 f_tmp = np.zeros_like(wave_tmp) f_tmp[np.int(vsini)] = 1 lsf = rotBroad(wave_tmp, f_tmp, epsilon, vsini) lsf = lsf[lsf != 0] #print(lsf) #print(wave0) return lsf
def _task_fit_refstar(paras): vsini_arr, limbdark_arr,RV_arr,wvs,refstarpho_spec_func,atm_model,spec,cutoff = paras vsini_ravel= np.ravel(vsini_arr) limbdark_ravel= np.ravel(limbdark_arr) RV_ravel= np.ravel(RV_arr) posterior = np.zeros(vsini_arr.shape) posterior.shape = (np.size(vsini_arr),) c_kms = 299792.458 for k,(vsini,limbdark,rv) in enumerate(zip(vsini_ravel,limbdark_ravel,RV_ravel)): hd_wvs =np.linspace(wvs[0],wvs[-1],10*(np.size(wvs)-1)+1) refstarpho_spec = refstarpho_spec_func(hd_wvs*(1-rv/c_kms)) broadened_refstarpho = pyasl.rotBroad(hd_wvs, refstarpho_spec, limbdark, vsini) broadened_refstarpho = broadened_refstarpho[::10] model = [atm*broadened_refstarpho for atm in atm_model] # model = [broadened_refstarpho for atm in atm_model] model = [LPFvsHPF(vec,cutoff)[1] for vec in model] model = [vec/np.nanstd(vec) for vec in model] model = np.array(model).transpose() # model = model[:,5:6] sigmas_vec = np.ones(spec.shape) logdet_Sigma = np.sum(2*np.log(sigmas_vec)) model = model/sigmas_vec[:,None] spec_hpf = LPFvsHPF(spec,cutoff)[1] spec_norma = np.nanstd(spec_hpf) data_sig = spec_hpf/spec_norma/sigmas_vec data_sig[0:200] = np.nan data_sig[np.size(data_sig)-200::] = np.nan where_finite_data = np.where(np.isfinite(data_sig)) data_sig = data_sig[where_finite_data] model = model[where_finite_data[0],:] HPFparas,HPFchi2,rank,s = np.linalg.lstsq(model,data_sig,rcond=None) data_model = np.dot(model,HPFparas) HPFchi2 = np.nansum((data_sig - data_model)**2) slogdet_icovphi0 = np.linalg.slogdet(np.dot(model.T,model)) # residuals = np.zeros(spec.shape) +np.nan # residuals[where_finite_data] = data_model*spec_norma-spec[where_finite_data] posterior[k] = -0.5*logdet_Sigma-0.5*slogdet_icovphi0[1]- (model.shape[0]-model.shape[-1]+2-1)/(2)*np.log(HPFchi2) # print(posterior[k]) posterior.shape = vsini_arr.shape return posterior
def _rotational_convolution(wl_band, spec_band, vsini, band_str, epsilon=0.6, pltt=False): ''' Convolve the spectrum with rotational kernel based on the star's projected rotation velocity and assuming a constant linear limb-darkening across the stellar disk. Parameters ---------- `wl_band': array-like Spectral array of wavelengths in microns `spec_band': array-like Stellar spectrum array in erg/s/cm^2/cm `band_str': str The letter designating the spectral band under consideration. Must be in ['U','B','V','R','I','Y','J','H','K'] `R': scalar The spectral resolution of the spectrograph (lambda / d_lambda) `pltt': boolean If True, the convolved and original spectra are plotted using pylab.show() Returns ------- `spec_conv': numpy.array Stellar spectrum array in erg/s/cm^2/cm over the spectral band ''' print '\nConvolving the %s stellar spectrum with a '%band_str + \ 'rotational profile...' try: spec_conv = rotBroad(wl_band, spec_band, epsilon, vsini) except NameError: # no convolution is bad spec_conv = spec_band if pltt: plt.plot(wl_band, spec_band, 'k-', label='Original') plt.plot(wl_band, spec_conv, 'b-', label='Rotationally convolved') plt.xlabel('Wavelength [microns]'), plt.ylabel('Flux [erg/s/cm2/cm]') plt.legend(), plt.show() return spec_conv
def RotationalBroadening(self, **kwargs): ''' This function broadens the spectrum to account for for the broadening effect of stellar rotation. :param: vsini - float, rotational velocity [km/s] :param: epsilon: float, limb-darkening coefficient (0-1) ''' epsilon = kwargs["epsilon"] vsini = kwargs["vsini"] w = np.reshape(self.model.wv[0], (1, -1))[0] s = self.model.sp[0] flux = pyasl.rotBroad(w, s, epsilon, vsini) self.model.sp = np.reshape(flux, (1, -1)) # self.model.wv = np.reshape(flux, (1, -1)) return self
def broaden(even_wl, modelspec_interp, res, vsini, limb, plot=False): """Adds resolution, vsin(i) broadening, taking into account limb darkening. Args: even_wl (list): evenly spaced model wavelength vector modelspec_interp (list): model spectrum vector res (float): desired spectral resolution vsini (float): star vsin(i) limb (float): the limb darkening coeffecient plot (boolean): if True, plots the full input spectrum and the broadened output. Defaults to False. Returns: a tuple containing an evenly spaced wavelength vector spanning the width of the original wavelength range, and a corresponding flux vector """ #sig = np.mean(even_wl)/res broad = pyasl.instrBroadGaussFast(even_wl, modelspec_interp, res, maxsig=5) if vsini != 0 and limb != 0: rot = pyasl.rotBroad(even_wl, broad, limb, vsini) #, edgeHandling='firstlast') else: rot = broad #modelspec_interp = [(modelspec_interp[n] / max(modelspec_interp)) for n in range(len(modelspec_interp))] #broad = [broad[n]/max(broad) for n in range(len(broad))] #rot = [(rot[n]/max(rot)) for n in range(len(rot))] if plot == True: plt.figure() plt.plot(even_wl, modelspec_interp, label='model') plt.plot(even_wl, broad, label='broadened') plt.plot(even_wl, rot, label='rotation') plt.legend(loc='best') plt.xlabel('wavelength (angstroms)') plt.ylabel('normalized flux') plt.savefig('rotation.pdf') return even_wl, rot
def add_rot_broad(wlen, flux, rot_vel, method='fast', edgeHandling='cut'): if method == 'fast': flux_broad = fastRotBroad(wlen, flux, 0, rot_vel) else: # method == 'slow' flux_broad = rotBroad(wlen, flux, 0, rot_vel) if edgeHandling == 'cut': skipping = abs(wlen[-1] * rot_vel * 1000 / cst.c) wvl_stepsize = np.mean( [wlen[i + 1] - wlen[i] for i in range(len(wlen) - 1)]) skipped_bins = int(skipping / wvl_stepsize) #print('Bins skipped for rotational broadening {b}'.format(b=skipped_bins)) wlen_cut, flux_cut = cut_spectrum(wlen, flux_broad, nb_bins_left=skipped_bins, nb_bins_right=skipped_bins) return wlen_cut, flux_cut else: # edgeHandling == 'keep' return wlen, flux_broad
def sanity_NoiseExample(self): """ The noise example from SVD """ import numpy as np import matplotlib.pylab as plt from PyAstronomy import pyasl # Get some "data" wvl = np.arange(5000., 5010., 0.02) template = np.ones(len(wvl)) # There are two sharp lines in the template template[100] = 0.5 template[115] = 0.3 # Apply rotational broadening to the delta spectrum nflux = pyasl.rotBroad(wvl, template, 0.5, 23.45, edgeHandling="firstlast") nflux += np.random.normal(0., 0.005, len(nflux)) # Carry out decomposition svd = pyasl.SVD() svd.decompose(template, 51) # Access the singular values sv = svd.getSingularValues() # Calculate the reduced chi square as a function of the number # of singular values neglected in the calculation of the # model. chi = [] for i in range(1, len(sv), 5): b = svd.getBroadeningFunction(nflux, wlimit=sorted(sv)[i]) m, mind = svd.getModel(b, modelIndices=True, asarray=True) chi.append( ((nflux[mind] - m)**2/0.005**2).sum() / len(mind) ) plt.title("Reduced $\chi^2$ vs. number of neglected singular values") plt.plot(range(1, len(sv), 5), chi, 'bp-')
def all_same(items): return all(x == items[0] for x in items) difflist = [] for idx, point in enumerate(wave[0:-1]): difflist.append(wave[idx+1] - point) if all_same(difflist) == True: print('Wavelength grid already evenly spaced') else: print('Resampling spectrum so it is evenly spaced in wavelength') dwave = np.max(difflist) newwave = np.arange(wave[0], wave[-1], dwave) newspec = np.interp(newwave, wave, spec) wave = newwave spec = newspec # apply rotational broadening print('Applying rotational broadening, please be patient...') bspec = pyasl.rotBroad(wave, spec, linearLD, vsini) # save the result fout = open(outfile, 'w') for w, s in zip(wave, bspec): print(w, s, file=fout) # plot the result plt.title("Rotational broadening") plt.xlabel("Wavelength") plt.ylabel("Arbitrary flux") plt.plot(wave, spec, 'k-') plt.plot(wave, bspec, 'r-') plt.show()
plt.imshow(np.nansum(posterior,axis=2),interpolation="nearest",origin="lower",extent=[vsini_vec[0],vsini_vec[-1],limbdark_vec[0],limbdark_vec[-1]],aspect="auto") plt.subplot(3,3,7) plt.imshow(np.nansum(posterior,axis=0).T,interpolation="nearest",origin="lower",extent=[vsini_vec[0],vsini_vec[-1],RV_vec[0],RV_vec[-1]],aspect="auto") plt.subplot(3,3,8) plt.imshow(np.nansum(posterior,axis=1).T,interpolation="nearest",origin="lower",extent=[limbdark_vec[0],limbdark_vec[-1],RV_vec[0],RV_vec[-1]],aspect="auto") if 1: c_kms = 299792.458 max_k,max_l,max_m = np.unravel_index(np.argmax(posterior),posterior.shape) vsini,limbdark,rv=vsini_grid[max_k,max_l,max_m],limbdark_grid[max_k,max_l,max_m],RV_grid[max_k,max_l,max_m] refstarpho_spec = refstarpho_spec_func(wvs*(1-rv/c_kms)) broadened_refstarpho = pyasl.rotBroad(wvs, refstarpho_spec, limbdark, vsini) model = [atm*broadened_refstarpho for atm in atm_model] # model = [broadened_refstarpho for atm in atm_model] model = [LPFvsHPF(vec,cutoff)[1] for vec in model] model = [vec/np.nanstd(vec) for vec in model] model = np.array(model).transpose() # model = model[:,5:6] sigmas_vec = np.ones(spec.shape) logdet_Sigma = np.sum(2*np.log(sigmas_vec)) model = model/sigmas_vec[:,None] spec_hpf = LPFvsHPF(spec,cutoff)[1] spec_norma = np.nanstd(spec_hpf)
def calc_log_likelihood(self,param): # param is spin velocity investigated spin_vel,radial_vel = param log_prior = 0. log_likelihood = 0. self.function_calls += 1 # check priors log_prior += self.log_prior(spin_vel,'spin_vel') log_prior += self.log_prior(radial_vel,'radial_vel') if log_prior == -np.inf: return -np.inf wlen,flux={},{} for key in self.t_wvl.keys(): wlen[key],flux[key] = self.t_wvl[key],self.t_flux[key] # Doppler shift if 'radial_vel' in self.params_names: for key in wlen.keys(): wlen[key],flux[key] = doppler_shift(wlen[key],flux[key],radial_vel) # rot. broad. spectrum if 'spin_vel' in self.params_names: for key in self.t_wvl.keys(): if self.algo == 'fast': flux[key] = pyasl.fastRotBroad(wlen[key],flux[key],0,spin_vel) else: # 'slow' flux[key] = pyasl.rotBroad(wlen[key],flux[key],0,spin_vel) # make sure that we have same wvl coverage as data for key in wlen.keys(): wlen[key],flux[key] = np.transpose([[wlen[key][i],flux[key][i]] for i in range(len(wlen[key])) if wlen[key][i] >= self.d_wvl[key][0] and wlen[key][i] <= self.d_wvl[key][-1]]) # calculate CCF between template and rot. broadened template CC_range_i = {} for key in self.t_wvl.keys(): dRV,CC_range_i[key] = pyasl.crosscorrRV(wlen[key],flux[key], self.t_wvl[key],self.t_flux[key], rvmin=self.rvmin,rvmax=self.rvmax,drv=self.drv, skipedge=self.skipedge ) CC = np.array([sum([CC_range_i[key][drv_i] for key in CC_range_i.keys()]) for drv_i in range(len(dRV))]) drv_max_i = np.argmax(CC) drv_max = dRV[drv_max_i] # normalise CCF CC_max = CC[drv_max_i] CC = CC/CC_max """ # the problem of just shifting the CCF by some RV value is that is doesnt account for the fact that the doppler shift also stretches the spectrum CCF_new = CC if 'radial_vel' in self.params_names: CCF_f = interp1d(dRV + radial_vel,CC,fill_value = 0) CCF_new = CCF_f(self.CCF_dRV) """ CC_final = [CC[i] for i in range(len(CC)) if dRV[i] >= self.CCF_dRV[0] and dRV[i] <= self.CCF_dRV[-1]] assert(len(CC_final)==len(self.CCF_CC)) for rv_i in range(len(self.CCF_dRV)): log_likelihood += -0.5*((CC_final[rv_i]-self.CCF_CC[rv_i])/self.std_CCF)**2 if self.function_calls%self.write_threshold == 0: hours = (time() - self.start_time)/3600.0 info_list = [self.function_calls, log_likelihood, hours] with open(self.diag_file,'a') as f: for i in np.arange(len(info_list)): if (i == len(info_list) - 1): f.write(str(info_list[i]).ljust(15) + "\n") else: f.write(str(info_list[i]).ljust(15) + " ") if self.function_calls%(self.write_threshold) == 0: plt.figure() plt.plot(self.CCF_dRV,self.CCF_CC,'r',label='CCF with data') plt.plot(dRV,CC,'k',label='CCF with template') plt.legend() plt.savefig(self.output_dir + 'model/CCF_'+str(self.function_calls)+'.png') print(log_prior + log_likelihood) print("--> ", self.function_calls) return log_prior + log_likelihood
def _fitRV(paras): vsini,wvs,science_spec_hpf,science_spec_lpf, science_err,slit1_spec_hpf, dark1_spec_hpf, dark2_spec_hpf,\ wvs4broadening,planet_convspec_broadsampling,A0_spec,phoenix_A0_func,\ A0_rv,A0_baryrv,science_baryrv,c_kms,cutoff,rv_list = paras if vsini != 0: planet_broadspec = pyasl.rotBroad(wvs4broadening, planet_convspec_broadsampling, 0.5, vsini) planet_broadspec_func = interp1d(wvs4broadening, planet_broadspec, bounds_error=False, fill_value=np.nan) else: planet_broadspec_func = interp1d(wvs4broadening, planet_convspec_broadsampling, bounds_error=False, fill_value=np.nan) where_data_nans = np.where(np.isnan(science_spec_hpf)) transmission = A0_spec / phoenix_A0_func(wvs * (1 - (A0_rv - A0_baryrv) / c_kms)) transmission[where_data_nans] = np.nan m1_norv = planet_broadspec_func(wvs) * transmission m1_norv = m1_norv / np.nanmean(m1_norv) * np.nanmean(science_spec_lpf) m1_norv_spec_hpf = np.zeros(science_spec_lpf.shape) for order_id in range(Norders): _, m1_norv_spec_hpf[order_id, :] = LPFvsHPF(m1_norv[order_id, :], cutoff=cutoff) fluxout = np.zeros((2, 5, np.size(rv_list))) dAICout = np.zeros((5, np.size(rv_list))) logpostout = np.zeros((5, np.size(rv_list))) data_hpf_list = [ science_spec_hpf, m1_norv_spec_hpf, slit1_spec_hpf, dark1_spec_hpf, dark2_spec_hpf ] for data_id, data_hpf in enumerate(data_hpf_list): where_data_nans = np.where(np.isnan(data_hpf)) transmission = A0_spec / phoenix_A0_func(wvs * (1 - (A0_rv - A0_baryrv) / c_kms)) transmission[where_data_nans] = np.nan # m2 = phoenix_host_func(wvs * (1 - (host_rv - science_baryrv) / c_kms)) * transmission # for order_id in range(Norders): # m2_tmp_lpf, m2_tmp_hpf = LPFvsHPF(m2[order_id, :], cutoff=cutoff) # m2[order_id, :] = m2_tmp_hpf / m2_tmp_lpf * science_spec_lpf[order_id, :] for rv_id, rv in enumerate(rv_list): # print(vsini_id,np.size(vsini_list),rv_id,np.size(rv_list)) m1 = planet_broadspec_func( wvs * (1 - (rv - science_baryrv) / c_kms)) * transmission for order_id in range(Norders): m1[order_id, :] = LPFvsHPF(m1[order_id, :], cutoff=cutoff)[1] # science_spec_hpf[np.where(np.isnan(m1)*np.isnan(m2))] = np.nan ravelHPFdata = np.ravel(data_hpf) ravelwvs = np.ravel(wvs) # plt.figure(1) # plt.plot(np.ravel(wvs), np.ravel(transmission)) # plt.figure(2) # plt.plot(np.ravel(wvs), np.ravel(m1)) # plt.figure(3) # plt.plot(np.ravel(wvs), ravelHPFdata) # plt.show() where_data_finite = np.where(np.isfinite(ravelHPFdata)) ravelHPFdata = ravelHPFdata[where_data_finite] ravelwvs = ravelwvs[where_data_finite] sigmas_vec = np.ravel(science_err)[where_data_finite] logdet_Sigma = np.sum(2 * np.log(sigmas_vec)) m1_ravel = np.ravel(m1)[where_data_finite] # m2_ravel = np.ravel(m2)[where_data_finite] # HPFmodel_H0 = m2_ravel[:, None] # HPFmodel_H2 = m1_ravel[:, None] # HPFmodel = np.concatenate([m1_ravel[:, None], m2_ravel[:, None]], axis=1) # HPFmodel = m1_ravel[:,None] # print(np.where(np.isnan(sigmas_vec))) # print(np.sum(ravelHPFdata * m1_ravel / sigmas_vec ** 2) / np.sum((m1_ravel / sigmas_vec) ** 2)) # print(np.sum(ravelHPFdata * m1_ravel / sigmas_vec ** 2) , np.sum((m1_ravel / sigmas_vec) ** 2)) # print(np.sum(ravelHPFdata) , np.sum((m1_ravel) ** 2)) # exit() # # print(np.where(np.isnan( ravelHPFdata/sigmas_vec))) # # print(np.where(np.isnan( HPFmodel/sigmas_vec[:,None]))) # plt.plot(HPFmodel[:,0]/np.std(HPFmodel[:,0]),color="blue") # # plt.plot(HPFmodel[:,1]/np.std(HPFmodel[:,1]),color="red") # plt.plot(ravelHPFdata/np.std(ravelHPFdata),color="purple") # plt.plot(HPFmodel_H2/np.std(HPFmodel_H2),"--") # plt.show() if 1: # HPFparas = [np.sum(ravelHPFdata*HPFmodel_H2/sigmas_vec**2)/np.sum((HPFmodel_H2/sigmas_vec)**2),] # ravelHPFdata = ravelHPFdata / np.std(ravelHPFdata) # HPFmodel_H2 = HPFmodel_H2 / np.std(HPFmodel_H2) norm_HPFmodel = m1_ravel / sigmas_vec HPFparas = [ np.sum(ravelHPFdata / sigmas_vec * norm_HPFmodel) / np.sum( (norm_HPFmodel)**2), ] Npixs_HPFdata = np.size(ravelHPFdata) data_model = HPFparas[0] * m1_ravel ravelresiduals = ravelHPFdata - data_model HPFchi2 = np.nansum((ravelresiduals / sigmas_vec)**2) HPFchi2_H0 = np.nansum((ravelHPFdata / sigmas_vec)**2) a = np.zeros(np.size(HPFparas)) a[0] = 1 a_err = np.sqrt( (HPFchi2 / Npixs_HPFdata) / np.sum(norm_HPFmodel**2)) minus2logL_HPF = Npixs_HPFdata * ( 1 + np.log(HPFchi2 / Npixs_HPFdata) + logdet_Sigma + np.log(2 * np.pi)) minus2logL_HPF_H0 = Npixs_HPFdata * ( 1 + np.log(HPFchi2_H0 / Npixs_HPFdata) + logdet_Sigma + np.log(2 * np.pi)) AIC_HPF = 2 * 1 + minus2logL_HPF AIC_HPF_H0 = minus2logL_HPF_H0 # covphi = HPFchi2 / Npixs_HPFdata * (1 / np.sum(m1_ravel ** 2)) slogdet_icovphi0 = np.log(1 / np.sum((norm_HPFmodel)**2)) fluxout[0, data_id, rv_id] = HPFparas[0] fluxout[1, data_id, rv_id] = a_err dAICout[data_id, rv_id] = AIC_HPF_H0 - AIC_HPF logpostout[ data_id, rv_id] = -0.5 * logdet_Sigma - 0.5 * slogdet_icovphi0 - ( Npixs_HPFdata - 1 + 2 - 1) / (2) * np.log(HPFchi2) # print(HPFparas) # print(rv_list) # print(vsini) # plt.plot(ravelHPFdata,label="data") # plt.plot(HPFparas[0]*m1_ravel,label="m") #HPFparas[0]* # plt.plot(ravelresiduals,label="res") # plt.show() return fluxout, dAICout, logpostout
def vsini_calc_kurucz(wvl, flux, teff, logg, center_wave, flux_err, limbdark, vsini, color, folder_fig, mjd, star_name, lbdc, ltem, llog, lambd, prof, arm): ''' Function that calculate vsini using rotational broadening pyasl.rotBroad and the Kurucz Grids of model atmospheres. :param limbdark: between 0 (no) to 1 (maximum) :param wvl: observational wavelength (array) :param flux: observational flux (array) :param flux_err: observational flux error (array) :param teff: effective temperature (float) :param logg: gravitational acceleration (float) :param center_wave: centre wavelength of the line (float) :param vsini: array of possible values of vsini (array) :param color: array of colors (array) :param folder_fig: folder where the figures will be save (string) :param mjd: modified Julian date (float) :param star_name: star name (string) :param lbdc: list of wavelengths from the model (array) :param ltem: list of temperatures from the model (array) :param llog: list of logg from the model (array) :param lambd: wavelenghts from the model (array) :param prof: fluxes from the model (array) :param arm: xshooter arm (string) :return: plots, best vsini, best limbdark, and reduced chi2 values ''' print(num_spa * '-') print('\nFinding nearest model...\n') lbdc_near, idx_lbcd = find_nearest(array=np.array(lbdc), value=center_wave) teff_near, idx_teff = find_nearest(array=np.array(ltem), value=teff) logg_near, idx_logg = find_nearest(array=np.array(llog), value=logg) # Models data idx = np.where((ltem == teff_near) & (llog == logg_near)) flux_model = prof[idx, idx_lbcd, :].flatten() wave_model = lambd[idx_lbcd] sigma_model = flux_model * 0.001 wave_model, flux_model, sigma_model = \ cut_spec(wave=wave_model, flux=flux_model, err=sigma_model, center_wave=center_wave, delta=50) # ------------------------------------------------------------------------------ # Normalization print('Selecting best range ...\n') idx = np.where((wave_model > center_wave - 50) & (wave_model < center_wave + 50)) flux_model = spt.linfit(wave_model[idx], flux_model[idx]) wave_model = wave_model[idx] flux_model_list = list(flux_model) indx_min = flux_model_list.index(np.min(flux_model)) delt_2 = abs(wave_model[indx_min] - center_wave) if wave_model[indx_min] > center_wave: wave_model = wave_model - delt_2 else: wave_model = wave_model + delt_2 # ------------------------------------------------------------------------------ print('Centering the lines ...\n') flux_list = list(flux) indx_min = flux_list.index(np.min(flux_list)) plt.plot(wvl[indx_min], flux[indx_min], 'o', markersize=12) wvl_adj = wvl[indx_min - 20:indx_min + 20] flux_adj = flux[indx_min - 20:indx_min + 20] a, b, c = np.polyfit(x=wvl_adj, y=flux_adj, deg=2) fit = a * wvl**2 + b * wvl + c fit_list = list(fit) ind_adj = fit_list.index(np.min(fit)) center_adj = wvl[ind_adj] delt_2 = center_adj - center_wave if center_adj > center_wave: wvl = wvl + delt_2 else: wvl = wvl - delt_2 # plt.plot(wvl, fit, '-.') # ------------------------------------------------------------------------------ # Looping print('Adjusting to vsinis...\n') rflux_arr, chi2red_arr, vsini_arr_2, limbdark_arr = [], [], [], [] for k in range(len(vsini)): # print('Adjust to vsini = %0.2f ...\n' % vsini[k]) for w in range(len(limbdark)): wvl_rflux = np.linspace(np.min(wave_model), np.max(wave_model), len(flux_model)) flux_model = np.interp(wvl_rflux, wave_model, flux_model) rflux = pyasl.rotBroad(wvl_rflux, flux_model, limbdark[w], vsini[k], edgeHandling='firstlast') # plt.plot(wave_model, flux_model, label=('A={:.2f} al={:.2f}'. # format(A[i], al[j]))) flux_interp = np.interp(wvl_rflux, wvl, flux) flux_err_interp = np.interp(wvl_rflux, wvl, flux_err) chi2red = (sum(((flux_interp - rflux) / flux_err_interp)**2)) / \ (len(rflux) - 1 - 2) rflux_arr.append(rflux) vsini_arr_2.append(vsini[k]) limbdark_arr.append(limbdark[w]) chi2red_arr.append(chi2red) ind_min_adj = chi2red_arr.index(np.min(chi2red_arr)) best_vsini = vsini_arr_2[ind_min_adj] best_limbd = limbdark_arr[ind_min_adj] # ------------------------------------------------------------------------------ print('Plotting and saving...') plt.vlines(x=center_wave, ymin=0.0, ymax=2.0, linestyles='--') plt.plot(wave_model, flux_model, label='model', color='orange') plt.plot(wvl_rflux, rflux_arr[ind_min_adj], label=('vsini={:.2f}, \ limbdark={:.2f}'.format(best_vsini, best_limbd)), color='lightgreen') plt.plot(wvl, flux, 'b-', label='original') # Plot the results plt.title("Rotational broadening") plt.xlabel("Wavelength $[\AA]$") plt.ylabel("Normalized flux") plt.ylim(0.3, 1.2) plt.xlim(center_wave - 30, center_wave + 30) plt.legend(loc='best', fontsize=12) if os.path.isdir(folder_fig + star_name + '/vsini/') is False: os.mkdir(folder_fig + star_name + '/vsini/') folder_fig_2 = folder_fig + star_name + '/vsini/' name_fig = folder_fig_2 + star_name + '_' + str(mjd) + '_' + \ arm + '_' + 'vsini.png' plt.tight_layout() plt.savefig(name_fig) plt.close() return chi2red_arr, vsini_arr_2
phoenix_refstar_conv = convolve_spectrum(phoenix_wvs,phoenix_refstar,R0,specpool) with open(phoenix_refstar_filename, 'w+') as csvfile: csvwriter = csv.writer(csvfile, delimiter=' ') csvwriter.writerows([["wvs","spectrum"]]) csvwriter.writerows([[a,b] for a,b in zip(phoenix_wvs,phoenix_refstar_conv)]) with open(phoenix_refstar_filename, 'r') as csvfile: csv_reader = csv.reader(csvfile, delimiter=' ') list_starspec = list(csv_reader) refstarpho_spec_str_arr = np.array(list_starspec, dtype=np.str) col_names = refstarpho_spec_str_arr[0] refstarpho_spec = refstarpho_spec_str_arr[1::,1].astype(np.float) refstarpho_spec_wvs = refstarpho_spec_str_arr[1::,0].astype(np.float) where_IFSfilter = np.where((refstarpho_spec_wvs>wvs[0])*(refstarpho_spec_wvs<wvs[-1])) refstarpho_spec = refstarpho_spec/np.mean(refstarpho_spec[where_IFSfilter]) refstarpho_spec_func = interp1d(refstarpho_spec_wvs,refstarpho_spec,bounds_error=False,fill_value=np.nan) c_kms = 299792.458 refstarpho_spec = refstarpho_spec_func(wvs*(1-refstar_RV/c_kms)) broadened_refstarpho = pyasl.rotBroad(wvs, refstarpho_spec, 0.5, vsini_fixed_id) transmission_model = spec/broadened_refstarpho transmission_model = transmission_model/np.nanmean(transmission_model) plt.plot(wvs,transmission_model+specid*0.2,label=os.path.basename(spec_filename).split("bb_")[0]) # plt.show() plt.savefig(os.path.join(phoenix_folder,"fitting",star_name,star_name+"_"+os.path.basename(phoenix_model_refstar_filename).split(".fits")[0]+".png"),bbox_inches='tight') plt.close(1)
def vsini_calc_kurucz(wvl, flux, teff, logg, center_wave, flux_err, limbdark, vsini, color, folder_fig, mjd, star_name, lbdc, ltem, llog, lambd, prof, arm): ''' Function that calculate vsini using rotational broadening pyasl.rotBroad and the Kurucz Grids of model atmospheres. :param limbdark: between 0 (no) to 1 (maximum) :param wvl: observational wavelength (array) :param flux: observational flux (array) :param flux_err: observational flux error (array) :param teff: effective temperature (float) :param logg: gravitational acceleration (float) :param center_wave: centre wavelength of the line (float) :param vsini: array of possible values of vsini (array) :param color: array of colors (array) :param folder_fig: folder where the figures will be save (string) :param mjd: modified Julian date (float) :param star_name: star name (string) :param lbdc: list of wavelengths from the model (array) :param ltem: list of temperatures from the model (array) :param llog: list of logg from the model (array) :param lambd: wavelenghts from the model (array) :param prof: fluxes from the model (array) :param arm: xshooter arm (string) :return: plots, best vsini, best limbdark, and reduced chi2 values ''' print(num_spa * '-') print('\nFinding nearest model...\n') lbdc_near, idx_lbcd = find_nearest(array=np.array(lbdc), value=center_wave) teff_near, idx_teff = find_nearest(array=np.array(ltem), value=teff) logg_near, idx_logg = find_nearest(array=np.array(llog), value=logg) # Models data idx = np.where((ltem == teff_near) & (llog == logg_near)) flux_model = prof[idx, idx_lbcd, :].flatten() wave_model = lambd[idx_lbcd] sigma_model = flux_model * 0.001 wave_model, flux_model, sigma_model = \ cut_spec(wave=wave_model, flux=flux_model, err=sigma_model, center_wave=center_wave, delta=50) # ------------------------------------------------------------------------------ # Normalization print('Selecting best range ...\n') idx = np.where((wave_model > center_wave - 50) & (wave_model < center_wave + 50)) flux_model = spt.linfit(wave_model[idx], flux_model[idx]) wave_model = wave_model[idx] flux_model_list = list(flux_model) indx_min = flux_model_list.index(np.min(flux_model)) delt_2 = abs(wave_model[indx_min] - center_wave) if wave_model[indx_min] > center_wave: wave_model = wave_model - delt_2 else: wave_model = wave_model + delt_2 # ------------------------------------------------------------------------------ print('Centering the lines ...\n') flux_list = list(flux) indx_min = flux_list.index(np.min(flux_list)) plt.plot(wvl[indx_min], flux[indx_min], 'o', markersize=12) wvl_adj = wvl[indx_min - 20:indx_min + 20] flux_adj = flux[indx_min - 20:indx_min + 20] global label_emp if np.size(flux_adj) != 0: a, b, c = np.polyfit(x=wvl_adj, y=flux_adj, deg=2) label_emp = '' else: a, b, c = 0, 0, 0 print('flux_adj is empty!') label_emp = 'ERROR!!!' fit = a * wvl**2 + b * wvl + c fit_list = list(fit) ind_adj = fit_list.index(np.min(fit)) center_adj = wvl[ind_adj] delt_2 = center_adj - center_wave if center_adj > center_wave: wvl = wvl + delt_2 else: wvl = wvl - delt_2 # plt.plot(wvl, fit, '-.') # ------------------------------------------------------------------------------ # Looping print('Adjusting to vsinis...\n') rflux_arr, chi2red_arr, vsini_arr_2, limbdark_arr = [], [], [], [] for k in range(len(vsini)): # print('Adjust to vsini = %0.2f ...\n' % vsini[k]) for w in range(len(limbdark)): wvl_rflux = np.linspace(np.min(wave_model), np.max(wave_model), len(flux_model)) flux_model = np.interp(wvl_rflux, wave_model, flux_model) rflux = pyasl.rotBroad(wvl_rflux, flux_model, limbdark[w], vsini[k], edgeHandling='firstlast') # plt.plot(wave_model, flux_model, label=('A={:.2f} al={:.2f}'. # format(A[i], al[j]))) flux_interp = np.interp(wvl_rflux, wvl, flux) flux_err_interp = np.interp(wvl_rflux, wvl, flux_err) chi2red = (sum(((flux_interp - rflux) / flux_err_interp)**2)) / \ (len(rflux) - 1 - 2) rflux_arr.append(rflux) vsini_arr_2.append(vsini[k]) limbdark_arr.append(limbdark[w]) chi2red_arr.append(chi2red) ind_min_adj = chi2red_arr.index(np.min(chi2red_arr)) best_vsini = vsini_arr_2[ind_min_adj] best_limbd = limbdark_arr[ind_min_adj] # ------------------------------------------------------------------------------ print('Plotting and saving...') plt.title(label_emp) plt.vlines(x=center_wave, ymin=0.0, ymax=2.0, linestyles='--') plt.plot(wave_model, flux_model, label='model', color='orange') plt.plot(wvl_rflux, rflux_arr[ind_min_adj], label=('vsini={:.2f}, \ limbdark={:.2f}'.format(best_vsini, best_limbd)), color='lightgreen') plt.plot(wvl, flux, 'b-', label='original') # Plot the results plt.title("Rotational broadening") plt.xlabel("Wavelength $[\AA]$") plt.ylabel("Normalized flux") plt.ylim(0.3, 1.2) plt.xlim(center_wave - 30, center_wave + 30) plt.legend(loc='best', fontsize=12) if os.path.isdir(folder_fig + star_name + '/vsini/') is False: os.mkdir(folder_fig + star_name + '/vsini/') folder_fig_2 = folder_fig + star_name + '/vsini/' name_fig = folder_fig_2 + star_name + '_' + str(mjd) + '_' + \ arm + '_' + 'vsini.png' plt.tight_layout() plt.savefig(name_fig) plt.close() return chi2red_arr, vsini_arr_2
os.system('rm -f out?') return w, f if __name__ == '__main__': region = [10130, 10227] lines = np.loadtxt('/home/daniel/.plotfits/linelist.moog', usecols=(0, )) # 10 Leo (4821, 2.41, 0.04, 1.26) w10Leo = get_wavelength(fits.getheader('10LeoYJ.fits')) f10Leo = fits.getdata('10LeoYJ.fits') f10Leo, w10Leo = dopplerShift(w10Leo, f10Leo, -82.53) idx = (region[0] <= w10Leo) & (w10Leo <= region[1]) w10Leo, f10Leo = w10Leo[idx], f10Leo[idx] w1, f1 = create_synthetic('10 Leo') f1 = pyasl.rotBroad(w1, f1, 0.40, 5) # Arcturus (4269, 1.69, 1.41, -0.46) warc = get_wavelength(fits.getheader('ArcturusSummer.fits')) farc = fits.getdata('ArcturusSummer.fits') idx = (region[0] <= warc) & (warc <= region[1]) warc, farc = warc[idx], farc[idx] w2, f2 = create_synthetic('Arcturus') f2 = pyasl.rotBroad(w2, f2, 0.40, 4.5) # plt.subplot(211) plt.plot(warc, farc) plt.plot(w2, f2, '--r') # plt.subplot(212) plt.plot(w10Leo, f10Leo - 0.4)
with pyfits.open(phoenix_wv_filename) as hdulist: phoenix_wvs = hdulist[0].data / 1.e4 crop_phoenix = np.where( (phoenix_wvs > wvs[0] - (wvs[-1] - wvs[0]) / 4) * (phoenix_wvs < wvs[-1] + (wvs[-1] - wvs[0]) / 4)) phoenix_wvs = phoenix_wvs[crop_phoenix] with pyfits.open(phoenix_A0_filename) as hdulist: phoenix_A0 = hdulist[0].data[crop_phoenix] phoenix_A0_func = interp1d(phoenix_wvs, phoenix_A0, bounds_error=False, fill_value=np.nan) wvs4broadening = np.arange(phoenix_wvs[0], phoenix_wvs[-1], 1e-4) broadened_phoenix_A0 = pyasl.rotBroad(wvs4broadening, phoenix_A0_func(wvs4broadening), standard_limbdark, standard_vsini) broadened_phoenix_A0 = convolve_spectrum(wvs4broadening, broadened_phoenix_A0, R, mypool=mypool) phoenix_A0_func = interp1d( wvs4broadening / (1 - (standard_rv + standard_bary_rv) / const.c.to('km/s').value), broadened_phoenix_A0, bounds_error=False, fill_value=np.nan) telluric_transmission = mn_standard_spec / phoenix_A0_func(wvs) # plt.plot(wvs,telluric_transmission/np.nanmean(telluric_transmission),label="new") # tr_list = []