def astroNN(dr=None): """ NAME: astroNN PURPOSE: download the astroNN file INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2018-10-20 - Written - Bovy (UofT) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.astroNNPath(dr=dr) if os.path.exists(filePath): return None # Create the file path if int(dr) == 14: downloadPath= 'https://github.com/henrysky/astroNN_spectra_paper_figures/raw/master/astroNN_apogee_dr14_catalog.fits' else: downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr,verbose=True) return None
def apogeePlate(dr=None): """ NAME: apogeePlate PURPOSE: download the apogeePlate file INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2015-12-27 - Written - Bovy (UofT) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.apogeePlatePath(dr=dr) if os.path.exists(filePath): return None # Create the file path if int(dr) < 16: downloadPath= os.path.join(path._APOGEE_DATA,'dr%s' % dr, 'apogee','target',os.path.basename(filePath))\ .replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) elif int(dr) >= 16: #change of location/format after DR16 downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr) return None
def all_apStar(dr=None): """ NAME: all_apStar PURPOSE: Convenience function to download all apStar files for a given DR INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2019-12-23 - Written - Bovy (UofT) """ from . import read as apread if dr is None: dr= path._default_dr() alldata= apread.allStar(raw=True) for ii in range(len(alldata)): try: _= apread.apStar(alldata['LOCATION_ID'][ii] if int(dr) < 14 else alldata['FIELD'][ii], alldata['APOGEE_ID'][ii], telescope=alldata['TELESCOPE'][ii],dr=dr) except: print("Failed to download location {}, apogee_id {}, telescope {}"\ .format(alldata['LOCATION_ID'][ii] if int(dr) < 14 else alldata['FIELD'][ii], alldata['APOGEE_ID'][ii], alldata['TELESCOPE'][ii])) return None
def apogeeObject(field_name, dr=None): """ NAME: apogeeObject PURPOSE: download an apogeeObject file INPUT: field_name - name of the field dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2015-12-27 - Written - Bovy (UofT) """ if dr is None: dr = path._default_dr() # First make sure the file doesn't exist filePath = path.apogeeObjectPath(field_name, dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath= os.path.join(path._APOGEE_DATA,'dr%s' % dr, 'apogee','target','apogeeObject', os.path.basename(filePath))\ .replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath, filePath, dr) return None
def aspcapStar(loc_id,apogee_id,dr=None): """ NAME: aspcapStar PURPOSE: download an aspcapStar file INPUT: loc_id - location ID apogee_id - APOGEE ID of the star dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2014-11-25 - Written - Bovy (IAS) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.aspcapStarPath(loc_id,apogee_id,dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, 'dr%s' % dr), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr) return None
def allVisit(dr=None): """ NAME: allVisit PURPOSE: download the allVisit file INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2014-11-26 - Written - Bovy (IAS) 2015-08-17 - Adjusted for new path (mv old to new) - Bovy (UofT) """ if dr is None: dr = path._default_dr() # First make sure the file doesn't exist filePath = path.allVisitPath(dr=dr) if os.path.exists(filePath): return None # Check whether we can find it in its old place oldFilePath = path.allVisitPath(dr=dr, _old=True) if os.path.exists(oldFilePath): # mv to new place try: os.makedirs(os.path.dirname(filePath)) except OSError: pass shutil.move(oldFilePath, filePath) return None # Create the file path downloadPath = filePath.replace( os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath, filePath, dr, verbose=True) return None
def allVisit(dr=None): """ NAME: allVisit PURPOSE: download the allVisit file INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2014-11-26 - Written - Bovy (IAS) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.allVisitPath(dr=dr) if os.path.exists(filePath): return None # Create the file path, hacked from aspcapStar path aspPath= path.aspcapStarPath(4140,'dum',dr=dr) downloadPath= aspPath.replace(os.path.join(path._APOGEE_DATA, 'dr%s' % dr), _base_url(dr=dr)) head, tail= os.path.split(downloadPath) #strips off filename downloadPath, tail= os.path.split(head) #strips off location_id downloadPath= os.path.join(downloadPath,os.path.basename(filePath)) _download_file(downloadPath,filePath,dr,verbose=True) return None
def apStar(loc_id,apogee_id,dr=None): """ NAME: apStar PURPOSE: download an apStar file INPUT: loc_id - location ID apogee_id - APOGEE ID of the star dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2015-01-13 - Written - Bovy (IAS) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.apStarPath(loc_id,apogee_id,dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr) return None
def apogeeObject(field_name,dr=None): """ NAME: apogeeObject PURPOSE: download an apogeeObject file INPUT: field_name - name of the field dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2015-12-27 - Written - Bovy (UofT) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.apogeeObjectPath(field_name,dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath= os.path.join(path._APOGEE_DATA,'dr%s' % dr, 'apogee','target','apogeeObject', os.path.basename(filePath))\ .replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr) return None
def allVisit(dr=None): """ NAME: allVisit PURPOSE: download the allVisit file INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2014-11-26 - Written - Bovy (IAS) 2015-08-17 - Adjusted for new path (mv old to new) - Bovy (UofT) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.allVisitPath(dr=dr) if os.path.exists(filePath): return None # Check whether we can find it in its old place oldFilePath= path.allVisitPath(dr=dr,_old=True) if os.path.exists(oldFilePath): # mv to new place try: os.makedirs(os.path.dirname(filePath)) except OSError: pass shutil.move(oldFilePath,filePath) return None # Create the file path downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr,verbose=True) return None
def apStar(loc_id,apogee_id,telescope='apo25m',dr=None): """ NAME: apStar PURPOSE: download an apStar file INPUT: loc_id - location ID apogee_id - APOGEE ID of the star telescope= telescope used ('apo25m' [default], 'apo1m', 'lco25m') dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2015-01-13 - Written - Bovy (IAS) 2018-01-22 - Edited for new post-DR14 path structure - Bovy (UofT) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.apStarPath(loc_id,apogee_id,dr=dr,telescope=telescope) if os.path.exists(filePath): return None # Create the file path downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr) return None
def apVisit(plateid, mjd, fiberid, telescope='apo25m', dr=None): """ NAME: apVisit PURPOSE: download a single apVisit file INPUT: plateid = 4-digit plate ID mjd = 5-digit MJD fiberid = 3-digit fiber ID telescope= ('apo25m') Telescope at which this plate has been observed ('apo25m' for standard APOGEE-N, 'apo1m' for the 1m telescope) dr = return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2016-11 - Meredith Rawls 2019-01-28 - Added telescope keyword, clarified that it's plateid that's needed - Bovy (UofT) TODO: automatically find all apVisit files for a given apogee ID and download them """ if dr is None: dr = path._default_dr() # First make sure the file doesn't exist filePath = path.apVisitPath(plateid, mjd, fiberid, telescope=telescope,dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath = filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath, filePath, dr) return None
def ferreModelLibrary(lib='GK',pca=True,sixd=True,unf=False,dr=None, convertToBin=True,spider=False): """ NAME: ferreModelLibrary PURPOSE: download a FERRE model library INPUT: lib= ('GK') spectral library dr= return the path corresponding to this data release pca= (True) if True, download the PCA compressed library sixd= (True) if True, download the 6D library (w/o vmicro) unf= (False) if True, download the binary library (otherwise ascii) convertToBin= (True) if True and not unf, convert the ascii file to binary using ferre's ascii2bin (which has to be on the path) spider= (False) if True, run wget as a spider (doesn't download) OUTPUT: (none; just downloads; also downloads the corresponding .hdr) HISTORY: 2015-01-21 - Written - Bovy (IAS) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.ferreModelLibraryPath(lib=lib,dr=dr,pca=pca, sixd=sixd,unf=unf) if not os.path.exists(filePath): # Create the file path downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr,verbose=True,spider=spider) if convertToBin and not spider: sys.stdout.write('\r'+"Converting ascii model library to binary (can take a few minutes) ...\r") sys.stdout.flush() try: p= subprocess.Popen(['ascii2bin'],stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, cwd=os.path.dirname(filePath)) p.stdin.write((os.path.basename(filePath)+'\n')\ .encode('utf-8')) p.stdin.write(b'unf\n') stdout, stderr= p.communicate() except subprocess.CalledProcessError: print("Conversion of %s to binary failed ..." % (os.path.basename(filePath))) sys.stdout.write('\r'+_ERASESTR+'\r') sys.stdout.flush() # Also download the header if unf: headerFilePath= filePath.replace('.unf','.hdr') else: headerFilePath= filePath.replace('.dat','.hdr') if os.path.exists(headerFilePath): return None headerDownloadPath= headerFilePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(headerDownloadPath,headerFilePath,dr,verbose=True, spider=spider) return None
def _load_precomp(dr=None,fiber='combo',sparse=True): """Load a precomputed LSF""" if dr is None: dr= appath._default_dr() fileDir= os.path.dirname(appath.apLSFPath('a',dr=dr)) filePath= os.path.join(fileDir,'apogee-lsf-dr%s-%s.fits' % (dr,fiber)) # Download the file if necessary if not os.path.exists(filePath): dlink= \ filePath.replace(fileDir,'https://zenodo.org/record/16147/files') _download_file(dlink,filePath,dr) x= numpy.linspace(-7.,7.,43) elsf= fitsio.read(filePath) if sparse: return (x,sparsify(elsf)) else: return (x,elsf)
def path(elem,dr=None): """ NAME: path PURPOSE: return the path of a window file INPUT: elem - element dr= return the path corresponding to this data release OUTPUT: path string HISTORY: 2015-02-27 - Written - Bovy (IAS) """ if dr is None: dr= _default_dr() return os.path.join(os.path.dirname(os.path.realpath(__file__)), 'filter/%s/%s.filt' \ % (_dr_string(dr), (elem.lower().capitalize())))
def path(elem, dr=None): """ NAME: path PURPOSE: return the path of a window file INPUT: elem - element dr= return the path corresponding to this data release OUTPUT: path string HISTORY: 2015-02-27 - Written - Bovy (IAS) """ if dr is None: dr = _default_dr() return os.path.join(os.path.dirname(os.path.realpath(__file__)), 'filter/%s/%s.filt' \ % (_dr_string(dr), (elem.lower().capitalize())))
def _load_precomp(dr=None,fiber='combo',sparse=True): """Load a precomputed LSF""" if dr is None: dr= appath._default_dr() if dr is 'current': warnings.warn("Preloaded LSFs for current DR not yet available, falling back on DR12 files") dr= '12' fileDir= os.path.dirname(appath.apLSFPath('a',dr=dr)) filePath= os.path.join(fileDir,'apogee-lsf-dr%s-%s.fits' % (dr,fiber)) # Download the file if necessary if not os.path.exists(filePath): dlink= \ filePath.replace(fileDir,'https://zenodo.org/record/16147/files') _download_file(dlink,filePath,dr) x= numpy.linspace(-7.,7.,43) elsf= fitsio.read(filePath) if sparse: return (x,sparsify(elsf)) else: return (x,elsf)
def astroNNAges(dr=None): """ NAME: astroNNAges PURPOSE: download the astroNN ages file INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2018-02-16 - Written - Bovy (UofT) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.astroNNAgesPath(dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath= 'http://www.astro.ljmu.ac.uk/~astjmack/APOGEEGaiaAges/'\ 'astroNNBayes_ages_goodDR14.fits' _download_file(downloadPath,filePath,dr,verbose=True) return None
def astroNNDistances(dr=None): """ NAME: astroNNDistances PURPOSE: download the astroNN distances file INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2018-02-15 - Written - Bovy (UofT) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.astroNNDistancesPath(dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath= 'https://github.com/henrysky/astroNN_gaia_dr2_paper/raw/'\ 'master/apogee_dr14_nn_dist.fits' _download_file(downloadPath,filePath,dr,verbose=True) return None
def rcsample(dr=None): """ NAME: rcsample PURPOSE: download the rcsample file INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2014-11-26 - Written - Bovy (IAS) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.allVisitPath(dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath=\ os.path.join(_base_url(dr=dr,rc=True), 'apogee/vac/apogee-rc/cat/apogee-rc-DR%s.fits' % dr) _download_file(downloadPath,filePath,dr) return None
def apLSF(chip, dr=None): """ NAME: apLSF PURPOSE: download an apLSF file INPUT: chip - chip 'a', 'b', or 'c' dr= return the path corresponding to this data release OUTPUT: (none; just downloads) HISTORY: 2015-03-12 - Written - Bovy (IAS) """ if dr is None: dr = path._default_dr() # First make sure the file doesn't exist filePath = path.apLSFPath(chip, dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath = filePath.replace( os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath, filePath, dr, verbose=True) return None
def rcsample(dr=None): """ NAME: rcsample PURPOSE: download the rcsample file INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2014-11-26 - Written - Bovy (IAS) """ if dr is None: dr = path._default_dr() # First make sure the file doesn't exist filePath = path.rcsamplePath(dr=dr) if os.path.exists(filePath): return None # Check whether we can find it in its old place oldFilePath = path.rcsamplePath(dr=dr, _old=True) if os.path.exists(oldFilePath): # mv to new place try: os.makedirs(os.path.dirname(filePath)) except OSError: pass shutil.move(oldFilePath, filePath) return None # Create the file path if dr == '11': # special case, bc in DR12 SAS downloadPath = filePath.replace( os.path.join(path._APOGEE_DATA, _dr_string('12')), _base_url(dr='12')) else: downloadPath = filePath.replace( os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath, filePath, dr, verbose=False) return None
def rcsample(dr=None): """ NAME: rcsample PURPOSE: download the rcsample file INPUT: dr= return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2014-11-26 - Written - Bovy (IAS) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.rcsamplePath(dr=dr) if os.path.exists(filePath): return None # Check whether we can find it in its old place oldFilePath= path.rcsamplePath(dr=dr,_old=True) if os.path.exists(oldFilePath): # mv to new place try: os.makedirs(os.path.dirname(filePath)) except OSError: pass shutil.move(oldFilePath,filePath) return None # Create the file path if dr == '11': # special case, bc in DR12 SAS downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string('12')), _base_url(dr='12')) else: downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr,verbose=False) return None
def apLSF(chip,dr=None): """ NAME: apLSF PURPOSE: download an apLSF file INPUT: chip - chip 'a', 'b', or 'c' dr= return the path corresponding to this data release OUTPUT: (none; just downloads) HISTORY: 2015-03-12 - Written - Bovy (IAS) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.apLSFPath(chip,dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr,verbose=True) return None
def apVisit(loc_id, mjd, fiberid, dr=None): """ NAME: apVisit PURPOSE: download a single apVisit file INPUT: loc_id = 4-digit location ID (field for 1m targets) mjd = 5-digit MJD fiberid = 3-digit fiber ID dr = return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2016-11 - Meredith Rawls TODO: automatically find all apVisit files for a given apogee ID and download them """ if dr is None: dr = path._default_dr() # First make sure the file doesn't exist filePath = path.apVisitPath(loc_id, mjd, fiberid, dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath = filePath.replace( os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath, filePath, dr) return None
def apVisit(loc_id, mjd, fiberid, dr=None): """ NAME: apVisit PURPOSE: download a single apVisit file INPUT: loc_id = 4-digit location ID (field for 1m targets) mjd = 5-digit MJD fiberid = 3-digit fiber ID dr = return the path corresponding to this data release (general default) OUTPUT: (none; just downloads) HISTORY: 2016-11 - Meredith Rawls TODO: automatically find all apVisit files for a given apogee ID and download them """ if dr is None: dr = path._default_dr() # First make sure the file doesn't exist filePath = path.apVisitPath(loc_id, mjd, fiberid, dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath = filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath, filePath, dr) return None
2018-02-05 - Updated to account for changing detector ranges - Price-Jones (UofT) """ filePath= path.modelSpecPath(lib=lib,teff=teff,logg=logg,metals=metals, cfe=cfe,nfe=nfe,afe=afe,vmicro=vmicro,dr=dr) if not os.path.exists(filePath): download.modelSpec(lib=lib,teff=teff,logg=logg,metals=metals, cfe=cfe,nfe=nfe,afe=afe,vmicro=vmicro,dr=dr, **kwargs) # Need to use astropy's fits reader, bc the file has issues import astropy.io.fits as apyfits from astropy.utils.exceptions import AstropyUserWarning import warnings warnings.filterwarnings('ignore',category=AstropyUserWarning) hdulist= apyfits.open(filePath) # Find index of nearest grid point in Teff, logg, and metals if dr is None: dr= path._default_dr() if dr == '12': logggrid= numpy.linspace(0.,5.,11) metalsgrid= numpy.linspace(-2.5,0.5,7) if lib.lower() == 'gk': teffgrid= numpy.linspace(3500.,6000.,11) teffIndx= numpy.argmin(numpy.fabs(teff-teffgrid)) elif lib.lower() == 'f': teffgrid= numpy.linspace(5500.,8000.,11) teffIndx= numpy.argmin(numpy.fabs(teff-teffgrid)) loggIndx= numpy.argmin(numpy.fabs(logg-logggrid)) metalsIndx= numpy.argmin(numpy.fabs(metals-metalsgrid)) if header and not ext == 234: return (hdulist[ext].data[metalsIndx,loggIndx,teffIndx], hdulist[ext].header) elif not ext == 234:
from sewingmachine import equivalentwidths, linelist import numpy as np from astropy.io import fits import apogee.tools.read as apread import apogee.tools.path as appath import apogee.spec.plot as splot from tqdm import tqdm import os _DEFAULT_DR = appath._default_dr() def measure_apogee(allStar, linelist_obj, output_fits=False, *args, **kwargs): if isinstance(linelist_obj, str): linelist_obj = linelist.Linelist(linelist_obj) loc_ids, apogee_ids = make_speclist(allStar) lams = splot.apStarWavegrid() ews = np.empty([np.shape(allStar)[0], np.shape(linelist_obj.labels)[0]]) errs = np.empty([np.shape(allStar)[0], np.shape(linelist_obj.labels)[0]]) try: dr = int(_DEFAULT_DR) except ValueError: dr = 16 if dr <= 13: lockey = 'LOCATION_ID' else: lockey = 'FIELD' for i in tqdm(range(len(apogee_ids))): try: try: loc, id = str(allStar[lockey][i],
def modelSpec(lib='GK',teff=4500,logg=2.5,metals=0., cfe=0.,nfe=0.,afe=0.,vmicro=2., dr=None,rmHDU1=True,rmHDU2=True): """ NAME: modelSpec PURPOSE: download a model spectrum file INPUT: lib= ('GK') spectral library teff= (4500) grid-point Teff logg= (2.5) grid-point logg metals= (0.) grid-point metallicity cfe= (0.) grid-point carbon-enhancement nfe= (0.) grid-point nitrogen-enhancement afe= (0.) grid-point alpha-enhancement vmicro= (2.) grid-point microturbulence dr= return the path corresponding to this data release rmHUD1= (True) if True, rm the first (v. large) HDU with the high-resolution model spectrum rmHDU2= (True) if True, rm the second (quite large) HDU with the model spectrum convolved with the LSF OUTPUT: (none; just downloads) HISTORY: 2015-01-20 - Written - Bovy (IAS) """ if dr is None: dr= path._default_dr() # First make sure the file doesn't exist filePath= path.modelSpecPath(lib=lib,teff=teff,logg=logg,metals=metals, cfe=cfe,nfe=nfe,afe=afe,vmicro=vmicro,dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath= filePath.replace(os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath,filePath,dr,verbose=True) # Post-processing of the file, removing the big first HDU or the first two for local storage if rmHDU1 or rmHDU2: # Open the file, need to use astropy's fits reader, bc the file has issues import astropy.io.fits as apyfits from astropy.utils.exceptions import AstropyUserWarning import warnings warnings.filterwarnings('ignore',category=AstropyUserWarning) hdulist= apyfits.open(filePath) if rmHDU1: hdu= apyfits.PrimaryHDU(numpy.zeros((2,2))) else: hdu= hdulist[0].copy() inp= [hdu] if rmHDU2: hdu2= apyfits.ImageHDU(numpy.zeros((2,2))) else: hdu2= hdulist[1].copy() inp.append(hdu2) inp.extend(hdulist[2:]) newHdulist= apyfits.HDUList(inp) # Fix any issues in the headers for ii in range(5): if '[A/M]' in newHdulist[ii].header: newHdulist[ii].header['AM']= newHdulist[ii].header.pop('[A/M]',None) if '[C/M]' in newHdulist[ii].header: newHdulist[ii].header['CM']= newHdulist[ii].header.pop('[C/M]',None) if '[N/M]' in newHdulist[ii].header: newHdulist[ii].header['NM']= newHdulist[ii].header.pop('[N/M]',None) # Overwrite file newHdulist.writeto(filePath,clobber=True,output_verify='silentfix') return None
def mcmc(spec,specerr, fparam=None, teff=4750.,logg=2.5,metals=0.,am=0.,nm=0.,cm=0.,vm=None, nsamples=1000,nwalkers=40, initsig=[20.,0.05,0.025,0.025,0.025,0.025,0.025], fixteff=False,fixlogg=False,fixmetals=False,fixam=False,fixcm=False, fixnm=False,fixvm=False, lib='GK',pca=True,sixd=True,dr=None, inter=3,f_format=1,f_access=None, verbose=False): """ NAME: mcmc PURPOSE: Perform MCMC of the 6/7 parameter global fit of model spectra to a given data spectrum INPUT: Either: (1) location ID - single or list/array of location IDs APOGEE ID - single or list/array of APOGEE IDs; loads aspcapStar (2) spec - spectrum: can be (nwave) or (nspec,nwave) specerr - spectrum errors: can be (nwave) or (nspec,nwave) Input parameters (can be 1D arrays) Either: (1) fparam= (None) output of ferre.fit (2) teff= (4750.) Effective temperature (K) logg= (2.5) log10 surface gravity / cm s^-2 metals= (0.) overall metallicity am= (0.) [alpha/M] nm= (0.) [N/M] cm= (0.) [C/M] vm= if using the 7D library, also specify the microturbulence MCMC options: nsamples= (1000) number of samples to get nwalkers= (40) number of ensemble walkers to use in the MCMC initsig= std. dev. of the initial ball of walkers around [Teff,logg,log10vmicro,metals,cm,nm,am] specify log10vmicro even when using a 6D library fixteff= (True) if True, fix teff at the input value fixlogg= (True) if True, fix logg at the input value fixvm= (True) if True, fix vm at the input value (only if sixd is False) fixmetals= (None) if True, fix metals at the input value fixam= (None) if True, fix am at the input value fixcm= (None) if True, fix cm at the input value fixnm= (None) if True, fix nm at the input value Library options: lib= ('GK') spectral library pca= (True) if True, use a PCA compressed library sixd= (True) if True, use the 6D library (w/o vm) dr= data release FERRE options: inter= (3) order of the interpolation f_format= (1) file format (0=ascii, 1=unf) f_access= (None) 0: load whole library, 1: use direct access (for small numbers of interpolations), None: automatically determine a good value (currently, 1) verbose= (False) if True, run FERRE in verbose mode OUTPUT: TBD HISTORY: 2015-04-08 - Written - Bovy (IAS) """ # Parse fparam if not fparam is None: teff= fparam[:,paramIndx('TEFF')] logg= fparam[:,paramIndx('LOGG')] metals= fparam[:,paramIndx('METALS')] am= fparam[:,paramIndx('ALPHA')] nm= fparam[:,paramIndx('N')] cm= fparam[:,paramIndx('C')] if sixd: vm= None else: vm= fparam[:,paramIndx('LOG10VDOP')] # Make sure the Teff etc. have the right dimensionality if len(spec.shape) == 1: nspec= 1 else: raise ValueError("apogee.modelspec.ferre.mcmc only works for a single spectrum") nspec= spec.shape[0] if nspec > 1 and isinstance(teff,float): teff= teff*numpy.ones(nspec) if nspec > 1 and isinstance(logg,float): logg= logg*numpy.ones(nspec) if nspec > 1 and isinstance(metals,float): metals= metals*numpy.ones(nspec) if nspec > 1 and isinstance(am,float): am= am*numpy.ones(nspec) if nspec > 1 and isinstance(nm,float): nm= nm*numpy.ones(nspec) if nspec > 1 and isinstance(cm,float): cm= cm*numpy.ones(nspec) if nspec > 1 and not vm is None and isinstance(vm,float): vm= vm*numpy.ones(nspec) if dr is None: dr= appath._default_dr() # Setup the walkers ndim= 7-sixd-fixvm+sixd*fixvm-fixteff-fixlogg-fixmetals-fixam-fixcm-fixnm p0= [] for ii in range(nwalkers): tp0= [] # Teff if not fixteff: tteff= teff+numpy.random.normal()*initsig[0] if tteff > 6000.: tteff= 6000. if tteff < 3500.: tteff= 3500. tp0.append(tteff) # logg if not fixlogg: tlogg= logg+numpy.random.normal()*initsig[1] if logg > 5.: tlogg= 5. if logg < 0.: tlogg= 0. tp0.append(tlogg) # log10vmicro if not (fixvm or sixd): tvm= numpy.log10(vm)+numpy.random.normal()*initsig[2] if tvm > numpy.log10(8.0): tvm= numpy.log10(8.0) if tvm < numpy.log10(0.5): tvm= numpy.log10(0.5) tp0.append(tvm) # metals if not fixmetals: tmetals= metals+numpy.random.normal()*initsig[3] if metals > 0.5: tmetals= 0.5 if metals < -2.5: tmetals= -2.5 tp0.append(tmetals) # cm if not fixcm: tcm= cm+numpy.random.normal()*initsig[4] if cm > 1.0: tcm= 1.0 if cm < -1.0: tcm= -1. tp0.append(tcm) # nm if not fixnm: tnm= nm+numpy.random.normal()*initsig[5] if nm > 0.5: tnm= 1.0 if nm < -1.0: tnm= -1.0 tp0.append(tnm) # am if not fixam: tam= am+numpy.random.normal()*initsig[6] if am > 0.5: tam= 1.0 if am < -1.0: tam= -1.0 tp0.append(tam) p0.append(numpy.array(tp0)[:,0]) p0= numpy.array(p0) # Prepare the data dspec= numpy.tile(spec,(nwalkers,1)) dspecerr= numpy.tile(specerr,(nwalkers,1)) # Run MCMC sampler= apogee.util.emcee.EnsembleSampler(nwalkers,ndim,_mcmc_lnprob, args=[dspec,dspecerr, teff,logg,vm,metals, cm,nm,am, fixteff,fixlogg,fixvm, fixmetals,fixcm,fixnm, fixam,sixd,pca, dr,lib, inter,f_format,f_access]) # Burn-in 10% of nsamples pos, prob, state = sampler.run_mcmc(p0,nsamples//10) sampler.reset() # Run main MCMC sampler.run_mcmc(pos,nsamples) return sampler.flatchain
def fit(spec,specerr, teff=4750.,logg=2.5,metals=0.,am=0.,nm=0.,cm=0.,vm=None, fixteff=False,fixlogg=False,fixmetals=False,fixam=False,fixcm=False, fixnm=False,fixvm=False, lib='GK',pca=True,sixd=True,dr=None, offile=None, inter=3,f_format=1,f_access=None, errbar=1,indini=[1,1,1,2,2,3],init=1,initcannon=False, verbose=False): """ NAME: fit PURPOSE: Fit a model spectrum to a given data spectrum INPUT: Either: (1) location ID - single or list/array of location IDs APOGEE ID - single or list/array of APOGEE IDs; loads aspcapStar (2) spec - spectrum: can be (nwave) or (nspec,nwave) specerr - spectrum errors: can be (nwave) or (nspec,nwave) Input parameters (can be 1D arrays); only used when init=0 teff= (4750.) Effective temperature (K) logg= (2.5) log10 surface gravity / cm s^-2 metals= (0.) overall metallicity am= (0.) [alpha/M] nm= (0.) [N/M] cm= (0.) [C/M] vm= if using the 7D library, also specify the microturbulence Fit options: fixteff= (False) if True, fix teff at the input value fixlogg= (False) if True, fix logg at the input value fixmetals= (False) if True, fix metals at the input value fixam= (False) if True, fix am at the input value fixcm= (False) if True, fix cm at the input value fixnm= (False) if True, fix nm at the input value fixvm= (False) if True, fix vm at the input value (only if sixd is False) Library options: lib= ('GK') spectral library pca= (True) if True, use a PCA compressed library sixd= (True) if True, use the 6D library (w/o vm) dr= data release FERRE options: inter= (3) order of the interpolation errbar= (1) method for calculating the error bars indini= ([1,1,1,2,2,3]) how to initialize the search (int or array/list with ndim entries) init= (1) if 0, initialize the search at the parameters in the pfile f_format= (1) file format (0=ascii, 1=unf) f_access= (None) 0: load whole library, 1: use direct access (for small numbers of interpolations), None: automatically determine a good value (currently, 1) Other options: initcannon= (False) If True, initialize a single run by first running the Cannon using the default Cannon fit (sets init=0) Output options: offile= (None) if offile is set, the FERRE OFFILE is saved to this file, otherwise this file is removed verbose= (False) if True, run FERRE in verbose mode OUTPUT: best-fit parameters (nspec,nparams); in the same order as the FPARAM APOGEE data product HISTORY: 2015-01-29 - Written - Bovy (IAS) """ # Initialize using the Cannon? if initcannon: init= 0 # just run one fit using the Cannon as a starting guess initparams= cannon.polylabels(spec,specerr) if not fixteff: teff= initparams[:,0] if not fixlogg: logg= initparams[:,1] if not fixmetals: metals= initparams[:,2] if not fixam: am= initparams[:,3] if not fixcm: cm= numpy.zeros_like(initparams[:,0]) if not fixnm: nm= numpy.zeros_like(initparams[:,0]) # Make sure the Teff etc. have the right dimensionality if len(spec.shape) == 1: nspec= 1 else: nspec= spec.shape[0] if nspec > 1 and isinstance(teff,float): teff= teff*numpy.ones(nspec) if nspec > 1 and isinstance(logg,float): logg= logg*numpy.ones(nspec) if nspec > 1 and isinstance(metals,float): metals= metals*numpy.ones(nspec) if nspec > 1 and isinstance(am,float): am= am*numpy.ones(nspec) if nspec > 1 and isinstance(nm,float): nm= nm*numpy.ones(nspec) if nspec > 1 and isinstance(cm,float): cm= cm*numpy.ones(nspec) if nspec > 1 and not vm is None and isinstance(vm,float): vm= vm*numpy.ones(nspec) if dr is None: dr= appath._default_dr() # Fix any of the parameters? indv= [] indini= copy.copy(indini) # need to copy bc passed by reference if isinstance(indini,numpy.ndarray) and \ ((not sixd and fixvm) or fixcm or fixnm or fixam or fixmetals \ or fixlogg or fixteff): indini= list(indini) if not sixd and not fixvm: indv.append(1) elif not sixd: if isinstance(indini,list): indini[0]= -1 if not fixcm: indv.append(2-sixd) else: if isinstance(indini,list): indini[1-sixd]= -1 if not fixnm: indv.append(3-sixd) else: if isinstance(indini,list): indini[2-sixd]= -1 if not fixam: indv.append(4-sixd) else: if isinstance(indini,list): indini[3-sixd]= -1 if not fixmetals: indv.append(5-sixd) else: if isinstance(indini,list): indini[4-sixd]= -1 if not fixlogg: indv.append(6-sixd) else: if isinstance(indini,list): indini[5-sixd]= -1 if not fixteff: indv.append(7-sixd) else: if isinstance(indini,list): indini[6-sixd]= -1 if isinstance(indini,list): while -1 in indini: indini.remove(-1) # Setup temporary directory to run FERRE from tmpDir= tempfile.mkdtemp(dir='./') try: # First write the ipf file with the parameters write_ipf(tmpDir,teff,logg,metals,am,nm,cm,vm=vm) # Write the file with the fluxes and the flux errors write_ffile(tmpDir,spec,specerr=specerr) # Now write the input.nml file if f_access is None: f_access= 1 write_input_nml(tmpDir,'input.ipf','output.dat',ndim=7-sixd, nov=7-sixd-fixcm-fixnm-fixam-fixmetals\ -fixlogg-fixteff, indv=indv, synthfile=appath.ferreModelLibraryPath\ (lib=lib,pca=pca,sixd=sixd,dr=dr, header=True,unf=False), ffile='input.frd',erfile='input.err', opfile='output.opf', inter=inter,f_format=f_format, errbar=errbar,indini=indini,init=init, f_access=f_access) # Run FERRE run_ferre(tmpDir,verbose=verbose) # Read the output cols= (1,2,3,4,5,6) tmpOut= numpy.loadtxt(os.path.join(tmpDir,'output.opf'),usecols=cols) if len(spec.shape) == 1 or spec.shape[0] == 1: out= numpy.zeros((1,7)) tmpOut= numpy.reshape(tmpOut,(1,7-sixd)) else: out= numpy.zeros((nspec,7)) out[:,paramIndx('TEFF')]= tmpOut[:,-1] out[:,paramIndx('LOGG')]= tmpOut[:,-2] out[:,paramIndx('METALS')]= tmpOut[:,-3] out[:,paramIndx('ALPHA')]= tmpOut[:,-4] out[:,paramIndx('N')]= tmpOut[:,-5] out[:,paramIndx('C')]= tmpOut[:,-6] if sixd and dr == '12': out[:,paramIndx('LOG10VDOP')]=\ numpy.log10(2.478-0.325*out[:,paramIndx('LOGG')]) else: out[:,paramIndx('LOG10VDOP')]= tmpOut[:,0] if not offile is None: os.rename(os.path.join(tmpDir,'output.dat'),offile) finally: # Clean up if os.path.exists(os.path.join(tmpDir,'input.ipf')): os.remove(os.path.join(tmpDir,'input.ipf')) if os.path.exists(os.path.join(tmpDir,'input.frd')): os.remove(os.path.join(tmpDir,'input.frd')) if os.path.exists(os.path.join(tmpDir,'input.err')): os.remove(os.path.join(tmpDir,'input.err')) if os.path.exists(os.path.join(tmpDir,'input.nml')): os.remove(os.path.join(tmpDir,'input.nml')) if os.path.exists(os.path.join(tmpDir,'output.dat')): os.remove(os.path.join(tmpDir,'output.dat')) if os.path.exists(os.path.join(tmpDir,'output.opf')): os.remove(os.path.join(tmpDir,'output.opf')) os.rmdir(tmpDir) return out
def modelSpec(lib='GK', teff=4500, logg=2.5, metals=0., cfe=0., nfe=0., afe=0., vmicro=2., dr=None, header=True, ext=234, apStarWavegrid=None, **kwargs): """ NAME: modelSpec PURPOSE: Read a model spectrum file INPUT: lib= ('GK') spectral library teff= (4500) grid-point Teff logg= (2.5) grid-point logg metals= (0.) grid-point metallicity cfe= (0.) grid-point carbon-enhancement nfe= (0.) grid-point nitrogen-enhancement afe= (0.) grid-point alpha-enhancement vmicro= (2.) grid-point microturbulence dr= return the path corresponding to this data release ext= (234) extension to load (if ext=234, the blue, green, and red spectra will be combined [onto the aspcapStar wavelength grid by default, just concatenated if apStarWavegrid=False), with NaN where there is no model) apStarWavegrid= (True) if False and ext=234, don't put the spectrum on the apStar wavelength grid, but just concatenate the blue, green, and red detector header= (True) if True, also return the header (not for ext=234) dr= return the path corresponding to this data release (general default) +download kwargs OUTPUT: model spectrum or (model spectrum file, header) HISTORY: 2015-01-13 - Written - Bovy (IAS) """ filePath = path.modelSpecPath(lib=lib, teff=teff, logg=logg, metals=metals, cfe=cfe, nfe=nfe, afe=afe, vmicro=vmicro, dr=dr) if not os.path.exists(filePath): download.modelSpec(lib=lib, teff=teff, logg=logg, metals=metals, cfe=cfe, nfe=nfe, afe=afe, vmicro=vmicro, dr=dr, **kwargs) # Need to use astropy's fits reader, bc the file has issues import astropy.io.fits as apyfits from astropy.utils.exceptions import AstropyUserWarning import warnings warnings.filterwarnings('ignore', category=AstropyUserWarning) hdulist = apyfits.open(filePath) # Find index of nearest grid point in Teff, logg, and metals if dr is None: dr = path._default_dr() if dr == '12': logggrid = numpy.linspace(0., 5., 11) metalsgrid = numpy.linspace(-2.5, 0.5, 7) if lib.lower() == 'gk': teffgrid = numpy.linspace(3500., 6000., 11) teffIndx = numpy.argmin(numpy.fabs(teff - teffgrid)) elif lib.lower() == 'f': teffgrid = numpy.linspace(5500., 8000., 11) teffIndx = numpy.argmin(numpy.fabs(teff - teffgrid)) loggIndx = numpy.argmin(numpy.fabs(logg - logggrid)) metalsIndx = numpy.argmin(numpy.fabs(metals - metalsgrid)) if header and not ext == 234: return (hdulist[ext].data[metalsIndx, loggIndx, teffIndx], hdulist[ext].header) elif not ext == 234: return hdulist[ext].data[metalsIndx, loggIndx, teffIndx] else: #ext == 234, combine 2,3,4 out = numpy.zeros(7214) out[:2920] = hdulist[2].data[metalsIndx, loggIndx, teffIndx] out[2920:5320] = hdulist[3].data[metalsIndx, loggIndx, teffIndx] out[5320:] = hdulist[4].data[metalsIndx, loggIndx, teffIndx] return out
def modelSpec(lib='GK',teff=4500,logg=2.5,metals=0., cfe=0.,nfe=0.,afe=0.,vmicro=2., dr=None,header=True,ext=234,apStarWavegrid=None,**kwargs): """ NAME: modelSpec PURPOSE: Read a model spectrum file INPUT: lib= ('GK') spectral library teff= (4500) grid-point Teff logg= (2.5) grid-point logg metals= (0.) grid-point metallicity cfe= (0.) grid-point carbon-enhancement nfe= (0.) grid-point nitrogen-enhancement afe= (0.) grid-point alpha-enhancement vmicro= (2.) grid-point microturbulence dr= return the path corresponding to this data release ext= (234) extension to load (if ext=234, the blue, green, and red spectra will be combined [onto the aspcapStar wavelength grid by default, just concatenated if apStarWavegrid=False), with NaN where there is no model) apStarWavegrid= (True) if False and ext=234, don't put the spectrum on the apStar wavelength grid, but just concatenate the blue, green, and red detector header= (True) if True, also return the header (not for ext=234) dr= return the path corresponding to this data release (general default) +download kwargs OUTPUT: model spectrum or (model spectrum file, header) HISTORY: 2015-01-13 - Written - Bovy (IAS) """ filePath= path.modelSpecPath(lib=lib,teff=teff,logg=logg,metals=metals, cfe=cfe,nfe=nfe,afe=afe,vmicro=vmicro,dr=dr) if not os.path.exists(filePath): download.modelSpec(lib=lib,teff=teff,logg=logg,metals=metals, cfe=cfe,nfe=nfe,afe=afe,vmicro=vmicro,dr=dr, **kwargs) # Need to use astropy's fits reader, bc the file has issues import astropy.io.fits as apyfits from astropy.utils.exceptions import AstropyUserWarning import warnings warnings.filterwarnings('ignore',category=AstropyUserWarning) hdulist= apyfits.open(filePath) # Find index of nearest grid point in Teff, logg, and metals if dr is None: dr= path._default_dr() if dr == '12': logggrid= numpy.linspace(0.,5.,11) metalsgrid= numpy.linspace(-2.5,0.5,7) if lib.lower() == 'gk': teffgrid= numpy.linspace(3500.,6000.,11) teffIndx= numpy.argmin(numpy.fabs(teff-teffgrid)) elif lib.lower() == 'f': teffgrid= numpy.linspace(5500.,8000.,11) teffIndx= numpy.argmin(numpy.fabs(teff-teffgrid)) loggIndx= numpy.argmin(numpy.fabs(logg-logggrid)) metalsIndx= numpy.argmin(numpy.fabs(metals-metalsgrid)) if header and not ext == 234: return (hdulist[ext].data[metalsIndx,loggIndx,teffIndx], hdulist[ext].header) elif not ext == 234: return hdulist[ext].data[metalsIndx,loggIndx,teffIndx] else: #ext == 234, combine 2,3,4 out= numpy.zeros(7214) out[:2920]= hdulist[2].data[metalsIndx,loggIndx,teffIndx] out[2920:5320]= hdulist[3].data[metalsIndx,loggIndx,teffIndx] out[5320:]= hdulist[4].data[metalsIndx,loggIndx,teffIndx] return out
def modelSpec(lib='GK', teff=4500, logg=2.5, metals=0., cfe=0., nfe=0., afe=0., vmicro=2., dr=None, rmHDU1=True, rmHDU2=True): """ NAME: modelSpec PURPOSE: download a model spectrum file INPUT: lib= ('GK') spectral library teff= (4500) grid-point Teff logg= (2.5) grid-point logg metals= (0.) grid-point metallicity cfe= (0.) grid-point carbon-enhancement nfe= (0.) grid-point nitrogen-enhancement afe= (0.) grid-point alpha-enhancement vmicro= (2.) grid-point microturbulence dr= return the path corresponding to this data release rmHUD1= (True) if True, rm the first (v. large) HDU with the high-resolution model spectrum rmHDU2= (True) if True, rm the second (quite large) HDU with the model spectrum convolved with the LSF OUTPUT: (none; just downloads) HISTORY: 2015-01-20 - Written - Bovy (IAS) """ if dr is None: dr = path._default_dr() # First make sure the file doesn't exist filePath = path.modelSpecPath(lib=lib, teff=teff, logg=logg, metals=metals, cfe=cfe, nfe=nfe, afe=afe, vmicro=vmicro, dr=dr) if os.path.exists(filePath): return None # Create the file path downloadPath = filePath.replace( os.path.join(path._APOGEE_DATA, _dr_string(dr)), _base_url(dr=dr)) _download_file(downloadPath, filePath, dr, verbose=True) # Post-processing of the file, removing the big first HDU or the first two for local storage if rmHDU1 or rmHDU2: # Open the file, need to use astropy's fits reader, bc the file has issues import astropy.io.fits as apyfits from astropy.utils.exceptions import AstropyUserWarning import warnings warnings.filterwarnings('ignore', category=AstropyUserWarning) hdulist = apyfits.open(filePath) if rmHDU1: hdu = apyfits.PrimaryHDU(numpy.zeros((2, 2))) else: hdu = hdulist[0].copy() inp = [hdu] if rmHDU2: hdu2 = apyfits.ImageHDU(numpy.zeros((2, 2))) else: hdu2 = hdulist[1].copy() inp.append(hdu2) inp.extend(hdulist[2:]) newHdulist = apyfits.HDUList(inp) # Fix any issues in the headers for ii in range(5): if '[A/M]' in newHdulist[ii].header: newHdulist[ii].header['AM'] = newHdulist[ii].header.pop( '[A/M]', None) if '[C/M]' in newHdulist[ii].header: newHdulist[ii].header['CM'] = newHdulist[ii].header.pop( '[C/M]', None) if '[N/M]' in newHdulist[ii].header: newHdulist[ii].header['NM'] = newHdulist[ii].header.pop( '[N/M]', None) # Overwrite file newHdulist.writeto(filePath, clobber=True, output_verify='silentfix') return None
def pixels_cannon(*args, **kwargs): """ NAME: pixels_cannon PURPOSE: determine continuum pixels using a Cannon-like technique (Ness et al. 2015) INPUT: Either: a) Input for running the apogee.spec.cannon: spec - spectra to fit (nspec,nlambda) specerrs - errors on the spectra (nspec,nlambda); assume no covariances label1, label2, ... - labels (nspec); best to subtract reference values before running this type= ('lin') type of Cannon to run: 'lin' - linear Cannon 'quad' - quadratic Cannon b) Output from a previous Cannon run: coefficients - coefficients from the fit (ncoeffs,nlambda) scatter - scatter from the fit (nlambda) KEYWORDS: baseline_dev= (0.015) maximum deviation from baseline label1_max= (10.**-5.) maximum deviation in first linear coefficient label2_max= (0.006) similar for the second label3_max= (0.012) similar for the third labelN_max= same with default 0.03 ... scatter_max= (0.015) maximum scatter of residuals dr= (module-wide default) data release OUTPUT: Boolean index into the wavelength range with True for continuum pixels HISTORY: 2015-02-05 - Written - Bovy (IAS@KITP) """ # Grab kwargs type = kwargs.pop('type', 'lin') dr = kwargs.pop('dr', path._default_dr()) # Parse input if len(args) == 0: # Use default fit from apogee.spec._train_cannon import load_fit coeffs, scatter, baseline_labels = load_fit() type = 'quad' else: spec = args[0] specerr = args[1] # Determine the type of input if len(specerr.shape) == 2: # Run the Cannon if type.lower() == 'lin': coeffs, scatter = cannon.linfit(*args) elif type.lower() == 'quad': coeffs, scatter = cannon.quadfit(*args) else: coeffs = spec scatter = specerr ncoeffs = coeffs.shape[0] if type.lower() == 'lin': nlabels = ncoeffs - 1 elif type.lower() == 'quad': nlabels = int((-3 + numpy.sqrt(9 + 8 * (ncoeffs - 1)))) // 2 # Determine continuum pixels out = numpy.ones(len(scatter), dtype='bool') # Deviation from baseline out[numpy.fabs(coeffs[0] - 1.) > kwargs.get('baseline_dev', 0.015)] = False # Large dependence on labels maxs = numpy.zeros(nlabels) maxs[0] = kwargs.get('label1_max', 10.**-5.) maxs[1] = kwargs.get('label2_max', 0.006) maxs[2] = kwargs.get('label3_max', 0.012) for ii in range(nlabels - 3): maxs[ii + 3] = kwargs.get('label%i_max' % (ii + 4), 0.03) for ii in range(1, nlabels + 1): out[numpy.fabs(coeffs[ii]) > maxs[ii - 1]] = False # Large residuals out[scatter > kwargs.get('scatter_max', 0.015)] = False _, _, _, aspcapDR12length = _aspcapPixelLimits(dr='12') if int(dr) > 12 and coeffs.shape[1] == aspcapDR12length: # Want continuum pixels on >DR12 ASPCAP grid, but using coefficients # from <= DR12 grid dr_module = path._default_dr() path.change_dr(12) out = toApStarGrid(out) path.change_dr(dr) out = toAspcapGrid(out) path.change_dr(dr_module) return out
def elemfit(spec,specerr,elem, fparam=None, teff=4750.,logg=2.5,metals=0.,am=0.,nm=0.,cm=0.,vm=None, fixteff=True,fixlogg=True,fixmetals=None,fixam=None, fixcm=None, fixnm=None,fixvm=True, estimate_err=False, lib='GK',pca=True,sixd=True,dr=None, offile=None, inter=3,f_format=1,f_access=None, errbar=1,indini=[1,1,1,2,2,3],init=0, verbose=False): """ NAME: elemfit PURPOSE: Fit a model spectrum to a given data spectrum for a given element window INPUT: Either: (1) location ID - single or list/array of location IDs APOGEE ID - single or list/array of APOGEE IDs; loads aspcapStar (2) spec - spectrum: can be (nwave) or (nspec,nwave) specerr - spectrum errors: can be (nwave) or (nspec,nwave) elem - element to fit (e.g., 'Al') estimate_err= (False) if True, estimate the error from Delta chi^2=1; only works for errors <~ 0.3 dex, code returns numpy.nan when error is larger Input parameters (can be 1D arrays); only used when init=0 Either: (1) fparam= (None) output of ferre.fit (2) teff= (4750.) Effective temperature (K) logg= (2.5) log10 surface gravity / cm s^-2 metals= (0.) overall metallicity am= (0.) [alpha/M] nm= (0.) [N/M] cm= (0.) [C/M] vm= if using the 7D library, also specify the microturbulence Fit options: fixteff= (True) if True, fix teff at the input value fixlogg= (True) if True, fix logg at the input value fixvm= (True) if True, fix vm at the input value (only if sixd is False) The following are set to False based on the element being fit (C -> fixcm=False, N -> fixnm=False, O,Mg,S,Si,Ca,Ti -> fixam=False, rest -> fixmetals=False) fixmetals= (None) if True, fix metals at the input value fixam= (None) if True, fix am at the input value fixcm= (None) if True, fix cm at the input value fixnm= (None) if True, fix nm at the input value Library options: lib= ('GK') spectral library pca= (True) if True, use a PCA compressed library sixd= (True) if True, use the 6D library (w/o vm) dr= data release FERRE options: inter= (3) order of the interpolation errbar= (1) method for calculating the error bars indini= ([1,1,1,2,2,3]) how to initialize the search (int or array/list with ndim entries) init= (0) if 0, initialize the search at the parameters in the pfile f_format= (1) file format (0=ascii, 1=unf) f_access= (None) 0: load whole library, 1: use direct access (for small numbers of interpolations), None: automatically determine a good value (currently, 1) Output options: offile= (None) if offile is set, the FERRE OFFILE is saved to this file, otherwise this file is removed verbose= (False) if True, run FERRE in verbose mode OUTPUT: best-fit parameters (nspec,nparams); in the same order as the FPARAM APOGEE data product (fixed inputs are repeated in the output) if estimate_err: tuple with best-fit (see above) and error on the element abundance HISTORY: 2015-02-27 - Written - Bovy (IAS) """ # Parse fparam if not fparam is None: teff= fparam[:,paramIndx('TEFF')] logg= fparam[:,paramIndx('LOGG')] metals= fparam[:,paramIndx('METALS')] am= fparam[:,paramIndx('ALPHA')] nm= fparam[:,paramIndx('N')] cm= fparam[:,paramIndx('C')] if sixd: vm= None else: vm= fparam[:,paramIndx('LOG10VDOP')] # Make sure the Teff etc. have the right dimensionality if len(spec.shape) == 1: nspec= 1 else: nspec= spec.shape[0] if nspec > 1 and isinstance(teff,float): teff= teff*numpy.ones(nspec) if nspec > 1 and isinstance(logg,float): logg= logg*numpy.ones(nspec) if nspec > 1 and isinstance(metals,float): metals= metals*numpy.ones(nspec) if nspec > 1 and isinstance(am,float): am= am*numpy.ones(nspec) if nspec > 1 and isinstance(nm,float): nm= nm*numpy.ones(nspec) if nspec > 1 and isinstance(cm,float): cm= cm*numpy.ones(nspec) if nspec > 1 and not vm is None and isinstance(vm,float): vm= vm*numpy.ones(nspec) if dr is None: dr= appath._default_dr() # Set fixXX based on element being fit, first set None to True if fixcm is None: fixcm= True if fixnm is None: fixnm= True if fixam is None: fixam= True if fixmetals is None: fixmetals= True if elem.lower() == 'c': fixcm= False elif elem.lower() == 'n': fixnm= False elif elem.lower() in ['o','mg','s','si','ca','ti']: fixam= False else: fixmetals= False # Fix any of the parameters? indv= [] indini= copy.copy(indini) # need to copy bc passed by reference if isinstance(indini,numpy.ndarray) and \ ((not sixd and fixvm) or fixcm or fixnm or fixam or fixmetals \ or fixlogg or fixteff): indini= list(indini) if not sixd and not fixvm: indv.append(1) elif not sixd: if isinstance(indini,list): indini[0]= -1 if not fixcm: indv.append(2-sixd) else: if isinstance(indini,list): indini[1-sixd]= -1 if not fixnm: indv.append(3-sixd) else: if isinstance(indini,list): indini[2-sixd]= -1 if not fixam: indv.append(4-sixd) else: if isinstance(indini,list): indini[3-sixd]= -1 if not fixmetals: indv.append(5-sixd) else: if isinstance(indini,list): indini[4-sixd]= -1 if not fixlogg: indv.append(6-sixd) else: if isinstance(indini,list): indini[5-sixd]= -1 if not fixteff: indv.append(7-sixd) else: if isinstance(indini,list): indini[6-sixd]= -1 if isinstance(indini,list): while -1 in indini: indini.remove(-1) if init == 0: indini= 0 # Setup temporary directory to run FERRE from tmpDir= tempfile.mkdtemp(dir='./') try: # First write the ipf file with the parameters write_ipf(tmpDir,teff,logg,metals,am,nm,cm,vm=vm) # Write the file with the fluxes and the flux errors write_ffile(tmpDir,spec,specerr=specerr) # Now write the input.nml file if f_access is None: f_access= 1 write_input_nml(tmpDir,'input.ipf','output.dat',ndim=7-sixd, nov=7-sixd-fixcm-fixnm-fixam-fixmetals\ -fixlogg-fixteff, indv=indv, synthfile=appath.ferreModelLibraryPath\ (lib=lib,pca=pca,sixd=sixd,dr=dr, header=True,unf=False), ffile='input.frd',erfile='input.err', opfile='output.opf', inter=inter,f_format=f_format, errbar=errbar,indini=indini,init=init, f_access=f_access, filterfile=apwindow.path(elem,dr=dr)) # Run FERRE run_ferre(tmpDir,verbose=verbose) # Read the output cols= (1,2,3,4,5,6) tmpOut= numpy.loadtxt(os.path.join(tmpDir,'output.opf'),usecols=cols) if len(spec.shape) == 1 or spec.shape[0] == 1: out= numpy.zeros((1,7)) tmpOut= numpy.reshape(tmpOut,(1,7-sixd)) else: out= numpy.zeros((nspec,7)) out[:,paramIndx('TEFF')]= tmpOut[:,-1] out[:,paramIndx('LOGG')]= tmpOut[:,-2] out[:,paramIndx('METALS')]= tmpOut[:,-3] out[:,paramIndx('ALPHA')]= tmpOut[:,-4] out[:,paramIndx('N')]= tmpOut[:,-5] out[:,paramIndx('C')]= tmpOut[:,-6] if sixd and dr == '12': out[:,paramIndx('LOG10VDOP')]=\ numpy.log10(2.478-0.325*out[:,paramIndx('LOGG')]) else: out[:,paramIndx('LOG10VDOP')]= tmpOut[:,0] if not offile is None: os.rename(os.path.join(tmpDir,'output.dat'),offile) finally: # Clean up if os.path.exists(os.path.join(tmpDir,'input.ipf')): os.remove(os.path.join(tmpDir,'input.ipf')) if os.path.exists(os.path.join(tmpDir,'input.frd')): os.remove(os.path.join(tmpDir,'input.frd')) if os.path.exists(os.path.join(tmpDir,'input.err')): os.remove(os.path.join(tmpDir,'input.err')) if os.path.exists(os.path.join(tmpDir,'input.nml')): os.remove(os.path.join(tmpDir,'input.nml')) if os.path.exists(os.path.join(tmpDir,'output.dat')): os.remove(os.path.join(tmpDir,'output.dat')) if os.path.exists(os.path.join(tmpDir,'output.opf')): os.remove(os.path.join(tmpDir,'output.opf')) os.rmdir(tmpDir) if estimate_err: # Determine the chi2 and the error elem_linspace= (-0.5,0.5,51) elems= numpy.linspace(*elem_linspace) c2= elemchi2(spec,specerr,elem, elem_linspace=elem_linspace, fparam=out,lib=lib,pca=pca,sixd=sixd,dr=dr, inter=inter,f_format=f_format,f_access=f_access, verbose=verbose) from scipy import interpolate, optimize outerr= numpy.empty(nspec) for ii in range(nspec): spl= \ interpolate.InterpolatedUnivariateSpline(elems, c2[ii]-numpy.amin(c2[ii])) try: ul= optimize.brentq(lambda x: spl(x)-1., 0.,elem_linspace[1]-0.01) ll= optimize.brentq(lambda x: spl(x)-1., elem_linspace[0]+0.01,0.) outerr[ii]= (ul-ll)/2. except ValueError: outerr[ii]= numpy.nan return (out,outerr) else: return out