def _get_URI(name='GENEVA',ID=None,**kwargs): """ Build GCPD URI from available options. kwargs are to catch unused arguments. @param name: photometric system name (E.g. JOHNSON, STROMGREN, GENEVA...) @type name: string (automatically uppercased) @keyword ID: star name (should be resolvable by SIMBAD) @type ID: string @return: """ #-- GCPD is poor at recognising aliases: therefore we try different # identifiers retrieved from Sesame that GCPD understands recognized_alias = ['HD','BD',"CD"] try: aliases = sesame.search(ID)['alias'] for alias in aliases: if alias[:2] in recognized_alias: ID = alias[:2]+' '+alias[2:] break else: logger.error('Star %s has no aliases recognised by GCPD: query will not return results'%(ID)) except KeyError: logger.error('Unknown star %s: GCPD query will not return results'%(ID)) base_url = 'http://obswww.unige.ch/gcpd/cgi-bin/photoSys.cgi?phot=%02d&type=original&refer=with&mode=starno&ident=%s'%(systems[name],urllib.quote(ID)) logger.debug(base_url) return base_url
def _get_URI(name='GENEVA', ID=None, **kwargs): """ Build GCPD URI from available options. kwargs are to catch unused arguments. @param name: photometric system name (E.g. JOHNSON, STROMGREN, GENEVA...) @type name: string (automatically uppercased) @keyword ID: star name (should be resolvable by SIMBAD) @type ID: string @return: """ #-- GCPD is poor at recognising aliases: therefore we try different # identifiers retrieved from Sesame that GCPD understands recognized_alias = ['HD', 'BD', "CD"] try: aliases = sesame.search(ID)['alias'] for alias in aliases: if alias[:2] in recognized_alias: ID = alias[:2] + ' ' + alias[2:] break else: logger.error( 'Star %s has no aliases recognised by GCPD: query will not return results' % (ID)) except KeyError: logger.error('Unknown star %s: GCPD query will not return results' % (ID)) base_url = 'http://obswww.unige.ch/gcpd/cgi-bin/photoSys.cgi?phot=%02d&type=original&refer=with&mode=starno&ident=%s' % ( systems[name], urllib.quote(ID)) logger.debug(base_url) return base_url
def get_sismo_data(ID): """ Retrieve CoRoT timeseries from a local data repository. The output record array has fields 'HJD', 'flux', 'e_flux', 'flag'. @param ID: ID of the target: either an integer (CoRoT ID), an SIMBAD-recognised target name, or a valid CoRoT FITS file @type ID: int or str @return: data, header @rtype: numpy recarray, dict """ #-- data on one target can be spread over multiple files: collect the # data data = [] if isinstance(ID, str) and os.path.isfile(ID): header = pyfits.getheader(ID) times, flux, error, flags = fits.read_corot(ID) data.append([times, flux, error, flags]) else: #-- resolve the target's name: it's either a target name or CoRoT ID. try: ID = int(ID) except ValueError: info = sesame.search(ID, db='S') IDs = [alias for alias in info['alias'] if 'HD' in alias] if len(IDs) != 1: logger.error( "Data retrieval for %s not possible. Reason: no HD number resolved" % (ID)) return ID = IDs[0] #-- collect the files containing data on the target #catfiles = config.glob((os.sep).join(['catalogs','corot','sismo']),'*.fits') fn_sismo = os.path.join(cc.path.ivsdata, 'catalogs', 'corot', 'sismo', '*.fits') catfiles = glob.glob(fn_sismo) catfiles.sort() for catfile in catfiles: try: header = pyfits.getheader(catfile) except IOError: continue if header['starname'] == ID or header['corotid'].replace( ' ', '') == '%s' % (ID): times, flux, error, flags = fits.read_corot(catfile) data.append([times, flux, error, flags]) #-- now make a record array and sort according to times if not data: raise ValueError( 'target {0} not in offline CoRoT data repository'.format(ID)) data = np.hstack(data) data = np.rec.fromarrays(data, dtype=[('HJD', '>f8'), ('flux', '>f8'), ('e_flux', '>f8'), ('flag', 'i')]) sa = np.argsort(data['HJD']) return data[sa], header
def get_sismo_data(ID): """ Retrieve CoRoT timeseries from a local data repository. The output record array has fields 'HJD', 'flux', 'e_flux', 'flag'. @param ID: ID of the target: either an integer (CoRoT ID), an SIMBAD-recognised target name, or a valid CoRoT FITS file @type ID: int or str @return: data, header @rtype: numpy recarray, dict """ # -- data on one target can be spread over multiple files: collect the # data data = [] if isinstance(ID, str) and os.path.isfile(ID): header = pyfits.getheader(ID) times, flux, error, flags = fits.read_corot(ID) data.append([times, flux, error, flags]) else: # -- resolve the target's name: it's either a target name or CoRoT ID. try: ID = int(ID) except ValueError: info = sesame.search(ID, db="S") IDs = [alias for alias in info["alias"] if "HD" in alias] if len(IDs) != 1: logger.error("Data retrieval for %s not possible. Reason: no HD number resolved" % (ID)) return ID = IDs[0] # -- collect the files containing data on the target # catfiles = config.glob((os.sep).join(['catalogs','corot','sismo']),'*.fits') fn_sismo = os.path.join(cc.path.ivsdata, "catalogs", "corot", "sismo", "*.fits") catfiles = glob.glob(fn_sismo) catfiles.sort() for catfile in catfiles: try: header = pyfits.getheader(catfile) except IOError: continue if header["starname"] == ID or header["corotid"].replace(" ", "") == "%s" % (ID): times, flux, error, flags = fits.read_corot(catfile) data.append([times, flux, error, flags]) # -- now make a record array and sort according to times if not data: raise ValueError("target {0} not in offline CoRoT data repository".format(ID)) data = np.hstack(data) data = np.rec.fromarrays(data, dtype=[("HJD", ">f8"), ("flux", ">f8"), ("e_flux", ">f8"), ("flag", "i")]) sa = np.argsort(data["HJD"]) return data[sa], header
def galex(**kwargs): """ Cone search for Galex targets. """ ID = kwargs.pop('ID', None) if ID is None: ra, dec = kwargs.pop('ra'), kwargs.pop('dec') else: info = sesame.search(ID, db='A') if not 'jradeg' in info: return None, None, None ra, dec = info['jradeg'], info['jdedeg'] radius = 0.1 #radius = radius/60. base_url = 'http://galex.stsci.edu/gxws/conesearch/conesearch.asmx/ConeSearchToXml?ra={0:f}&dec={1:f}&sr={2:f}&verb=1'.format( ra, dec, radius) #base_url = 'http://galex.stsci.edu/GR4/?page=searchresults&RA={ra:f}&DEC={dec:f}&query=no'.format(ra=ra,dec=dec) url = urllib.URLopener() filen, msg = url.retrieve(base_url, filename=None) fuv_flux, e_fuv_flux = None, None columns = [ '_r', 'ra', 'dec', 'fuv_flux', 'fuv_fluxerr', 'nuv_flux', 'nuv_fluxerr' ] values = [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan] #flux in microJy units = dict(fuv_flux='muJy', nuv_flux='muJy') got_target = False with open(filen, 'r') as ff: for line in ff.readlines(): for i, col in enumerate(columns): if col + '>' in line: values[i] = np.float(line.split('>')[1].split('<')[0]) got_target = (col == 'fuv_fluxerr') if got_target: break values[0] = np.sqrt((values[1] - ra)**2 + (values[2] - dec)**2) * 3600 columns[1] = '_RAJ2000' columns[2] = '_DEJ2000' results = np.rec.fromarrays(np.array([values]).T, names=columns) if np.all(np.isnan(np.array(values))): results = None return results, units, None
def galex(**kwargs): """ Cone search for Galex targets. """ ID = kwargs.pop('ID',None) if ID is None: ra,dec = kwargs.pop('ra'),kwargs.pop('dec') else: info = sesame.search(ID,db='A') if not 'jradeg' in info: return None,None,None ra,dec = info['jradeg'],info['jdedeg'] radius = 0.1 #radius = radius/60. base_url = 'http://galex.stsci.edu/gxws/conesearch/conesearch.asmx/ConeSearchToXml?ra={0:f}&dec={1:f}&sr={2:f}&verb=1'.format(ra,dec,radius) #base_url = 'http://galex.stsci.edu/GR4/?page=searchresults&RA={ra:f}&DEC={dec:f}&query=no'.format(ra=ra,dec=dec) url = urllib.URLopener() filen,msg = url.retrieve(base_url,filename=None) fuv_flux,e_fuv_flux = None,None columns = ['_r','ra','dec','fuv_flux','fuv_fluxerr','nuv_flux','nuv_fluxerr'] values = [np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan] #flux in microJy units = dict(fuv_flux='muJy',nuv_flux='muJy') got_target = False with open(filen,'r') as ff: for line in ff.readlines(): for i,col in enumerate(columns): if col+'>' in line: values[i] = np.float(line.split('>')[1].split('<')[0]) got_target = (col=='fuv_fluxerr') if got_target: break values[0] = np.sqrt( (values[1]-ra)**2 + (values[2]-dec)**2)*3600 columns[1] = '_RAJ2000' columns[2] = '_DEJ2000' results = np.rec.fromarrays(np.array([values]).T,names=columns) if np.all(np.isnan(np.array(values))): results = None return results,units,None
def get_dss_image(ID,ra=None,dec=None,width=5,height=5): """ Retrieve an image from DSS plot with >>> data,coords,size = mast.get_image('HD21389') >>> pl.imshow(data[::-1],extent=[coords[0]-size[0]/2,coords[0]+size[0]/2, coords[1]-size[1]/2,coords[1]+size[1]/2]) """ #-- set a reasonable timeout timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(30.) if ra is None or dec is None: info = sesame.search(ID) ra,dec = info['jradeg'],info['jdedeg'] url = urllib.URLopener() myurl = "http://archive.stsci.edu/cgi-bin/dss_search?ra=%s&dec=%s&equinox=J2000&height=%s&generation=%s&width=%s&format=FITS"%(ra,dec,height,'2i',width) out = url.retrieve(myurl) data1 = pyfits.getdata(out[0]) #-- reset timeout to original value socket.setdefaulttimeout(timeout) return data1,(ra,dec),(width/60.,height/60.)
def get_dss_image(ID, ra=None, dec=None, width=5, height=5): """ Retrieve an image from DSS plot with >>> data,coords,size = mast.get_image('HD21389') >>> pl.imshow(data[::-1],extent=[coords[0]-size[0]/2,coords[0]+size[0]/2, coords[1]-size[1]/2,coords[1]+size[1]/2]) """ #-- set a reasonable timeout timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(30.) if ra is None or dec is None: info = sesame.search(ID) ra, dec = info['jradeg'], info['jdedeg'] url = urllib.URLopener() myurl = "http://archive.stsci.edu/cgi-bin/dss_search?ra=%s&dec=%s&equinox=J2000&height=%s&generation=%s&width=%s&format=FITS" % ( ra, dec, height, '2i', width) out = url.retrieve(myurl) data1 = pyfits.getdata(out[0]) #-- reset timeout to original value socket.setdefaulttimeout(timeout) return data1, (ra, dec), (width / 60., height / 60.)
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