def get_exo_catalog(): """ Retrieve the locally saved CoRoT exoplanet database. """ exofile = config.get_datafile('catalogs/corot/exo','exo.tsv') data,units,comms = vizier.tsv2recarray(exofile) return data,units,comms
def systematics(units='muHz'): """ Return a list of known systematic effects from the Kepler satellite. """ ffile = config.get_datafile('catalogs/kepler','systematics.dat') systems = ascii.read2recarray(ffile) systems['frequency'] = conversions.nconvert(systems['unit'],units,systems['frequency']) systems['e_frequency'] = conversions.nconvert(systems['unit'],units,systems['e_frequency']) systems['w_frequency'] = conversions.nconvert(systems['unit'],units,systems['w_frequency']) return systems
def get_profile_from_file(filename): """ Used for doctest purposes: import line profile from a given test file """ filedata = np.loadtxt(config.get_datafile('Spectra_testfiles', filename), delimiter='\t').T #Calculate SNR of profiles SNR = np.nanmean(filedata[1]) / np.nanstd(filedata[1]) #returns the profile velocity, flux, and SNR return filedata[0], filedata[1], SNR
def VALD(elem=None, xmin=3200., xmax=4800., outputdir=None): """ Request linelists from VALD for each ion seperately within a specific wavelength range. elem = an array of ions e.g. ['CI','OII'], xmin and xmax: wavelength range in which the spectral lines are searched, outputdir = output directory chosen by the user. If no elements are given, this function returns all of them. @param elem: list of ions @type elem: list of str Example usage: >>> x = VALD(elem=['CI','OII'],xmin=3000., xmax=4000.) CI OII """ if elem is None: files = sorted(config.glob('VALD_individual', 'VALD_*.lijnen')) elem = [ os.path.splitext(os.path.basename(ff))[0].split('_')[1] for ff in files ] all_lines = [] for i in range(len(elem)): print(elem[i]) filename = config.get_datafile('VALD_individual', 'VALD_' + elem[i] + '.lijnen') if not os.path.isfile(filename): logger.info('No data for element ' + str(elem[i])) return None newwav, newexc, newep, newgf = np.loadtxt(filename).T lines = np.rec.fromarrays([newwav, newexc, newep, newgf], names=['wavelength', 'ion', 'ep', 'gf']) keep = (xmin <= lines['wavelength']) & (lines['wavelength'] <= xmax) if not hasattr(keep, '__iter__'): continue lines = lines[keep] if len(lines) and outputdir is not None: ascii.write_array(lines, outputdir + 'VALD_' + str(elem[i]) + '_' + str(xmin) + '_' + str(xmax) + '.dat', auto_width=True, header=True, formats=['%.3f', '%.1f', '%.3f', '%.3f']) elif len(lines): all_lines.append(lines) else: logger.debug('No lines of ' + str(elem[i]) + ' in given wavelength range') return np.hstack(all_lines)
def systematics(units='muHz'): """ Return a list of known systematic effects from the Kepler satellite. """ ffile = config.get_datafile('catalogs/kepler', 'systematics.dat') systems = ascii.read2recarray(ffile) systems['frequency'] = conversions.nconvert(systems['unit'], units, systems['frequency']) systems['e_frequency'] = conversions.nconvert(systems['unit'], units, systems['e_frequency']) systems['w_frequency'] = conversions.nconvert(systems['unit'], units, systems['w_frequency']) return systems
def calibrate(wave,flux,header=None): """ Rough calibration of Hermes spectrum. Thanks to Roy Ostensen for computing the response function via detailed modeling of Feige 66. """ #-- read instrument response function instrument = config.get_datafile('catalogs/hermes','hermes_20110319.resp') iwave,iflux = ascii.read2array(instrument).T keep = (iwave.min()<=wave) & (wave<=iwave.max()) #-- interpolate on observed wavelength array iflux = np.interp(wave[keep],iwave,iflux) return wave[keep],flux[keep]/iflux,iflux
def resolve(corot_id): """ Convert a CoRoT ID to ra,dec. @param corot_id: CoRoT exoplanet identification number @type corot_id: int @return: RA, DEC (degrees) @rtype: float,float """ exofile = config.get_datafile('catalogs/corot/exo','exo.tsv') data,units,comms = vizier.tsv2recarray(exofile) index = np.argmin(np.abs(data['CoRoT']-corot_id)) if data['CoRoT'][index]-corot_id==0: logger.info('CoRoT %s resolved to RA=%s, DEC=%s'%(corot_id,data[index]['_RAJ2000'],data[index]['_DEJ2000'])) return data[index]['_RAJ2000'],data[index]['_DEJ2000'] else: logger.info('CoRoT %s not resolved by CoRoT catalog')
def get_response(instrument='hermes'): """ Returns the response curve of the given instrument. Up till now only a HERMES response cruve is available. This response curve is based on 25 spectra of the single sdB star Feige 66, and has a wavelenght range of 3800 to 8000 A. @param instrument: the instrument of which you want the response curve @type instrument: string """ basedir = 'spectables/responses/' if instrument == 'hermes': basename = 'response_Feige66.fits' response = config.get_datafile(basedir,basename) wave, flux = fits.read_spectrum(response) return wave, flux
def get_response(instrument='hermes'): """ Returns the response curve of the given instrument. Up till now only a HERMES response cruve is available. This response curve is based on 25 spectra of the single sdB star Feige 66, and has a wavelenght range of 3800 to 8000 A. @param instrument: the instrument of which you want the response curve @type instrument: string """ basedir = 'spectables/responses/' if instrument == 'hermes': basename = 'response_Feige66.fits' response = config.get_datafile(basedir, basename) wave, flux = fits.read_spectrum(response) return wave, flux
def search(ID, radius=1., filename=None): """ Retrieve datafiles from the Coralie catalogue. We search on coordinates, pulled from SIMBAD. If the star ID is not recognised, a string search is performed to match the 'targ name' field in the FITS headers. Only the s1d_A data are searched. @param ID: ID of the star, understandable by SIMBAD @type ID: str @param radius: search radius around the coordinates @type radius: 1 @param filename: write summary to outputfile if not None @type filename: str @return: record array with summary information on the observations, as well as their location (column 'filename') @rtype: numpy rec array """ data = ascii.read2recarray(config.get_datafile( os.path.join('catalogs', 'coralie'), 'CoralieFullDataOverview.tsv'), splitchar='\t') info = sesame.search(ID) if info: ra, dec = info['jradeg'], info['jdedeg'] keep = np.sqrt((data['ra'] - ra)**2 + (data['dec'] - dec)**2) < radius / 60. else: keep = [((re.compile(ID).search(objectn) is not None) and True or False) for objectn in data['object']] keep = np.array(keep) data = data[keep] logger.info('Found %d spectra' % (len(data))) if filename is not None: ascii.write_array(data, filename, auto_width=True, header=True) else: return data
def search(ID,radius=1.,filename=None): """ Retrieve datafiles from the Coralie catalogue. We search on coordinates, pulled from SIMBAD. If the star ID is not recognised, a string search is performed to match the 'targ name' field in the FITS headers. Only the s1d_A data are searched. @param ID: ID of the star, understandable by SIMBAD @type ID: str @param radius: search radius around the coordinates @type radius: 1 @param filename: write summary to outputfile if not None @type filename: str @return: record array with summary information on the observations, as well as their location (column 'filename') @rtype: numpy rec array """ data = ascii.read2recarray(config.get_datafile(os.path.join('catalogs','coralie'),'CoralieFullDataOverview.tsv'),splitchar='\t') info = sesame.search(ID) if info: ra,dec = info['jradeg'],info['jdedeg'] keep = np.sqrt((data['ra']-ra)**2 + (data['dec']-dec)**2) < radius/60. else: keep = [((re.compile(ID).search(objectn) is not None) and True or False) for objectn in data['object']] keep = np.array(keep) data = data[keep] logger.info('Found %d spectra'%(len(data))) if filename is not None: ascii.write_array(data,filename,auto_width=True,header=True) else: return data
def VALD(elem=None,xmin=3200.,xmax=4800.,outputdir=None): """ Request linelists from VALD for each ion seperately within a specific wavelength range. elem = an array of ions e.g. ['CI','OII'], xmin and xmax: wavelength range in which the spectral lines are searched, outputdir = output directory chosen by the user. If no elements are given, this function returns all of them. @param elem: list of ions @type elem: list of str """ if elem is None: files = sorted(config.glob('VALD_individual','VALD_*.lijnen')) elem = [os.path.splitext(os.path.basename(ff))[0].split('_')[1] for ff in files] all_lines = [] for i in range(len(elem)): print elem[i] filename = config.get_datafile('VALD_individual','VALD_' + elem[i] + '.lijnen') if not os.path.isfile(filename): logger.info('No data for element ' + str(elem[i])) return None newwav,newexc,newep,newgf = np.loadtxt(filename).T lines = np.rec.fromarrays([newwav,newexc,newep,newgf],names=['wavelength','ion','ep','gf']) keep = (xmin<=lines['wavelength']) & (lines['wavelength']<=xmax) if not hasattr(keep,'__iter__'): continue lines = lines[keep] if len(lines) and outputdir is not None: ascii.write_array(lines,outputdir + 'VALD_' + str(elem[i]) + '_' + str(xmin) + '_' + str(xmax) + '.dat',auto_width=True,header=True,formats=['%.3f','%.1f','%.3f','%.3f']) elif len(lines): all_lines.append(lines) else: logger.debug('No lines of ' + str(elem[i]) + ' in given wavelength range') return np.hstack(all_lines)
def get_lines(teff,logg,z=0,atoms=None,ions=None,wrange=(-inf,inf),\ blend=0.0): """ Retrieve line transitions and strengths for a specific stellar type Selection wavelength range in angstrom. Ions should be a list of ions to include. This can either be a string or a number A lines is considerd a blend if the closest line is closer than C{blend} angstrom. Returns record array with fields C{wavelength}, C{ion} and C{depth}. Example usage: Retrieve all Silicon lines between 4500 and 4600 for a B1V star. >>> data = get_lines(20000,4.0,atoms=['Si'],wrange=(4500,4600)) >>> p = pl.figure() >>> p = pl.vlines(data['wavelength'],1,1-data['depth']) See how the depth of the Halpha line varies wrt temperature: >>> teffs = range(5000,21000,1000) + range(22000,32000,2000) + range(30000,50000,50000) >>> depths = np.zeros((len(teffs),7)) >>> for i,teff in enumerate(teffs): ... data = get_lines(teff,5.0,ions=['HI'],wrange=(3800,7000)) ... depths[i] = data['depth'] >>> p = pl.figure();p = pl.title('Depth of Balmer lines (Halpha-Heta)') >>> p = pl.plot(teffs,1-depths,'o-') >>> p = pl.xlabel('Effective temperature');p = pl.grid() """ #-- get filepath filename = 'mask.%d.%02d.p%02d'%(int(teff),int(logg*10),int(z)) filename = config.get_datafile(stellar,filename) #-- read in the data and extract relevant columns data = ascii.read2recarray(filename,skip_lines=1,dtype=[('wavelength','f8'),('ion','f8'),('depth','f8'),('c3','f8'),('c4','f8'),('c5','f8')]) data = pl.mlab.rec_drop_fields(data,['c3','c4','c5']) data['wavelength'] *= 10. #-- remove blends if blend>0: blends_left = np.hstack([0,np.diff(data['wavelength'])]) blends_right= np.hstack([np.diff(data['wavelength']),1e10]) keep = (blends_left>blend) & (blends_right>blend) data = data[keep] #-- only keep those transitions within a certain wavelength range keep = (wrange[0]<=data['wavelength']) & (data['wavelength']<=wrange[1]) data = data[keep] #-- only keep those transitions that belong to certain ions or atoms if atoms is not None or ions is not None: keep = np.array(np.zeros(len(data)),bool) else: keep = np.array(np.ones(len(data)),bool) if atoms is not None: #-- convert all atoms to their number and select the appropriate ones atoms = [(isinstance(atom,str) and atomcode.index(atom.title()) or atom) for atom in atoms] for atom in atoms: keep = keep | (np.abs(data['ion']-atom)<0.5) if ions is not None: #-- convert all ions to their number and select the appropriate ones ions = [(isinstance(ion,str) and name2ioncode(ion) or ion) for ion in ions] for ion in ions: keep = keep | (np.abs(data['ion']-ion)<0.005) return data[keep]
def getP7Data(ID=None,code=None,include_nans=True): """ Extract P7 timeseries from the catalog. WARNING: only B{very} few target ID's can be resolved (HD,HIP,SAO and that's about it) WARNING: there could be nan's in the data somewhere. If you don't want nan's anywhere, set 'include_nans' to False. @param ID: target ID (limited!) @type ID: str @param code: target's GENEVA code (e.g. 100180642 for HD180642) @type code: int @return: record array containing times (HJD) and corresponding GENEVA mags, and a dictionary with header information (only source=P7) @rtype: np record array,dict """ if ID is not None: if not 'HD' in ID or not 'SAO' in ID or not 'HIC' in ID: info = sesame.search(ID) print info if 'alias' in info: for alias in info['alias']: if 'HD' in alias: ID = alias break if 'SAO' in alias: ID = alias break if 'HIC' in alias: ID = alias break # this should resolve the GENEVA name code = _geneva_name_resolver(ID=ID) catfile = config.get_datafile('catalogs/p7','p7photometry.fits') ff = pf.open(catfile) valid = ff[1].data.field('CODE')==code hjd = ff[1].data.field('HJD')[valid] U = ff[1].data.field('U')[valid] B = ff[1].data.field('B')[valid] B1 = ff[1].data.field('B1')[valid] B2 = ff[1].data.field('B2')[valid] V = ff[1].data.field('V')[valid] V1 = ff[1].data.field('V1')[valid] G = ff[1].data.field('G')[valid] ff.close() data = np.rec.fromarrays([hjd,U,B,B1,B2,V,V1,G],names='HJD,U,B,B1,B2,V,V1,G') logger.info('Retrieved %d photometric points from P7'%(len(data))) if not include_nans: nans = np.isnan(data['HJD']) for name in data.dtype.names: nans = nans | np.isnan(data[name]) data = data[-nans] logger.info('Keeping %d photometric points without "NaN" from P7'%(len(data))) return data,{'source':'P7'}
def getP7Data(ID=None, code=None, include_nans=True): """ Extract P7 timeseries from the catalog. WARNING: only B{very} few target ID's can be resolved (HD,HIP,SAO and that's about it) WARNING: there could be nan's in the data somewhere. If you don't want nan's anywhere, set 'include_nans' to False. @param ID: target ID (limited!) @type ID: str @param code: target's GENEVA code (e.g. 100180642 for HD180642) @type code: int @return: record array containing times (HJD) and corresponding GENEVA mags, and a dictionary with header information (only source=P7) @rtype: np record array,dict """ if ID is not None: if not 'HD' in ID or not 'SAO' in ID or not 'HIC' in ID: info = sesame.search(ID) print(info) if 'alias' in info: for alias in info['alias']: if 'HD' in alias: ID = alias break if 'SAO' in alias: ID = alias break if 'HIC' in alias: ID = alias break # this should resolve the GENEVA name code = _geneva_name_resolver(ID=ID) catfile = config.get_datafile('catalogs/p7', 'p7photometry.fits') ff = pf.open(catfile) valid = ff[1].data.field('CODE') == code hjd = ff[1].data.field('HJD')[valid] U = ff[1].data.field('U')[valid] B = ff[1].data.field('B')[valid] B1 = ff[1].data.field('B1')[valid] B2 = ff[1].data.field('B2')[valid] V = ff[1].data.field('V')[valid] V1 = ff[1].data.field('V1')[valid] G = ff[1].data.field('G')[valid] ff.close() data = np.rec.fromarrays([hjd, U, B, B1, B2, V, V1, G], names='HJD,U,B,B1,B2,V,V1,G') logger.info('Retrieved %d photometric points from P7' % (len(data))) if not include_nans: nans = np.isnan(data['HJD']) for name in data.dtype.names: nans = nans | np.isnan(data[name]) data = data[-nans] logger.info('Keeping %d photometric points without "NaN" from P7' % (len(data))) return data, {'source': 'P7'}
def get_file(integrated=False, **kwargs): """ Retrieve the filename containing the specified SED grid. The keyword arguments are specific to the kind of grid you're using. Basic keywords are 'grid' for the name of the grid, and 'z' for metallicity. For other keywords, see the source code. Available grids and example keywords: - grid='kurucz93': * metallicity (z): m01 is -0.1 log metal abundance relative to solar (solar abundances from Anders and Grevesse 1989) * metallicity (z): p01 is +0.1 log metal abundance relative to solar (solar abundances from Anders and Grevesse 1989) * alpha enhancement (alpha): True means alpha enhanced (+0.4) * turbulent velocity (vturb): vturb in km/s * nover= True means no overshoot * odfnew=True means no overshoot but with better opacities and abundances @param integrated: choose integrated version of the grid @type integrated: boolean @keyword grid: gridname (default Kurucz) @type grid: str @return: gridfile @rtype: str """ # -- possibly you give a filename grid = kwargs.get("grid", defaults["grid"]) if os.path.isfile(grid): return grid # -- general z = kwargs.get("z", defaults["z"]) # -- only for Kurucz vturb = int(kwargs.get("vturb", defaults["vturb"])) odfnew = kwargs.get("odfnew", defaults["odfnew"]) alpha = kwargs.get("alpha", defaults["alpha"]) nover = kwargs.get("nover", defaults["nover"]) # -- figure out what grid to use if grid == "kurucz": if not isinstance(z, str): z = "%.1f" % (z) if not isinstance(vturb, str): vturb = "%d" % (vturb) if not alpha and not nover and not odfnew: basename = "kurucz93_z%s_k%s_ld.fits" % (z, vturb) elif alpha and odfnew: basename = "kurucz93_z%s_ak%sodfnew_ld.fits" % (z, vturb) elif odfnew: basename = "kurucz93_z%s_k%sodfnew_ld.fits" % (z, vturb) elif nover: basename = "kurucz93_z%s_k%snover_ld.fits" % (z, vturb) else: basename = grid # -- retrieve the absolute path of the file and check if it exists: if not "*" in basename: if integrated: grid = config.get_datafile(basedir, "i" + basename) else: grid = config.get_datafile(basedir, basename) # -- we could also ask for a list of files, when wildcards are given: else: grid = config.glob(basedir, "i" + basename) if integrated: grid = config.glob(basedir, "i" + basename) else: grid = config.glob(basedir, basename) logger.debug("Selected %s" % (grid)) return grid
def get_lines(teff,logg,z=0,atoms=None,ions=None,wrange=(-inf,inf),\ blend=0.0): """ Retrieve line transitions and strengths for a specific stellar type Selection wavelength range in angstrom. Ions should be a list of ions to include. This can either be a string or a number A lines is considerd a blend if the closest line is closer than C{blend} angstrom. Returns record array with fields C{wavelength}, C{ion} and C{depth}. Example usage: Retrieve all Silicon lines between 4500 and 4600 for a B1V star. >>> data = get_lines(20000,4.0,atoms=['Si'],wrange=(4500,4600)) >>> p = pl.figure() >>> p = pl.vlines(data['wavelength'],1,1-data['depth']) See how the depth of the Halpha line varies wrt temperature: >>> teffs = range(5000,21000,1000) + range(22000,32000,2000) + range(30000,50000,50000) >>> depths = np.zeros((len(teffs),7)) >>> for i,teff in enumerate(teffs): ... data = get_lines(teff,5.0,ions=['HI'],wrange=(3800,7000)) ... depths[i] = data['depth'] >>> p = pl.figure();p = pl.title('Depth of Balmer lines (Halpha-Heta)') >>> p = pl.plot(teffs,1-depths,'o-') >>> p = pl.xlabel('Effective temperature');p = pl.grid() """ #-- get filepath filename = 'mask.%d.%02d.p%02d' % (int(teff), int(logg * 10), int(z)) filename = config.get_datafile(stellar, filename) #-- read in the data and extract relevant columns data = ascii.read2recarray(filename, skip_lines=1, dtype=[('wavelength', 'f8'), ('ion', 'f8'), ('depth', 'f8'), ('c3', 'f8'), ('c4', 'f8'), ('c5', 'f8')]) data = pl.mlab.rec_drop_fields(data, ['c3', 'c4', 'c5']) data['wavelength'] *= 10. #-- remove blends if blend > 0: blends_left = np.hstack([0, np.diff(data['wavelength'])]) blends_right = np.hstack([np.diff(data['wavelength']), 1e10]) keep = (blends_left > blend) & (blends_right > blend) data = data[keep] #-- only keep those transitions within a certain wavelength range keep = (wrange[0] <= data['wavelength']) & (data['wavelength'] <= wrange[1]) data = data[keep] #-- only keep those transitions that belong to certain ions or atoms if atoms is not None or ions is not None: keep = np.array(np.zeros(len(data)), bool) else: keep = np.array(np.ones(len(data)), bool) if atoms is not None: #-- convert all atoms to their number and select the appropriate ones atoms = [(isinstance(atom, str) and atomcode.index(atom.title()) or atom) for atom in atoms] for atom in atoms: keep = keep | (np.abs(data['ion'] - atom) < 0.5) if ions is not None: #-- convert all ions to their number and select the appropriate ones ions = [(isinstance(ion, str) and name2ioncode(ion) or ion) for ion in ions] for ion in ions: keep = keep | (np.abs(data['ion'] - ion) < 0.005) return data[keep]
def get_file(integrated=False, **kwargs): """ Retrieve the filename containing the specified SED grid. The keyword arguments are specific to the kind of grid you're using. Basic keywords are 'grid' for the name of the grid, and 'z' for metallicity. For other keywords, see the source code. Available grids and example keywords: - grid='kurucz93': * metallicity (z): m01 is -0.1 log metal abundance relative to solar (solar abundances from Anders and Grevesse 1989) * metallicity (z): p01 is +0.1 log metal abundance relative to solar (solar abundances from Anders and Grevesse 1989) * alpha enhancement (alpha): True means alpha enhanced (+0.4) * turbulent velocity (vturb): vturb in km/s * nover= True means no overshoot * odfnew=True means no overshoot but with better opacities and abundances @param integrated: choose integrated version of the grid @type integrated: boolean @keyword grid: gridname (default Kurucz) @type grid: str @return: gridfile @rtype: str """ #-- possibly you give a filename grid = kwargs.get('grid', defaults['grid']) if os.path.isfile(grid): return grid #-- general z = kwargs.get('z', defaults['z']) #-- only for Kurucz vturb = int(kwargs.get('vturb', defaults['vturb'])) odfnew = kwargs.get('odfnew', defaults['odfnew']) alpha = kwargs.get('alpha', defaults['alpha']) nover = kwargs.get('nover', defaults['nover']) #-- figure out what grid to use if grid == 'kurucz': if not isinstance(z, str): z = '%.1f' % (z) if not isinstance(vturb, str): vturb = '%d' % (vturb) if not alpha and not nover and not odfnew: basename = 'kurucz93_z%s_k%s_ld.fits' % (z, vturb) elif alpha and odfnew: basename = 'kurucz93_z%s_ak%sodfnew_ld.fits' % (z, vturb) elif odfnew: basename = 'kurucz93_z%s_k%sodfnew_ld.fits' % (z, vturb) elif nover: basename = 'kurucz93_z%s_k%snover_ld.fits' % (z, vturb) else: basename = grid #-- retrieve the absolute path of the file and check if it exists: if not '*' in basename: if integrated: grid = config.get_datafile(basedir, 'i' + basename) else: grid = config.get_datafile(basedir, basename) #-- we could also ask for a list of files, when wildcards are given: else: grid = config.glob(basedir, 'i' + basename) if integrated: grid = config.glob(basedir, 'i' + basename) else: grid = config.glob(basedir, basename) logger.debug('Selected %s' % (grid)) return grid
def get_file(**kwargs): """ Retrieve the filename containing the specified SED grid. Available grids and example keywords: - grid='fastwind': no options - grid='cmfgen': no options - grid='marcs': options c, atm (p or s) - grid='ostar2002': options z,v - grid='bstar2006a': options z,v - grid='bstar2006b': options z,v - grid='bstar2006': options z,v,a - grid='atlas': options z - grid='heberb': no options - grid='hebersdb': no options - grid='tmapsdb': no options Details for grid 'bstar2006': - metallicity in Z/Z0 with Z0 solar. z=0,0.001,0.01,0.033,0.1,0.2,0.5,1.,2 - microturbulent velocity: v=2 or v=10 km/s - abundance: a='' or a='CN'. In the latter, the Helium abundance is increased to He/H=0.2, the nitrogen abundance is increased by a factor of 5, and the carbon abundance is halved (CNO cycle processed material brought to the stellar surface) Details for grid 'heberb': LTE Grid computed for B-type stars by Uli Heber, reff: Heber et al. 2000 Details for grid 'hebersdb': LTE Grid computed for sdB stars by Uli Heber, reff: Heber et al. 2000 Details for grid 'tmapsdb': NLTE Grid computed for sdB stars using the TMAP (TUEBINGEN NLTE MODEL ATMOSPHERE PACKAGE) code. reff: Werner K., et al. 2003 and Rauch T., Deetjen J.L. 2003 @param grid: gridname, or path to grid. @type grid: string """ #-- possibly you give a filename grid = kwargs.get('grid', defaults['grid']) #.lower() if os.path.isfile(grid): return grid #-- general z = kwargs.get('z', defaults['z']) #-- only for Kurucz vturb = int(kwargs.get('vturb', defaults['vturb'])) #-- only for Marcs t = kwargs.get('t', defaults['t']) a = kwargs.get('a', defaults['a']) c = kwargs.get('c', defaults['c']) atm = kwargs.get('atm', defaults['atm']) #-- only for TLUSTY band = kwargs.get('band', defaults['band']) #-- figure out what grid to use if grid == 'cmfgen': basename = 'cmfgen_spectra.fits' elif grid == 'marcs': basename = 'marcsp_%sz%.1ft%.1f_a%.2f_c%.2f_spectra.fits' % (atm, z, t, a, c) elif grid == 'ostar2002': basename = 'OSTAR2002_z%.3fv%d_%s_spectra.fits' % (z, vturb, band) elif grid == 'bstar2006': basename = 'BSTAR2006_z%.3fv%d_%s_spectra.fits' % (z, vturb, band) elif grid == 'atlas': basename = 'ATLASp_z%.1ft%.1f_a%.2f_spectra.fits' % (z, t, a) elif grid == 'heberb': basename = 'Heber2000_B_h909.fits' elif grid == 'hebersdb': basename = 'Heber2000_sdB_h909.fits' elif grid == 'tmapsdb': basename = 'TMAP2011_sdB.fits' else: raise ValueError("grid %s does not exist" % (grid)) #-- retrieve the absolute path of the file and check if it exists: grid = config.get_datafile(basedir, basename) return grid
def make_data_overview(): """ Summarize all Hermes data in a file for easy data retrieval. The file is located in one of date data directories (see C{config.py}), in subdirectories C{catalogs/hermes/HermesFullDataOverview.tsv}. If it doesn't exist, it will be created. It contains the following columns, which are extracted from the Hermes FITS headers (except C{filename}: 1. UNSEQ 2. PROG_ID 3. OBSMODE 4. BVCOR 5. OBSERVER 6. OBJECT 7. RA 8. DEC 9. BJD 10. EXPTIME 11. PMTOTAL 12. DATE-AVG 13. OBJECT 14. airmass 15. filename This file can most easily be read with the L{ivs.inout.ascii} module and the command: >>> hermes_file = config.get_datafile(os.path.join('catalogs','hermes'),'HermesFullDataOverview.tsv') >>> data = ascii.read2recarray(hermes_file,splitchar='\\t') """ logger.info('Collecting files...') #-- all hermes data directories dirs = sorted(glob.glob(os.path.join(config.ivs_dirs['hermes'],'20??????'))) dirs = [idir for idir in dirs if os.path.isdir(idir)] obj_files = [] #-- collect in those directories the raw and relevant reduced files for idir in dirs: obj_files += sorted(glob.glob(os.path.join(idir,'raw','*.fits'))) #obj_files += sorted(glob.glob(os.path.join(idir,'reduced','*OBJ*wavelength_merged.fits'))) #obj_files += sorted(glob.glob(os.path.join(idir,'reduced','*OBJ*wavelength_merged_c.fits'))) #obj_files += sorted(glob.glob(os.path.join(idir,'reduced','*OBJ*log_merged.fits'))) #obj_files += sorted(glob.glob(os.path.join(idir,'reduced','*OBJ*log_merged_c.fits'))) #-- keep track of what is already in the file, if it exists: try: overview_file = config.get_datafile('catalogs/hermes','HermesFullDataOverview.tsv') #overview_file = config.get_datafile(os.path.join('catalogs','hermes'),'HermesFullDataOverview.tsv') overview_data = ascii.read2recarray(overview_file,splitchar='\t') outfile = open(overview_file,'a') logger.info('Found %d FITS files: appending to overview file %s'%(len(obj_files),overview_file)) # if not, begin a new file except IOError: overview_file = 'HermesFullDataOverview.tsv' outfile = open(overview_file,'w') outfile.write('#unseq prog_id obsmode bvcor observer object ra dec bjd exptime pmtotal date-avg airmass filename\n') outfile.write('#i i a20 >f8 a50 a50 >f8 >f8 >f8 >f8 >f8 a30 >f8 a200\n') overview_data = {'filename':[]} logger.info('Found %d FITS files: starting new overview file %s'%(len(obj_files),overview_file)) #-- and summarize the contents in a tab separated file (some columns contain spaces) existing_files = np.sort(overview_data['filename']) for i,obj_file in enumerate(obj_files): sys.stdout.write(chr(27)+'[s') # save cursor sys.stdout.write(chr(27)+'[2K') # remove line sys.stdout.write('Scanning %5d / %5d FITS files'%(i+1,len(obj_files))) sys.stdout.flush() # flush to screen #-- maybe this file is already processed: forget about it then index = existing_files.searchsorted(obj_file) if index<len(existing_files) and existing_files[index]==obj_file: sys.stdout.write(chr(27)+'[u') # reset cursor continue #-- keep track of: UNSEQ, PROG_ID, OBSMODE, BVCOR, OBSERVER, # OBJECT, RA, DEC, BJD, EXPTIME, DATE-AVG, PMTOTAL, # airmass and filename (not part of fitsheader) contents = dict(unseq=-1,prog_id=-1,obsmode='nan',bvcor=np.nan,observer='nan', object='nan',ra=np.nan,dec=np.nan, bjd=np.nan,exptime=np.nan,pmtotal=np.nan,airmass=np.nan, filename=os.path.realpath(obj_file)) contents['date-avg'] = 'nan' header = pf.getheader(obj_file) for key in contents: if key in header and key in ['unseq','prog_id']: try: contents[key] = int(header[key]) except: pass elif key in header and key in ['obsmode','observer','object','date-avg']: contents[key] = str(header[key]) elif key in header and key in ['ra','dec','exptime','pmtotal','bjd','bvcor']: contents[key] = float(header[key]) elif key=='airmass' and 'telalt' in header: if float(header['telalt'])<90: try: contents[key] = airmass.airmass(90-float(header['telalt'])) except ValueError: pass outfile.write('%(unseq)d\t%(prog_id)d\t%(obsmode)s\t%(bvcor)f\t%(observer)s\t%(object)s\t%(ra)f\t%(dec)f\t%(bjd)f\t%(exptime)f\t%(pmtotal)f\t%(date-avg)s\t%(airmass)f\t%(filename)s\n'%contents) outfile.flush() sys.stdout.write(chr(27)+'[u') # reset cursor outfile.close() return overview_file
def get_file(**kwargs): """ Retrieve the filename containing the specified SED grid. Available grids and example keywords: - grid='fastwind': no options - grid='cmfgen': no options - grid='marcs': options c, atm (p or s) - grid='ostar2002': options z,v - grid='bstar2006a': options z,v - grid='bstar2006b': options z,v - grid='bstar2006': options z,v,a - grid='atlas': options z - grid='heberb': no options - grid='hebersdb': no options - grid='tmapsdb': no options Details for grid 'bstar2006': - metallicity in Z/Z0 with Z0 solar. z=0,0.001,0.01,0.033,0.1,0.2,0.5,1.,2 - microturbulent velocity: v=2 or v=10 km/s - abundance: a='' or a='CN'. In the latter, the Helium abundance is increased to He/H=0.2, the nitrogen abundance is increased by a factor of 5, and the carbon abundance is halved (CNO cycle processed material brought to the stellar surface) Details for grid 'heberb': LTE Grid computed for B-type stars by Uli Heber, reff: Heber et al. 2000 Details for grid 'hebersdb': LTE Grid computed for sdB stars by Uli Heber, reff: Heber et al. 2000 Details for grid 'tmapsdb': NLTE Grid computed for sdB stars using the TMAP (TUEBINGEN NLTE MODEL ATMOSPHERE PACKAGE) code. reff: Werner K., et al. 2003 and Rauch T., Deetjen J.L. 2003 @param grid: gridname, or path to grid. @type grid: string """ #-- possibly you give a filename grid = kwargs.get('grid',defaults['grid'])#.lower() if os.path.isfile(grid): return grid #-- general z = kwargs.get('z',defaults['z']) #-- only for Kurucz vturb = int(kwargs.get('vturb',defaults['vturb'])) #-- only for Marcs t = kwargs.get('t',defaults['t']) a = kwargs.get('a',defaults['a']) c = kwargs.get('c',defaults['c']) atm = kwargs.get('atm',defaults['atm']) #-- only for TLUSTY band = kwargs.get('band',defaults['band']) #-- figure out what grid to use if grid=='cmfgen': basename = 'cmfgen_spectra.fits' elif grid=='marcs': basename = 'marcsp_%sz%.1ft%.1f_a%.2f_c%.2f_spectra.fits'%(atm,z,t,a,c) elif grid=='ostar2002': basename = 'OSTAR2002_z%.3fv%d_%s_spectra.fits'%(z,vturb,band) elif grid=='bstar2006': basename = 'BSTAR2006_z%.3fv%d_%s_spectra.fits'%(z,vturb,band) elif grid=='atlas': basename = 'ATLASp_z%.1ft%.1f_a%.2f_spectra.fits'%(z,t,a) elif grid=='heberb': basename = 'Heber2000_B_h909.fits' elif grid=='hebersdb': basename = 'Heber2000_sdB_h909.fits' elif grid=='tmapsdb': basename = 'TMAP2011_sdB.fits' else: raise ValueError, "grid %s does not exist"%(grid) #-- retrieve the absolute path of the file and check if it exists: grid = config.get_datafile(basedir,basename) return grid