Example #1
0
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
Example #4
0
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)
Example #5
0
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
Example #6
0
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 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
Example #8
0
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
Example #10
0
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
Example #11
0
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]
Example #15
0
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
Example #18
0
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]
Example #19
0
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
Example #23
0
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