def Fits_Info(plate,mjd,fiber,version): from astropy.io import fits from PyAstronomy.pyasl import helcorr # Now we stitch together the server path to each file. Careful though as there is a folder for the APO telescope and one for LCO that # contain different field. So we will check against LCO as it contains fewer plates lco = [9753,9761,9762,9856,9906,9907,9908] apopath = '/Volumes/CoveyData/APOGEE_Spectra/preDR15/apogee/spectro/redux/visits/apo25m/' lcopath = '/Volumes/CoveyData/APOGEE_Spectra/preDR15/apogee/spectro/redux/visits/lco25m/' int_plate = int(plate) # Setting path to file if int_plate in lco: filepath = lcopath + str(plate) + '/' + str(mjd) + '/asVisit-apogee2-' + str(plate) + '-' + str(mjd) + '-' + str(fiber) + '.fits' else: filepath = apopath + str(plate) + '/' + str(mjd) + '/apVisit-' + str(version) + '-' + str(plate) + '-' + str(mjd) + '-' + str(fiber) + '.fits' # Now we can open the fits file on the server try: fitsfile = fits.open(filepath) header = fitsfile[0].header except: print('Bad file path!') ''' Get: wavegrid, flux, error, VHELIO, RA, DEC, TELESCOP ''' # Grabbing the data for the wavelength and flux wavedata = fitsfile[4].data fluxdata = fitsfile[1].data ferrordata = fitsfile[2].data # Getting location information and the barycentric correction ra = header['RA'] dec = header['DEC'] jd = header['JD-MID'] telescope = header['TELESCOP'] # Sometimes there is no reported BC so we need to get one from the helcorr package try: vbc = header['BC'] except: if telescope == 'apo25m': vbc,hjd = helcorr(-105.4913,36.4649,2788,ra,dec,jd) else: vbc,hjd = helcorr(-70.413336,-29.05256,2380,ra,dec,jd) fitsfile.close() return(wavedata,fluxdata,ferrordata,vbc,ra,dec)
def compute_vbarycenter( spectrum): """ Compute the velocity correction to Barycentric for this date and direction """ global firstRun if baryCenterAvailable: longitude = spectrum.tellon latitude = spectrum.tellat altitude = spectrum.telelev ra2000 = spectrum.ra dec2000 = spectrum.dec # need to convert date time to Julian date jd = jdutil.datetime_to_jd(spectrum.utc) # Calculate barycentric correction (debug=True show # various intermediate results) corr, hjd = pyasl.helcorr(longitude, latitude, altitude, \ ra2000, dec2000, jd, debug=doDebug) if doDebug or firstRun: print("Barycentric correction [km/s]: %8.3f" % (corr)) firstRun = False else: corr = 0. return corr
def setjd(header, ra, dec): try: dateobs = header["EMMNWB"] t = astropy.time.Time(dateobs, format='fits', scale='utc') except ValueError: dateobs = header["DATE-OBS"] t = astropy.time.Time(dateobs, format='fits', scale='utc') try: jd = float(header["JD"]) except KeyError: jd = t.jd # Coordinates of European Southern Observatory # (Coordinates of UT1) latitude = -30.169661 longitude = -70.806525 altitude = 2207. # Coordinates of HD 12345 (J2000) ra2000 = convHMS(ra) dec2000 = convDMS(dec) # Calculate barycentric correction (debug=True show # various intermediate results) corr, hjd = pyasl.helcorr(longitude, latitude, altitude, \ ra2000, dec2000, jd, debug=False) # #if abs(float(header["JD"])-jd) > 0.003: # print "ERROR, check JD of exposures! mismatch between DATE-OBS or EMMNWB and JD header" # #sys.exit(1) # corr = header["BCV"] # strout = header["OBJECT"] + " " + header["DATE-OBS"] # strout = open("badfits_JD").read() + strout+"\n" # o = open("badfits_JD","w") # o.write(strout) # o.close() bjd = bjdcalc(hjd, ra2000, dec2000) print corr, jd, hjd, bjd return corr, jd, hjd, bjd
def shift(wl, spec, rv, bcarr, **kwargs): """for bccorr, use bcarr as well, which should be EITHER: 1) the pure barycentric velocity calculated elsewhere OR 2) a dictionary with the following entries (all as floats, except the observatory name code, if using): {'ra': RA (deg), 'dec': dec (deg), 'obs': observatory name or location of observatory, 'date': JD of midpoint of observation} The observatory can either be an observatory code as recognized in the PyAstronomy.pyasl.Observatory list of observatories, or an array containing longitude, latitude (both in deg) and altitude (in meters), in that order. To see a list of observatory codes use "PyAstronomy.pyasl.listobservatories()". Args: wl (list): wavelength array spec (list): flux array rv (float): Rotational velocity value bcarr (list): if len = 1, contains a precomputed barycentric velocity. Otherwise, should be a dictionary with the following properties: either an "obs" keyword and code from pyasl or a long, lat, alt set of floats identifying the observatory coordinates. Returns: barycentric velocity corrected wavelength vector using bccorr(). """ if len(bcarr) == 1: bcvel = bcarr[0] if len(bcarr) > 1: if isinstance(bcarr['obs'], str): try: ob = pyasl.observatory(bcarr['obs']) except: print( 'This observatory code didn\'t work. Try help(shift) for more information' ) lon, lat, alt = ob['longitude'], ob['latitude'], ob['altitude'] if np.isarray(bcarr['obs']): lon, lat, alt = bcarr['obs'][0], bcarr['obs'][1], bcarr['obs'][2] bcvel = pyasl.helcorr(lon, lat, alt, bcarr['ra'], bcarr['dec'], bcarr['date'])[0] wl = bccorr() return ''
def combine_header(header_list): new_header = header_list[0] new_header["MJD-OBS"] = mean(return_header_numbers(header_list, "MJD-OBS")) new_header["AIRMASS"] = mean(return_header_numbers(header_list, "AIRMASS")) new_header["EXPTIME"] = sum(return_header_numbers(header_list, "EXPTIME")) jd = new_header["MJD-OBS"] + 2400000.5 t = astropy.time.Time(jd, format='jd', scale='utc') new_header["DATE-OBS"] = str(t.fits) # Coordinates of European Southern Observatory # (Coordinates of UT1) longitude = new_header["LONG-OBS"] latitude = new_header["LAT-OBS"] altitude = new_header["ALT-OBS"] # Coordinates of HD 12345 (J2000) ra2000 = convHMS(new_header["RA"]) dec2000 = convDMS(new_header["DEC"]) # Calculate barycentric correction (debug=True show # various intermediate results) corr, hjd = pyasl.helcorr(longitude, latitude, altitude, \ ra2000, dec2000, jd, debug=False) print jd, corr, hjd new_header.set('HJD', hjd) new_header.set('JD', jd) new_header.set('BCORR', corr) new_header.set('AP0', "Spectrum FFdiv+BKsub") new_header.set('AP1', "Background FFdiv") new_header.set('AP2', "ThAr") new_header.set('AP3', "Spectrum BKsub") new_header.set('AP4', "Background") new_header.set('AP5', "Wavelength") return new_header, string.replace(string.replace(str(t.fits), "(UTC)", ""), ":", "-")
def revise_wavelength(self): fig = plt.figure(1) ax = fig.add_subplot(111) ax.plot(self.sky_sci) ylim = ax.get_ylim() xpos = [] def onclick(event): print('%s click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' % ('double' if event.dblclick else 'single', event.button, event.x, event.y, event.xdata, event.ydata)) xpos.append(event.xdata) ax.plot([event.xdata,event.xdata],ylim) plt.draw() cid = fig.canvas.mpl_connect('button_press_event', onclick) plt.show(1) cid = fig.canvas.mpl_disconnect(cid) pixelpos = np.array(xpos) fig = plt.figure(1) ax = fig.add_subplot(111) ax.plot(self.wave, self.sky_model) ylim = ax.get_ylim() for pixel in pixelpos: pass xpos = [] cid = fig.canvas.mpl_connect('button_press_event', onclick) plt.show(1) cid = fig.canvas.mpl_disconnect(cid) wavepos = np.array(xpos) coeffs = np.polyfit(pixelpos,wavepos,1) new_wave_func = np.poly1d(coeffs) self.new_wave = new_wave_func(np.arange(self.wave.size)) # Remember to sample the sky model on the new wavelength grid self.sky_model = np.interp(self.new_wave,self.wave,self.sky_model) self.wave = self.new_wave plt.plot(self.wave,self.sky_std/np.nanmedian(self.sky_std)) plt.plot(self.wave,self.sky_model/np.nanmedian(self.sky_model)) plt.show() # Calculate the barycentric correction lat = 19.8238 lon = 155.4689 alt = 4213.0 jd = Time(self.header['DATE-OBS']).jd ra = Angle(self.header['TARGRA'], unit='hourangle').degree dec = Angle(self.header['TARGDEC'], unit=u.deg).degree corr, hjd = pyasl.helcorr(lon, lat, alt, \ ra, dec, jd) cc = 299792.458 #km/s self.wave *= (1.0 + corr/cc)
def extract_spectra(self, files, extractor, star_dark=None, flat_files=None, flat_dark=None, location=('151.2094','-33.865',100.0), coord=None, do_bcor=True, ra_dec_hr=False): """Extract the spectrum from a file, given a dark file, a flat file and a dark for the flat. The process is: 1) Dark correcting the data and the flat fields. 2) Computing (but not applying) Barycentric corrections. 3) Extracting the data and the flat fields using the extract module, to form :math:`f_m(x)`, the flux for orders m and dispersion direction pixels x. 4) Normalising the flat fields, so that the median of each order is 1.0. 5) Dividing by the extracted flat field. Uncertainties from the flat field are added in quadrature. TODO: Not the neatest implementation, but should account for the fact that there are no flats or darks for the ThAr frames. Might be worth tidying up and making the implementation a little more elegant. Parameters ---------- files: list of strings One string for each file. CAn be on separate nights - a full pathname should be given. star_dark: flat_files: list of strings. One string for each star file. CAn be on separate nights - a full pathname should be given. flat_dark: location: (lattitude:string, longitude:string, elevation:string) The location on Earth where the data were taken. coord: astropy.coordinates.sky_coordinate.SkyCoord The coordinates of the observation site do_bcor: boolean Flag for whether to do barycentric correction Returns ------- fluxes: 3D np.array(float) Fluxes of form (Observation, Order, Flux/pixel) vars: 3D np.array(float) Variance of form (Observation, Order, Variance/pixel) bcors: 1D np.array(float) Barycentric correction for each observation. wave: 2D np.array(float) Wavelength coordinate map of form (Order, Wavelength/pixel) mjds: 1D np.array(float) Modified Julian Date (MJD) of each observation. """ # Initialise list of return values # Each index represents a single observation fluxes = [] vars = [] dates = [] bcors = [] #!!! This is dodgy, as files and flat_files should go together in a dict for ix,file in enumerate(files): # Dark correct the science and flat frames # Only if flat/darks have been supplied --> ThAr might not have them # If not supplied, just use science/reference data try: # Dark correct science frames if len(star_dark) > 0: data = pyfits.getdata(file) - star_dark else: data = pyfits.getdata(file) # Dark correct flats if len(flat_files) > 0 and len(flat_dark) > 0: flat = pyfits.getdata(flat_files[ix]) - flat_dark elif len(flat_files) > 0: flat = pyfits.getdata(flat_files[ix]) except: print('Unable to calibrate file ' + file + '. Check that format of data arrays are consistent.') print(pyfits.getdata(file).shape) print(star_dark.shape) continue header = pyfits.getheader(file) date = Time(header['JD'], format='jd', location=location) dates.append(date) # Determine the barycentric correction if do_bcor: if not coord: # Depending on whether the RA and DEC is saved in hours or # degrees, load and create a SkyCoord object if ra_dec_hr: ra_deg = float(header['RA'])*15 else: ra_deg = float(header['RA']) dec_deg = float(header['DEC']) coord = SkyCoord(ra=ra_deg, dec=dec_deg, unit='deg') if not location: location=(float(header['LONG']), float(header['LAT']), float(header['HEIGHT'])) #(obs_long, obs_lat, obs_alt, ra2000, dec2000, jd, debug=False) #pdb.set_trace() bcors.append(1e3*pyasl.helcorr(float(location[0]), float(location[1]),location[2],coord.ra.deg, coord.dec.deg,date.jd)[0] ) else: bcors.append(0.0) # Extract the fluxes and variance for the science and flat frames print("Extracting spectra from file #", str(ix)) flux, var = extractor.one_d_extract(data=data, rnoise=20.0) # Continue only when flats have been supplied # Perform flat field correction and adjust variances if len(flat_files) > 0: flat_flux, fvar = extractor.one_d_extract(data=flat, rnoise=20.0) for j in range(flat_flux.shape[0]): medf = np.median(flat_flux[j]) flat_flux[j] /= medf fvar[j] /= medf**2 #Calculate the variance after dividing by the flat var = var/flat_flux**2 + fvar * flux**2/flat_flux**4 #Now normalise the flux. flux /= flat_flux # Regardless of whether the data has been flat field corrected, # append to the arrays and continue fluxes.append(flux[:,:,0]) vars.append(var[:,:,0]) fluxes = np.array(fluxes) vars = np.array(vars) bcors = np.array(bcors) mjds = np.array([d.mjd for d in dates]) return fluxes, vars, bcors, mjds
while not all_rvs_calculated: num_rvs_extracted += high - low # Load in a segment of files fluxes, vars, wave, bcors, mjds = rv.load_fluxes(extracted_files[low:high]) bcors = [] # Calculate the barycentric correction for each observation, based on the # instantaneous position of the sun for t in mjds: time = Time(t, format="mjd") coord = SkyCoord(coordinates.get_sun(time)) location = location=('151.2094','-33.865',100.0) bcors.append(1e3*pyasl.helcorr(float(location[0]), float(location[1]), location[2], coord.ra.deg, coord.dec.deg, time.jd)[0] ) nf = fluxes.shape[0] nm = fluxes.shape[1] ny = fluxes.shape[2] # Calculate the RVs rvs, rv_sigs = rv.calculate_rv_shift(wave_ref, ref_spect, fluxes, vars, bcors, wave) rv_list.append(rvs) rv_sig_list.append(rv_sigs) bcors_list.append(bcors) mjds_list.append(mjds) # Move to next segment
def revise_wavelength(self): fig = plt.figure(1) ax = fig.add_subplot(111) ax.plot(self.sky_sci) ylim = ax.get_ylim() xpos = [] def onclick(event): print('%s click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' % ('double' if event.dblclick else 'single', event.button, event.x, event.y, event.xdata, event.ydata)) xpos.append(event.xdata) ax.plot([event.xdata, event.xdata], ylim) plt.draw() cid = fig.canvas.mpl_connect('button_press_event', onclick) plt.show(1) cid = fig.canvas.mpl_disconnect(cid) pixelpos = np.array(xpos) fig = plt.figure(1) ax = fig.add_subplot(111) ax.plot(self.wave, self.sky_model) ylim = ax.get_ylim() for pixel in pixelpos: pass xpos = [] cid = fig.canvas.mpl_connect('button_press_event', onclick) plt.show(1) cid = fig.canvas.mpl_disconnect(cid) wavepos = np.array(xpos) coeffs = np.polyfit(pixelpos, wavepos, 1) new_wave_func = np.poly1d(coeffs) self.new_wave = new_wave_func(np.arange(self.wave.size)) # Remember to sample the sky model on the new wavelength grid self.sky_model = np.interp(self.new_wave, self.wave, self.sky_model) self.wave = self.new_wave plt.plot(self.wave, self.sky_std / np.nanmedian(self.sky_std)) plt.plot(self.wave, self.sky_model / np.nanmedian(self.sky_model)) plt.show() # Calculate the barycentric correction lat = 19.8238 lon = 155.4689 alt = 4213.0 jd = Time(self.header['DATE-OBS']).jd ra = Angle(self.header['TARGRA'], unit='hourangle').degree dec = Angle(self.header['TARGDEC'], unit=u.deg).degree corr, hjd = pyasl.helcorr(lon, lat, alt, \ ra, dec, jd) cc = 299792.458 #km/s self.wave *= (1.0 + corr / cc)
fitspath = serverpath + str(plate) + '/' + str(mjd) + '/apVisit-r8-' + str(plate) + '-' + str(mjd) + '-' + str(fiber) + '.fits' openfile = fits.open(fitspath) header = openfile[0].header try: vbc = header['VHELIO'] except: ra = header['RA'] dec = header['DEC'] jd = header['JD-MID'] height = 2788 longg = -105.4913 lat = 36.4649 vbc,hjd = helcorr(longg,lat,height,ra,dec,jd) else: serverpath = '/Volumes/CoveyData/APOGEE_Spectra/preDR15/apogee/spectro/redux/visits/lco25m/' fitspath = serverpath + str(plate) + '/' + str(mjd) + '/asVisit-apogee2-' + str(plate) + '-' + str(mjd) + '-' + str(fiber) + '.fits' openfile = fits.open(fitspath) header = openfile[0].header try: vbc = header['VHELIO'] except: ra = header['RA'] dec = header['DEC']
def barycorr_crires(wavelength, flux, header, extra_offset=None): """Calculate Heliocentric correction values and apply to spectrum. # SHOULD test again with bary and see what the difference is. """ if header is None: logging.warning( "No header information to calculate heliocentric correction.") header = {} if (extra_offset is None) or (extra_offset == 0): return wavelength, flux try: longitude = float(header["HIERARCH ESO TEL GEOLON"]) latitude = float(header["HIERARCH ESO TEL GEOLAT"]) altitude = float(header["HIERARCH ESO TEL GEOELEV"]) ra = header["RA"] # CRIRES RA already in degrees dec = header["DEC"] # CRIRES hdr DEC already in degrees time = header["DATE-OBS"] # Observing date '2012-08-02T08:47:30.8425' # Convert easily to julian date with ephem jd = ephem.julian_date(time.replace("T", " ").split(".")[0]) # Calculate Heliocentric velocity helcorr = pyasl.helcorr(longitude, latitude, altitude, ra, dec, jd, debug=False) helcorr = helcorr[0] if header.get("BARYDONE", False): warnings.warn( "Applying barycentric correction when 'BARYDONE' already flag set." ) except KeyError as e: logging.warning("Not a valid header so can't do automatic correction.") helcorr = 0.0 if extra_offset is not None: logging.warning( "Warning!!!! have included a manual offset for testing") else: extra_offset = 0.0 helcorr_val = helcorr + extra_offset if helcorr_val == 0: logging.warning("Helcorr value was zero") return wavelength, flux else: # Apply Doppler shift to the target spectra with helcorr correction velocity nflux, wlprime = pyasl.dopplerShift(wavelength, flux, helcorr_val, edgeHandling=None, fillValue=None) logging.info( __("RV Size of Heliocenter correction for spectra {}", helcorr_val)) return wlprime, nflux
def structurate(ext, dirname, names): ext = ext.lower() for filein in names: if filein.lower().endswith(ext): filein = os.path.join(dirname, filein).strip('./') f = fits.open(filein) head = f[0].header prog = head['HIERARCH ESO OBS PROG ID'] ob = head['HIERARCH ESO OBS NAME'] if ob not in rej_ob: pplfil = head['PIPEFILE'] airm = np.mean([ head['HIERARCH ESO TEL AIRM START'], head['HIERARCH ESO TEL AIRM END'] ]) sng = np.mean([ head['HIERARCH ESO TEL AMBI FWHM START'], head['HIERARCH ESO TEL AMBI FWHM END'] ]) pla = head['HIERARCH ESO INS OBSPLATE'] expt = head['EXPTIME'] dat = head['DATE-OBS'].split('T')[0] tim = head['DATE-OBS'].split('T')[1] lat = head['HIERARCH ESO TEL GEOLAT'] lon = head['HIERARCH ESO TEL GEOLON'] elv = head['HIERARCH ESO TEL GEOELEV'] ptra = head['RA'] ptdec = head['DEC'] jld = head['MJD-OBS'] helicorr = pyasl.helcorr(lon, lat, elv, ptra, ptdec, jld + 2.4e6)[0] if prog not in filstruc.keys(): filstruc[prog] = {} infos[prog] = {} if ob not in filstruc[prog].keys(): filstruc[prog][ob] = {} infos[prog][ob] = {} if 'bin_table_info' in pplfil: tab = f[1].data assoc = {} coords = {} for l in tab: if l[3] != '': assoc[l[2] + 1] = l[3] coords[l[3]] = deg2HMS(l[4], l[5]) filstruc[prog][ob]['fibassoc'] = assoc infos[prog][ob]['coords'] = coords infos[prog][ob]['airmass'] = airm infos[prog][ob]['seeing'] = sng infos[prog][ob]['plate'] = pla infos[prog][ob]['exptime'] = expt infos[prog][ob]['date'] = dat infos[prog][ob]['time'] = tim infos[prog][ob]['vhelio'] = helicorr infos[prog][ob]['rv'] = {} elif ('mwfxb' in pplfil) and ('sigma' not in pplfil): if head['EXTNAME'].strip() == 'CCD-44': chip = 'lower' else: chip = 'upper' fibre = int(pplfil.strip('.fits').split('_')[2]) if fibre not in filstruc[prog][ob].keys(): filstruc[prog][ob][fibre] = {} flux = f[0].data wavest = head['CRVAL1'] wbin = head['CDELT1'] wave = [wavest + wbin * i for i in range(len(flux))] filstruc[prog][ob][fibre][chip] = [wave, flux]
def fill_headers(file_names, device): if device == 'mres': obsname = 'TNO' # Thai National Observatory, Doi Inthanon obslat = 18.573828 # Latitude of the observatory obslon = 98.4817485 # Longitude of the observatory, E obsalt = 2549. # Altitude of the observatory gain = 0.55 # Electronic gain in e-/ADU rdnoise = 2.0 # CCD readout noise elif device == 'eshel_ccs': obsname = 'CCS' # NARIT provincial observatory, Chachoengsao obslat = 13.593682 # Latitude of the observatory obslon = 101.256209 # Longitude of the observatory, E obsalt = 11. # Altitude of the observatory gain = 0.95 # Electronic gain in e-/ADU rdnoise = 7.0 # CCD readout noise elif device == 'eshel_krt': obsname = 'KRT' # NARIT provincial observatory, Korat obslat = 14.873460 # Latitude of the observatory obslon = 102.02883 # Longitude of the observatory, E obsalt = 245. # Altitude of the observatory gain = 0.95 # Electronic gain in e-/ADU rdnoise = 7.0 # CCD readout noise elif device == 'eshel_tno': obsname = 'TNO' # Thai National Observatory, Doi Inthanon obslat = 18.573828 # Latitude of the observatory obslon = 98.4817485 # Longitude of the observatory, E obsalt = 2549. # Altitude of the observatory gain = 0.95 # Electronic gain in e-/ADU rdnoise = 7.0 # CCD readout noise elif device == 'maestro': obsname = 'Terskol' # Terskol Observatory, Mt. Elbrus, Russia obslat = 43.272777 # Latitude of the observatory obslon = 42.500000 # Longitude of the observatory, E obsalt = 3100. # Altitude of the observatory gain = 1.0 # Electronic gain in e-/ADU rdnoise = 4.0 # CCD readout noise files, objnames = np.loadtxt(file_names, unpack=True, usecols=(0, 1), dtype=str, delimiter=';') simbad_session = Simbad() simbad_session.add_votable_fields('ra(H;ICRS;J2000)', 'dec(D;ICRS;J2000)') simbad_session.remove_votable_fields('coordinates') for ii in range(len(files)): files[ii] = files[ii].strip() objnames[ii] = objnames[ii].strip() print(f"File: {files[ii]}\tObjname: {objnames[ii]}") with fits.open(files[ii].strip(), mode='update') as hdu: hdr = hdu[0].header if hdr['NAXIS'] == 2: data = hdu[0].data.copy() elif hdr['NAXIS'] == 3: data = hdu[0].data[0].copy() if data.dtype.name != 'uint32': print(f"Scale data from {hdu[0].data.dtype.name} to 'float32'") hdu[0].data = np.float32(data) if 'DATE-OBS' in hdr: tm_start = Time.Time(hdr['DATE-OBS']) elif 'FRAME' in hdr: tm_start = Time.Time(hdr['FRAME']) if 'EXPOSURE' in hdr: texp = hdr['EXPOSURE'] * u.s hdr.set('EXPTIME', hdr['EXPOSURE'], 'Exposure (s)') else: texp = hdr['EXPTIME'] * u.s tm_mid = tm_start + texp / 2. tm_end = tm_start + texp ut = tm_mid.ymdhms[ 3] + tm_mid.ymdhms[4] / 60. + tm_mid.ymdhms[5] / 3600. ut_end = tm_end.ymdhms[ 3] + tm_end.ymdhms[4] / 60. + tm_end.ymdhms[5] / 3600. if 'DATE' not in hdr: hdr.set('DATE', hdr['DATE-OBS'].split(".")[0], 'Copy of DATE-OBS') hdr.set('DISPAXIS', 1, 'Keyword for IRAF') hdr.set('GAIN', gain, '') hdr.set('RDNOISE', rdnoise, '') hdr.set('OBSGEO-B', obslat, 'Latitude of the observatory') hdr.set('OBSGEO-L', obslon, 'Longitude of the observatory') hdr.set('OBSGEO-H', obsalt, 'Altitude of the observatory') hdr.set('OBSERVAT', obsname, 'Thai National Observatory') if (objnames[ii].lower() == "flat"): hdr.set('IMAGETYP', 'FLAT', '') elif (objnames[ii].lower() == "bias"): hdr.set('IMAGETYP', 'BIAS', '') elif (objnames[ii].lower() == "thar"): hdr.set('IMAGETYP', 'THAR', '') elif (objnames[ii].lower() == "sky"): hdr.set('IMAGETYP', 'OBJ', '') elif (objnames[ii].lower() == "dark"): hdr.set('IMAGETYP', 'DARK', '') if (objnames[ii].lower() != "flat") and (objnames[ii].lower() != "thar") \ and (objnames[ii].lower() != "bias") and (objnames[ii].lower() != "sky") and \ (objnames[ii].lower() != "dark"): query_result = simbad_session.query_object(objnames[ii]) ra = query_result['RA_H_ICRS_J2000'][0] dec = query_result['DEC_D_ICRS_J2000'][0] if 'RA' in hdr: hdr['RA'] = ra else: hdr.set('RA', ra, 'RA in hours') if 'DEC' in hdr: hdr['DEC'] = dec else: hdr.set('DEC', dec, 'DEC in degrees') if 'EPOCH' in hdr: hdr['EPOCH'] = 2000. else: hdr.set('EPOCH', 2000., 'EPOCH of coordinates') star = coord.SkyCoord(ra, dec, unit=(u.hourangle, u.deg), frame='icrs') observat = coord.EarthLocation.from_geodetic( obslon, obslat, obsalt * u.m) dateobs = np.char.replace(tm_mid.fits, 'T', ' ') dateobs = Time.Time(dateobs, scale='utc', location=observat) ltt_bary = dateobs.light_travel_time(star) bjd = dateobs.jd + ltt_bary.value bcr, hjd = helcorr(observat.lon.degree, observat.lat.degree, obsalt, star.ra.degree, star.dec.degree, dateobs.jd) hdr.set('HJD', hjd, 'Heliocentric JD') hdr.set('BJD', bjd, 'Barycentric JD') hdr.set('BARYCORR', bcr, 'Barycentric correction') hdr.set('IMAGETYP', 'OBJ', '') if 'OBJNAME' in hdr: hdr['OBJNAME'] = objnames[ii] else: hdr.set('OBJNAME', objnames[ii], '') if 'DATE-OBS' in hdr: hdr['DATE-OBS'] = tm_mid.fits else: hdr.set('DATE-OBS', tm_mid.fits, '') if 'UT' in hdr: hdr['UT'] = ut else: hdr.set('UT', ut, '') if 'UTEND' in hdr: hdr['UTEND'] = ut_end else: hdr.set('UTEND', ut_end, '') hdu[0].header = hdr hdu.flush() print("File %s has been updated" % (files[ii].strip())) print("...done") return None
def get_lines(line): ''' get_halpha, but more general ''' flux_all = [] vel_all = [] MJD_all = [] flag_all = [] ra = 84.9122543 dec = -34.07410972 if line == 'Ha': USE = [ 'ESPaDOnS', 'BeSS', 'BeSOS', 'UVES', 'FEROS', 'OPD - Musicos', 'OPD - Ecass', 'NRES' ] elif line == 'Hb': USE = ['ESPaDOnS', 'BeSOS', 'FEROS', 'NRES'] else: USE = ['ESPaDOnS', 'BeSOS', 'FEROS', 'NRES'] lbd0 = linesDict.line_names[line][1] # plot ESPaDOnS flag = 'ESPaDOnS' if flag in USE: lines = glob(direc + 'Dropbox/Amanda/Data/ESPaDOnS/new/*i.fits.gz') MJD = np.zeros([len(lines)]) JD = np.zeros([len(lines)]) #### # FROM THE HEADER ###COMMENT Correcting wavelength scale from Earth motion... ###COMMENT Coordinates of object : 5:39:38.94 & -34: 4:26.9 ###COMMENT Time of observations : 2011 11 9 @ UT 13:34:33 ###COMMENT (hour angle = 0.775 hr, airmass = 1.742 ) ###COMMENT Total exposure time : 25.0 s ###COMMENT Cosine latitude of observatory : 0.941 ###COMMENT Heliocentric velocity of observer towards star : 9.114 km/s for n in range(len(lines)): fname = lines[n] # read fits hdr_list = fits.open(fname) fits_data = hdr_list[0].data fits_header = hdr_list[0].header #f = open('{0}_{1}.txt'.format(flag, n), 'wb') #fits_header.totextfile('{0}_{1}.txt'.format(flag, n)) #read MJD MJD[n] = fits_header['MJDATE'] # #lat = fits_header['LATITUDE'] #lon = fits_header['LONGITUD'] lbd = fits_data[0, :] ordem = lbd.argsort() lbd = lbd[ordem] flux_norm = fits_data[1, ordem] vel, flux = spt.lineProf(lbd, flux_norm, lbc=lbd0) #cut = asas(vel, flux, line) #cut_all.append(cut) vel_all.append(vel) #corr_all.append(corr) flux_all.append(flux) MJD_all.append(MJD[n]) flag_all.append(flag) ## plot BeSS flag = 'BeSS' if flag in USE: lines = glob(direc + 'Dropbox/Amanda/Data/BeSS/new/*fits') MJD = np.zeros([len(lines)]) JD = np.zeros([len(lines)]) #FROM HEADER # BSS_VHEL shows the applied correction in km/s. If BSS_VHEL=0, #COMMENT no correction has been applied. The required correction given #COMMENT in BSS_RQVH (in km/s) is an escape velocity (redshift). To apply #COMMENT it within Iraf, the keyword redshift must be set to -BSS_RQVH #COMMENT and isvelocity must be set to "yes" in the dopcor task. for n in range(len(lines)): fname = lines[n] # read fits hdr_list = fits.open(fname) fits_data = hdr_list[0].data fits_header = hdr_list[0].header #fits_header.totextfile('{0}_{1}.txt'.format(flag, n)) #read MJD MJD[n] = fits_header['MID-HJD'] #HJD at mid-exposure t = Time(MJD[n], format='jd', scale='utc') MJD[n] = t.mjd #lat = fits_header['BSS_LAT'] #lon = fits_header['BSS_LONG'] #elev = fits_header['BSS_ELEV'] corr = -fits_header['BSS_RQVH'] lbd = fits_header['CRVAL1'] + fits_header['CDELT1'] * np.arange( len(fits_data)) vel, flux = spt.lineProf(lbd, fits_data, lbc=lbd0 * 10) vel = vel + corr #cut = asas(vel, flux, line) #cut_all.append(cut) vel_all.append(vel) #corr_all.append(corr) flux_all.append(flux) MJD_all.append(MJD[n]) flag_all.append(flag) # plot MUSICOS flag = 'OPD - Musicos' if flag in USE: lines = glob( direc + 'Dropbox/Amanda/Data/MUSICOS/andre/spec_*/acol/*halpha.fits') MJD = np.zeros([len(lines)]) ####################################### # Andre disse q estao corrigidos ####################################### for n in range(len(lines)): fname = lines[n] # read fits hdr_list = fits.open(fname) fits_data = hdr_list[0].data fits_header = hdr_list[0].header #fits_header.totextfile('{0}_{1}.txt'.format(flag, n)) #read MJD MJD[n] = fits_header['JD'] #JD t = Time(MJD[n], format='jd', scale='utc') MJD[n] = t.mjd #corr = fits_header['VHELIO'] lbd = fits_header['CRVAL1'] + fits_header['CDELT1'] * np.arange( len(fits_data)) vel, flux = spt.lineProf(lbd, fits_data, lbc=lbd0 * 10) vel_all.append(vel) #cut = asas(vel, flux, line) #cut_all.append(cut) #corr_all.append(corr) flux_all.append(flux) MJD_all.append(MJD[n]) flag_all.append(flag) ## plot Moser flag = 'OPD - Ecass' if flag in USE: lines = glob(direc + 'Dropbox/Amanda/Data/ecass_musicos/data/alpCol*') MJD = np.zeros([len(lines)]) ## NO INFO ON HEADER! #Latitude: 22° 32' 04" S Longitude: 45° 34' 57" W lat = -22.53444 lon = -45.5825 alt = 1864. for n in range(len(lines)): fname = lines[n] # read fits hdr_list = fits.open(fname) fits_data = hdr_list[0].data fits_header = hdr_list[0].header #fits_header.totextfile('{0}_{1}.txt'.format(flag, n)) #read MJD MJD[n] = fits_header['MJD'] #JD #t = Time(MJD[n], format = 'jd', scale='utc') #MJD[n] = t.mjd t = Time(MJD[n], format='mjd', scale='utc') JD[n] = t.jd corr, hjd = pyasl.helcorr(lon, lat, alt, ra, dec, JD[n]) #corr = 0. lbd = fits_header['CRVAL1'] + fits_header['CDELT1'] * np.arange( len(fits_data)) vel, flux = spt.lineProf(lbd, fits_data, lbc=lbd0 * 10) vel = vel + corr vel_all.append(vel) #cut = asas(vel, flux, line) #cut_all.append(cut) #corr_all.append(corr) flux_all.append(flux) MJD_all.append(MJD[n]) flag_all.append(flag) # plot UVES flag = 'UVES' if flag in USE: lines = glob(direc + 'Dropbox/Amanda/Data/UVES/new/*.fits') MJD = np.zeros([len(lines)]) JD = np.zeros([len(lines)]) #lat = -29.257778 #lon = -70.736667 # FROM HEADER ################################################################################### #HIERARCH ESO QC VRAD BARYCOR = -8.401681 / Barycentric radial velocity correctio #HIERARCH ESO QC VRAD HELICOR = -8.398018 / Heliocentric radial velocity correcti ################################################################################### for n in range(len(lines)): fname = lines[n] # read fits hdulist = fits.open(fname) # print column information #hdulist[1].columns # get to the data part (in extension 1) scidata = hdulist[1].data wave = scidata[0][0] arr1 = scidata[0][1] arr2 = scidata[0][2] fits_header = hdulist[0].header #fits_header.totextfile('{0}_{1}.txt'.format(flag, n)) MJD[n] = fits_header['MJD-OBS'] vel, flux = spt.lineProf(wave, arr1, lbc=lbd0 * 10) #vel = vel + corr #cut = asas(vel, flux, line) #cut_all.append(cut) vel_all.append(vel) #corr_all.append(corr) flux_all.append(flux) MJD_all.append(MJD[n]) flag_all.append(flag) ##plot BeSOS flag = 'BeSOS' if flag in USE: lines = glob(direc + 'Dropbox/Amanda/Data/BeSOS/2018/*.fits') MJD = np.zeros([len(lines)]) JD = np.zeros([len(lines)]) # FROM WEBSITE #All the spectra available are reduced and corrected with the heliocentric velocity for n in range(len(lines)): fname = lines[n] # read fits hdr_list = fits.open(fname) fits_data = hdr_list[0].data fits_header = hdr_list[0].header #fits_header.totextfile('{0}_{1}.txt'.format(flag, n)) #read MJD MJD[n] = fits_header['MJD'] #corr = 0. #t = Time(MJD[n], format = 'mjd', scale='utc') #JD[n] = t.jd #corr, hjd = pyasl.helcorr(lon, lat, 2400., ra, dec, JD[n]) lbd = fits_header['CRVAL1'] + fits_header['CDELT1'] * np.arange( len(fits_data)) vel, flux = spt.lineProf(lbd, fits_data, lbc=lbd0 * 10) #corr = fits_header['BVEL'] #vel = vel + corr #cut = asas(vel, flux, line) #cut_all.append(cut) vel_all.append(vel) #corr_all.append(corr) flux_all.append(flux) MJD_all.append(MJD[n]) flag_all.append(flag) #plot prof_nelson flag = 'FEROS' if flag in USE: lines = glob(direc + 'Dropbox/Amanda/Data/prof_nelson/*/*') MJD = np.zeros([len(lines)]) JD = np.zeros([len(lines)]) #lat = -29.257778 #lon = -70.736667 # FROM HEADER ################################################################### #HISTORY 'BARY_CORR' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' #HISTORY -1.5192770E+01 ################################################################### for n in range(len(lines)): fname = lines[n] # read fits hdr_list = fits.open(fname) fits_data = hdr_list[0].data fits_header = hdr_list[0].header #fits_header.totextfile('{0}_{1}.txt'.format(flag, n)) #read MJD MJD[n] = fits_header['MJD-OBS'] t = Time(MJD[n], format='mjd', scale='utc') JD[n] = t.jd #corr = 0. lbd = fits_header['CRVAL1'] + fits_header['CDELT1'] * np.arange( len(fits_data)) vel, flux = spt.lineProf(lbd, fits_data, lbc=lbd0 * 10) #vel = vel + corr vel_all.append(vel) #corr_all.append(corr) flux_all.append(flux) MJD_all.append(MJD[n]) flag_all.append(flag) flag = 'NRES' if flag in USE: lines = glob(direc + 'Dropbox/Amanda/Data/NRES/*fits*') MJD = np.zeros([len(lines)]) JD = np.zeros([len(lines)]) #lat = -29.257778 #lon = -70.736667 barycorr_list = [] # FROM HEADER ################################################################### #HISTORY 'BARY_CORR' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' #HISTORY -1.5192770E+01 ################################################################### order = linesDict.line_names[line][0] wl_list = [] flx_list = [] BJD_list = [] for n in range(len(lines)): fname = lines[n] hdulist = fits.open(fname) headers = hdulist[0].header BJD_mid_exp = headers['BJD'] #t = Time(BJD_mid_exp, format = 'jd', scale='utc') #MJD[n] = t.mjd DAY_OBS = headers['DATE-OBS'] SITE = headers['SITE'] LONG1 = headers['LONG1'] LAT1 = headers['LAT1'] HT1 = headers['HT1'] SpecRaw = hdulist[1] SpecFlat = hdulist[2] SpecBlaze = hdulist[3] ThArRaw = hdulist[4] ThArFlat = hdulist[5] WaveSpec = hdulist[6] WaveThAr = hdulist[7] SpecXcor = hdulist[8] RVBlockFit = hdulist[9] wl_list.append(WaveSpec) flx_list.append(SpecFlat) #flx_list.append(SpecBlaze) BJD_list.append(BJD_mid_exp) obs_loc = EarthLocation.from_geodetic(lat=LAT1 * u.deg, lon=LONG1 * u.deg, height=HT1 * u.m) sc = SkyCoord(ra=ra * u.deg, dec=dec * u.deg) wl_list = np.array(wl_list)[np.argsort(BJD_list)] flx_list = np.array(flx_list)[np.argsort(BJD_list)] BJD_list = np.array(BJD_list)[np.argsort(BJD_list)] for i, x in enumerate(wl_list): vel, flux = spt.lineProf(wl_list[i].data[order], flx_list[i].data[order], lbc=lbd0) #vel = vel + corr #vel_all.append(vel) #corr_all.append(corr) flux_all.append(flux) t = Time(BJD_list[i], format='jd', scale='utc') MJD[n] = t.mjd MJD_all.append(MJD[n]) flag_all.append(flag) # barycentric correction is more precise, but might be more difficult to apply barycorr = sc.radial_velocity_correction(kind='barycentric', obstime=Time(BJD_list[i], format='jd'), location=obs_loc) barycorr = barycorr.value / 1000. barycorr_list.append(barycorr) # heliocentric correction is easier, but less precise at a level of like 10 m/s #heliocorr = sc.radial_velocity_correction(kind='heliocentric',obstime=Time(BJD_list[i], format='jd'), location=obs_loc) #helcorr_list.append(heliocorr.value* au.value / (60*60*24)/ 1000.0) vl = vel + barycorr + vel * barycorr / (c.value / 1000.0) vel_all.append(vl) return MJD_all, vel_all, flux_all, flag_all
def disp_add(fits_name, thar_name, view): bcr = -999 if view: disp = matplotlib.pyplot.figure(1) ax = matplotlib.pyplot.gca() #read fits hdulist = pyfits.open(fits_name) spectrum = hdulist[0].data.copy() prihdr = hdulist[0].header hdulist.close() if 'IMAGETYP' in prihdr: if prihdr['IMAGETYP'] == 'OBJ': # Compute barycentric correction if 'BARYCORR' not in prihdr: if 'OBSGEO-B' in prihdr and 'OBSGEO-L' in prihdr and 'OBSGEO-H' in prihdr \ and 'RA' in prihdr and 'DEC' in prihdr and 'EPOCH' in prihdr: print("Compute barycentric correction...") logging.info("Compute barycentric correction...") dateobs = prihdr['DATE-OBS'] ra = prihdr['RA'] dec = prihdr['DEC'] epoch = prihdr['EPOCH'] obslat = prihdr['OBSGEO-B'] obslon = prihdr['OBSGEO-L'] obsalt = prihdr['OBSGEO-H'] star = coord.SkyCoord(ra, dec, unit=(u.hourangle, u.deg), frame='icrs') observat = coord.EarthLocation.from_geodetic(obslon, obslat, obsalt * u.m) dateobs = np.char.replace(dateobs, 'T', ' ') dateobs = time.Time(dateobs, scale='utc', location=observat) ltt_bary = dateobs.light_travel_time(star) bjd = dateobs.jd + ltt_bary.value bcr, hjd = helcorr(observat.lon.degree, observat.lat.degree, obsalt, star.ra.degree, star.dec.degree, dateobs.jd) prihdr.set('HJD', hjd, 'Heliocentric JD') prihdr.set('BJD', bjd, 'Barycentric JD') prihdr.set('BARYCORR', bcr, 'Barycentric correction') else: print("No information about the observatory in the header. Wavelength remains uncorrected") logging.warning("No information about the observatory in the header. Wavelength remains uncorrected") else: bcr = prihdr['BARYCORR'] #read solution sol_name = os.path.splitext(thar_name)[0] + '_disp.txt' print('Disp solution:', sol_name) solution = np.genfromtxt(sol_name) order_shift = int(solution[0]) x_order = int(solution[1]) y_order = int(solution[2]) solution = np.delete(solution, [0, 1, 2]) WAT2 = '' add_string = '' X = np.arange(0, spectrum.shape[1], 1) for ii in range(0, spectrum.shape[0]): O = np.empty_like(X) O.fill(ii+order_shift) WL = cheb_sol(solution, y_order)(X,O) if bcr != -999: WL = WL * np.sqrt((1. + bcr/c)/(1. - bcr/c)) # Doppler correction w1=np.min(WL) w2=np.max(WL) nw=len(X) dw=(w2-w1)/(nw-1) #-1 ## print ('Blue end:', w1, 'Red end:', w2, 'A/pix:', dw) X_lin=np.linspace(w1,w2, nw) graph_data = spectrum[ii,:] f2 = interp1d(WL, graph_data, kind='slinear', bounds_error = False) Y_lin=f2(X_lin) spectrum[ii,:] = Y_lin APNUM = (prihdr['APNUM'+str(ii+1)]) del prihdr['APNUM'+str(ii+1)] APNUM = APNUM.split() add_string = (" spec%i = \"%i %i %i %.10f %0.15f %i %i. %.2f %.2f\"" % (spectrum.shape[0]-ii, spectrum.shape[0]-ii, ii+order_shift, 0, w1, dw, nw, 0, float(APNUM[2]), float(APNUM[3]))) WAT2 = add_string + WAT2 if view: ax.plot(X_lin, Y_lin, 'r') del prihdr['CTYPE1'] del prihdr['CTYPE2'] del prihdr['CRPIX1'] del prihdr['WAT0_001'] del prihdr['WAT1_001'] del prihdr['WAT2_001'] prihdr['CTYPE1'] = 'MULTISPE' prihdr['CTYPE2'] = 'MULTISPE' prihdr['CRPIX1'] = 0 prihdr['WAT0_001'] = 'system=multispec' prihdr['WAT1_001'] = 'wtype=multispec label=Wavelength units=angstroms' WAT2 = 'wtype=multispec' + WAT2 for ii in range(1, int(2+len(WAT2)/68)): keyword = str("WAT2_%03i" % ii) prihdr[keyword] = str(WAT2[0:68]) WAT2 = WAT2[68:] prihdr['REFSPEC'] = (str(sol_name.split(os.sep)[-1]), 'WL reference spectrum') if bcr != -999: prihdr['HISTORY'] = 'Applied barycentric correction BARYCORR' hdulist[0].data = np.flip(spectrum, axis=0) new_name = os.path.splitext(fits_name)[0] + "_WCS.fits" hdulist.writeto(new_name, clobber=True) if view: matplotlib.pyplot.show() return new_name
def extract_spectra(files, star_dark, flat_files, flat_dark, location=('151.2094','-33.865',100.0), coord=None, outfile=None, do_bcor=True): """Extract the spectrum from a file, given a dark file, a flat file and a dark for the flat. Parameters ---------- files: list of strings One string for each file. CAn be on separate nights - a full pathname should be given. star_dark: flat_files: list of strings. One string for each star file. CAn be on separate nights - a full pathname should be given. flat_dark: location: (lattitude:string, longitude:string, elevation:string) The location on Earth where the data were taken. coord: outfile: do_bcor: boolean Returns ------- fluxes: vars: wave: bcors: mjds: """ # Initialise list of return values # Each index represents a single observation fluxes = [] vars = [] dates = [] bcors = [] #!!! This is dodgy, as files and flat_files should go together in a dict. !!! for ix,file in enumerate(files): # Dark correct the science and flat frames data = pyfits.getdata(file) - star_dark flat = pyfits.getdata(flat_files[ix]) - flat_dark header = pyfits.getheader(file) date = Time(header['DATE-OBS'], location=location) dates.append(date) # Determine the barycentric correction if do_bcor: if not coord: coord=SkyCoord( ra=float(header['RA']) , dec=float(header['DEC']) , unit='deg') if not location: location=( float(header['LONG']), float(header['LAT']), float(header['HEIGHT'])) #(obs_long, obs_lat, obs_alt, ra2000, dec2000, jd, debug=False) bcors.append( 1e3*pyasl.helcorr(float(location[0]),float(location[1]),location[2],coord.ra.deg, coord.dec.deg,date.jd)[0] ) else: bcors.append(0.0) # Extract the fluxes and variance for the science and flat frames flux, var = rhea2_extract.one_d_extract(data=data, rnoise=20.0) flat_flux, fvar = rhea2_extract.one_d_extract(data=flat, rnoise=20.0) for j in range(flat_flux.shape[0]): medf = np.median(flat_flux[j]) flat_flux[j] /= medf fvar[j] /= medf**2 #Calculate the variance after dividing by the flat var = var/flat_flux**2 + fvar * flux**2/flat_flux**4 #Now normalise the flux. flux /= flat_flux #pdb.set_trace() fluxes.append(flux[:,:,0]) vars.append(var[:,:,0]) fluxes = np.array(fluxes) vars = np.array(vars) bcors = np.array(bcors) mjds = np.array([d.mjd for d in dates]) # Output and save the results if not outfile is None: hl = pyfits.HDUList() hl.append(pyfits.ImageHDU(fluxes,header)) hl.append(pyfits.ImageHDU(vars)) hl.append(pyfits.ImageHDU(wave)) col1 = pyfits.Column(name='bcor', format='D', array=bcors) col2 = pyfits.Column(name='mjd', format='D', array=mjds) cols = pyfits.ColDefs([col1, col2]) hl.append(pyfits.new_table(cols)) hl.writeto(outfile, clobber=True) return fluxes,vars,wave,bcors,mjds