def get_photometry(ID=None,to_units='erg/s/cm2/AA',extra_fields=[],include=None, exclude=None,**kwargs): """ Collect photometry from different sources. The output consists of a record array containing the following keys: 'meas': the measurement's value directly from the catalog in original units 'e_meas': the error on the measurements 'flag': any flags that are associated with the measurement in a catalog 'unit': the unit of the original measurement 'source' the source catalog's name 'photband': photometric pass bands' name 'cwave': the effective wavelength of the passband 'cmeas': converted measurement (to C{to_units}) 'e_cmeas': error on converted measurment 'cunit': converted unit Be aware that some of the values can be 'nan': e.g. sometimes no error is listed in the catalog, or no flag. Also the 'cwave' column will be nan for all photometric colours (e.g. B-V) If you define C{extra_fields}, make sure all the {get_photometry} know how to handle it: probably some default values need to be inserted if these extra columns are not available in some catalog. It is safest just to leave it blank. You can include or exclude search sources via C{include} and C{exclude}. When given, these should be a list containing strings. The default is to include C{gator}, C{vizier} and C{gcpd}. Extra keyword arguments are passed to each C{get_photometry} functions in this package's modules. Example usage: 1. You want to download all available photometry and write the results to an ASCII file for later reference. >>> master = get_photometry('vega') >>> ascii.write_array(master,header=True,auto_width=True) 2. You want to plot the raw, unmodelled SED of an object: >>> master = get_photometry('vega') >>> pl.errorbar(master['cwave'],master['cmeas'],yerr=master['e_cmeas'],fmt='ko') >>> pl.gca().set_xscale('log',nonposx='clip') >>> pl.gca().set_yscale('log',nonposy='clip') We made no difference between colors (B-V) and magnitude (V), because the 'cwave' for colors is 'nan', so they will not be plotted anyway.The final two lines are just to correct errorbars that go below zero in a logarithmic plot. @param ID: the target's name, understandable by SIMBAD @type ID: str @param to_units: units to convert everything to. @type to_units: @param include: sources to include @type include: list of strings (from C{gator}, C{vizier} or C{gcpd}) @param exclude: sources to include @type exclude: list of strings (from C{gator}, C{vizier} or C{gcpd}) @return: record array where eacht entry is a photometric measurement @rtype: record array """ #-- make sure all catalog names are lower case if include is not None: include = [i.lower() for i in include] if exclude is not None: exclude = [i.lower() for i in exclude] #-- check which sources to include/exclude searchables = ['gator','vizier','gcpd','mast'] if include is not None: searchables = include if exclude is not None: searchables = list( set(searchables)- set(exclude)) #-- and search photometry if 'mast' in searchables: kwargs['master'] = mast.get_photometry(ID=ID,to_units=to_units,extra_fields=extra_fields,**kwargs) if 'gator' in searchables: kwargs['master'] = gator.get_photometry(ID=ID,to_units=to_units,extra_fields=extra_fields,**kwargs) if 'vizier' in searchables: #-- first query catalogs that can only be queried via HD number info = sesame.search(ID=ID,fix=True) if 'alias' in info: HDnumber = [name for name in info['alias'] if name[:2]=='HD'] if HDnumber: kwargs['master'] = vizier.get_photometry(extra_fields=extra_fields,constraints=['HD=%s'%(HDnumber[0][3:])],sources=['II/83/catalog','V/33/phot'],sort=None,**kwargs) #-- then query catalogs that can only be queried via another catalog results,units,comms = vizier.search('J/A+A/380/609/table1',ID=ID) if results is not None: catname = results[0]['Name'].strip() kwargs['master'] = vizier.get_photometry(take_mean=True,extra_fields=extra_fields,constraints=['Name={0}'.format(catname)],sources=['J/A+A/380/609/table{0}'.format(tnr) for tnr in range(2,5)],sort=None,**kwargs) #-- then query normal catalogs kwargs['master'] = vizier.get_photometry(ID=ID,to_units=to_units,extra_fields=extra_fields,**kwargs) if 'gcpd' in searchables: kwargs['master'] = gcpd.get_photometry(ID=ID,to_units=to_units,extra_fields=extra_fields,**kwargs) master = kwargs['master'] #-- now make a summary of the contents: photbands = [phot.split('.')[0] for phot in master['photband']] contents = [(i,photbands.count(i)) for i in sorted(list(set(photbands)))] for phot in contents: logger.info('%10s: found %d measurements'%phot) return master
xmlpage+=line.strip('\n') database = xmlparser.XMLParser(xmlpage).content try: database = database['Sesame']['Target']['%s'%(db)]['Resolver'] database = database[database.keys()[0]] except KeyError,IndexError: #-- we found nothing! database = {} ff.close() if fix: #-- fix the parallax: make sure we have the Van Leeuwen 2007 value. # simbad seems to have changed to old values to the new ones somewhere # in 2011. We check if this is the case for all stars: if 'plx' in database and not ('2007' in database['plx']['r']): data,units,comms = vizier.search('I/311/hip2',ID=ID) if data is not None and len(data): if not 'plx' in database: database['plx'] = {} database['plx']['v'] = data['Plx'][0] database['plx']['e'] = data['e_Plx'][0] database['plx']['r'] = 'I/311/hip2' #-- fix the spectral type data,units,comms = vizier.search('B/mk/mktypes',ID=ID) if data is not None and len(data): database['spType'] = data['SpType'][0] if 'jpos' in database: #-- add galactic coordinates (in degrees) ra,dec = database['jpos'].split() gal = conversions.convert('equatorial','galactic',(str(ra),str(dec)),epoch='2000') gal = float(gal[0])/np.pi*180,float(gal[1])/np.pi*180
def search(ID, db='S', fix=False): """ Query Simbad, NED and/or Vizier for information on an identifier. This retrieves basic information on a star, e.g. as shown in a typical Simbad page: coordinates, spectral type, fluxes, aliases, references... Database C{db} is one of 'S' (SIMBAD), 'N' (NED), 'V' (Vizier) or 'A' (all). This function returns a (sometimes nested) dictionary. Example output is given below, where nested dictionaries are shown with the separator '.' between the keys. If you set C{fix} to C{False}, following values will be updated: 1. the spectral type will be replaced by the one from the Skiff (2010) catalog if possible. 2. The parallax will be replaced with the value from the new Van Leeuwen reduction. 3. The galactic coordinates will be added (converted from RA and DEC) 4. The proper motions will be taken from the PPMXL catalog from Roeser 2010. Example usage: >>> info = search('vega',db='S') >>> print (info['jpos']) 18:36:56.33 +38:47:01.2 >>> print (info['jdedeg']) 38.78369194 >>> print (info['alias'][1]) * alf Lyr >>> print (info['plx']['v']) 128.93 >>> print (info['mag']['B']['v']) 0.03 This is an exhaustive list of example contents:: Vel.e = 0.9 Vel.q = A Vel.r = 1979IAUS...30...57E Vel.v = -13.9 alias = [u'V* alf Lyr', u'* alf Lyr', u'* 3 Lyr', u'ADS 11510 A', u'AG+38 1711', u'ASCC 507896', u'BD+38 3238', u'CCDM J18369+3847A', u'CEL 4636', u'CSI+38 3238 1', u'CSV 101745', u'1E 183515+3844.3', u'EUVE J1836+38.7', u'FK5 699', u'GC 25466', u'GCRV 11085', u'GEN# +1.00172167', u'GJ 721', u'HD 172167', u'HGAM 706', u'HIC 91262', u'HIP 91262', u'HR 7001', u'IDS 18336+3841 A', u'IRAS 18352+3844', u'IRC +40322', u'JP11 2999', u'LSPM J1836+3847', u'LTT 15486', u'2MASS J18365633+3847012', u'N30 4138', u'NAME VEGA', u'NLTT 46746', u'NSV 11128', u'8pc 128.93', u'PLX 4293.00', u'PLX 4293', u'PMC 90-93 496', u'PPM 81558', u'RAFGL 2208', u'ROT 2633', u'SAO 67174', u'SKY# 34103', u'TD1 22883', u'TYC 3105-2070-1', u'UBV 15842', u'UBV M 23118', u'USNO-B1.0 1287-00305764', u'USNO 882', u'uvby98 100172167 V', u'WDS J18369+3846A', u'Zkh 277', u'[HFE83] 1223'] errDEmas = 5.4 errRAmas = 5.16 jdedeg = 38.78369194 jpos = 18:36:56.33 +38:47:01.2 jradeg = 279.234735 mag.B.q = C mag.B.v = 0.03 mag.H.q = C mag.H.r = 2003yCat.2246....0C mag.H.v = -0.03 mag.I.q = E mag.I.r = 2003AJ....125..984M mag.I.v = 0.2 mag.J.q = C mag.J.r = 2003yCat.2246....0C mag.J.v = -0.18 mag.K.q = C mag.K.r = 2003yCat.2246....0C mag.K.v = 0.13 mag.R.q = E mag.R.r = 2003AJ....125..984M mag.R.v = 0.1 mag.V.q = C mag.V.v = 0.03 nrefs = 1860.0 oid = @2900336 oname = NAME VEGA otype = V* plx.e = 0.55 plx.q = A plx.r = [u'1997A', u'&', u'A...323L..49P'] plx.v = 128.93 pm.e = 0.83 pm.epmDE = 0.6 pm.epmRA = 0.57 pm.pa = 35.0 pm.pmDE = 287.47 pm.pmRA = 201.03 pm.q = A pm.r = [u'1997A', u'&', u'A...323L..49P'] pm.v = 350.79 refPos = [u'1997A', u'&', u'A...323L..49P'] spNum = 0.0000C800.0030.0000000000000000 spType = A0V >>> info = search('vega',db='N') >>> for key1 in sorted(info.keys()): ... print ('%s = %s'%(key1.ljust(8),info[key1])) INFO = from cache alias = [u'alpha Lyr', u'HR 7001', u'HD 172167', u'IRAS 18352+3844', u'IRAS F18352+3844'] errDEmas = 4824.0 errRAmas = 19570.0 jdedeg = 38.782316 jpos = 18:36:55.70 +38:46:56.3 jradeg = 279.2321017 oname = VEGA otype = !* refPos = 1990IRASF.C...0000M @param ID: name of the source @type ID: str @param db: database to use @type db: str ('N','S','V','A') @return: (nested) dictionary containing information on star @rtype: dictionary """ base_url = get_URI(ID, db=db) with urllib.request.urlopen(base_url) as ff: xmlpage = "" for line in ff.readlines(): line = line.decode('utf-8') line_ = line[::-1].strip(' ')[::-1] if line_[0] == '<': line = line_ xmlpage += line.strip('\n') database = xmlparser.XMLParser(xmlpage).content try: database = database['Sesame']['Target']['%s' % (db)]['Resolver'] database = database[list(database.keys())[0]] except KeyError as IndexError: # -- we found nothing! database = {} if fix: # -- fix the parallax: make sure we have the Van Leeuwen 2007 value. # simbad seems to have changed to old values to the new ones # somewhere in 2011. We check if this is the case for all stars: if 'plx' in database and not ('2007' in database['plx']['r']): data, units, comms = vizier.search('I/311/hip2', ID=ID) if data is not None and len(data): if 'plx' not in database: database['plx'] = {} database['plx']['v'] = data['Plx'][0] database['plx']['e'] = data['e_Plx'][0] database['plx']['r'] = 'I/311/hip2' # -- fix the spectral type data, units, comms = vizier.search('B/mk/mktypes', ID=ID) if data is not None and len(data): database['spType'] = data['SpType'][0] if 'jpos' in database: # -- add galactic coordinates (in degrees) ra, dec = database['jpos'].split() gal = conversions.convert('equatorial', 'galactic', (str(ra), str(dec)), epoch='2000') gal = float(gal[0]) / np.pi * 180, float(gal[1]) / np.pi * 180 database['galpos'] = gal # -- fix the proper motions data, units, comms = vizier.search('I/317/sample', ID=ID) if data is not None and len(data): if 'pm' not in database: database['pm'] = {} database['pm']['pmRA'] = data['pmRA'][0] database['pm']['pmDE'] = data['pmDE'][0] database['pm']['epmRA'] = data['e_pmRA'][0] database['pm']['epmDE'] = data['e_pmDE'][0] database['pm']['r'] = 'I/317/sample' return database