1
2 """
3 Crossmatch catalogs for data on one target, or crossmatch entire catalogs.
4
5 This module is callable from the command line. E.g., simply type::
6
7 $:> python crossmatch.py get_photometry ID=HD180642
8
9 or ask for help on any function::
10
11 $:> python crossmatch.py get_photometry --help
12 """
13 import logging
14 import itertools
15 import pylab as pl
16 import numpy as np
17
18 from ivs.catalogs import vizier
19 from ivs.catalogs import gator
20 from ivs.catalogs import gcpd
21 from ivs.catalogs import mast
22 from ivs.catalogs import sesame
23 from ivs.units import conversions
24 from ivs.aux import numpy_ext
25 from ivs.aux import progressMeter
26 from ivs.aux import loggers
27 from ivs.aux import argkwargparser
28 from ivs.inout import ascii
29
30 from scipy.spatial import KDTree
31
32 logger = logging.getLogger("CAT.XMATCH")
33
34 -def get_photometry(ID=None,to_units='erg/s/cm2/AA',extra_fields=[],include=None,
35 exclude=None,**kwargs):
36 """
37 Collect photometry from different sources.
38
39 The output consists of a record array containing the following keys:
40
41 'meas': the measurement's value directly from the catalog in original units
42 'e_meas': the error on the measurements
43 'flag': any flags that are associated with the measurement in a catalog
44 'unit': the unit of the original measurement
45 'source' the source catalog's name
46 'photband': photometric pass bands' name
47 'cwave': the effective wavelength of the passband
48 'cmeas': converted measurement (to C{to_units})
49 'e_cmeas': error on converted measurment
50 'cunit': converted unit
51
52 Be aware that some of the values can be 'nan': e.g. sometimes no error is
53 listed in the catalog, or no flag. Also the 'cwave' column will be nan for
54 all photometric colours (e.g. B-V)
55
56 If you define C{extra_fields}, make sure all the {get_photometry} know how
57 to handle it: probably some default values need to be inserted if these
58 extra columns are not available in some catalog. It is safest just to leave
59 it blank.
60
61 You can include or exclude search sources via C{include} and C{exclude}.
62 When given, these should be a list containing strings. The default is to
63 include C{gator}, C{vizier} and C{gcpd}.
64
65 Extra keyword arguments are passed to each C{get_photometry} functions in
66 this package's modules.
67
68 Example usage:
69
70 1. You want to download all available photometry and write the results to
71 an ASCII file for later reference.
72
73 >>> master = get_photometry('vega')
74 >>> ascii.write_array(master,header=True,auto_width=True)
75
76 2. You want to plot the raw, unmodelled SED of an object:
77
78 >>> master = get_photometry('vega')
79 >>> pl.errorbar(master['cwave'],master['cmeas'],yerr=master['e_cmeas'],fmt='ko')
80 >>> pl.gca().set_xscale('log',nonposx='clip')
81 >>> pl.gca().set_yscale('log',nonposy='clip')
82
83 We made no difference between colors (B-V) and magnitude (V), because the
84 'cwave' for colors is 'nan', so they will not be plotted anyway.The final
85 two lines are just to correct errorbars that go below zero in a logarithmic
86 plot.
87
88 @param ID: the target's name, understandable by SIMBAD
89 @type ID: str
90 @param to_units: units to convert everything to.
91 @type to_units:
92 @param include: sources to include
93 @type include: list of strings (from C{gator}, C{vizier} or C{gcpd})
94 @param exclude: sources to include
95 @type exclude: list of strings (from C{gator}, C{vizier} or C{gcpd})
96 @return: record array where eacht entry is a photometric measurement
97 @rtype: record array
98 """
99
100 if include is not None: include = [i.lower() for i in include]
101 if exclude is not None: exclude = [i.lower() for i in exclude]
102
103
104 searchables = ['gator','vizier','gcpd','mast']
105 if include is not None:
106 searchables = include
107 if exclude is not None:
108 searchables = list( set(searchables)- set(exclude))
109
110
111 if 'mast' in searchables:
112 kwargs['master'] = mast.get_photometry(ID=ID,to_units=to_units,extra_fields=extra_fields,**kwargs)
113 if 'gator' in searchables:
114 kwargs['master'] = gator.get_photometry(ID=ID,to_units=to_units,extra_fields=extra_fields,**kwargs)
115 if 'vizier' in searchables:
116
117 info = sesame.search(ID=ID,fix=True)
118 if 'alias' in info:
119 HDnumber = [name for name in info['alias'] if name[:2]=='HD']
120 if HDnumber:
121 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)
122
123 results,units,comms = vizier.search('J/A+A/380/609/table1',ID=ID)
124 if results is not None:
125 catname = results[0]['Name'].strip()
126 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)
127
128 kwargs['master'] = vizier.get_photometry(ID=ID,to_units=to_units,extra_fields=extra_fields,**kwargs)
129
130
131 if 'gcpd' in searchables:
132 kwargs['master'] = gcpd.get_photometry(ID=ID,to_units=to_units,extra_fields=extra_fields,**kwargs)
133 master = kwargs['master']
134
135
136 photbands = [phot.split('.')[0] for phot in master['photband']]
137 contents = [(i,photbands.count(i)) for i in sorted(list(set(photbands)))]
138 for phot in contents:
139 logger.info('%10s: found %d measurements'%phot)
140 return master
141
143 """
144 Add bibcodes to a master record.
145
146 @param master: master record of photometry
147 @type master: numpy record array
148 @return: master record of photometry with additional column
149 @rtype: numpy record array
150 """
151 bibcodes = []
152 for source in master['source']:
153 bibcodes.append('None')
154
155 if source.count('/')>=2:
156
157
158 if 'bibcode' in vizier.cat_info.options(source):
159 bibcodes[-1] = vizier.cat_info.get(source,'bibcode')
160
161 else:
162 bibcodes[-1] = vizier.catalog2bibcode(source)
163 elif source=='GCPD':
164 bibcodes[-1] = '1997A&AS..124..349M'
165 elif source in gator.cat_info.sections():
166 if 'bibcode' in gator.cat_info.options(source):
167 bibcodes[-1] = gator.cat_info.get(source,'bibcode')
168 elif source in mast.cat_info.sections():
169 if 'bibcode' in mast.cat_info.options(source):
170 bibcodes[-1] = mast.cat_info.get(source,'bibcode')
171 if bibcodes[-1]=='None' or bibcodes[-1] is None:
172 logger.info('Bibcode of source {0:25s} not found'.format(source))
173 bibcodes = np.array(bibcodes,str)
174 bibcodes = np.rec.fromarrays([bibcodes],names=['bibcode'])
175 return numpy_ext.recarr_join(master,bibcodes)
176
177
179 """
180 Make a bib file from a master record
181 """
182 bibcodes = sorted(set(list(master['bibcode'])))
183 with open(filename,'w') as ff:
184 ff.write('% \citet{{{0}}}\n\n\n'.format(','.join(bibcodes)))
185 for bibcode in bibcodes:
186 try:
187 ff.write(vizier.bibcode2bibtex(bibcode)+'\n')
188 except IOError:
189 logger.info('Error retrieving bibtex for {0}'.format(bibcode))
190
191
192
193
194
196 """
197 Crossmatch two sets of coordinates.
198 """
199 tree = KDTree(coords1)
200 distance,order = tree.query(coords2)
201
202 match_success = distance<(tol/(60.))
203
204
205
206
207
208
209
210
211
212
213
214
215
216 return (order[match_success],match_success),(order[-match_success],-match_success)
217
219 """
220 String representation of master record array
221
222 @param master: master record array containing photometry
223 @type master: numpy record array
224 """
225 master = master[np.argsort(master['photband'])]
226 txt = '#%19s %12s %12s %12s %10s %12s %12s %11s %s\n'%('PHOTBAND','MEAS','E_MEAS','UNIT','CWAVE','CMEAS','E_CMEAS','UNIT','SOURCE')
227 txt+= '#=========================================================================================================================\n'
228 for i,j,k,l,m,n,o,p in zip(master['photband'],master['meas'],master['e_meas'],master['unit'],master['cwave'],master['cmeas'],master['e_cmeas'],master['source']):
229 txt+='%20s %12g %12g %12s %10.0f %12g %12g erg/s/cm2/AA %s\n'%(i,j,k,l,m,n,o,p)
230 return txt
231
232 if __name__=="__main__":
233 logger = loggers.get_basic_logger()
234
235 method,args,kwargs = argkwargparser.parse()
236 print_help = '--help' in args or '-h' in args
237 if print_help:
238 help(globals()[method])
239 else:
240 master = globals()[method](*args,**kwargs)
241 print photometry2str(master)
242
243
244
245
246