def plot_targets_and_imacs_fov(host, camera='short', offset=(0, 0), clf=True, **kwargs): """ Plots the targets for the requested host and the IMACS FOV on top Parameters ---------- host : NSAHost The host to camera : str The camera to make the FOV box for: 'short' (f/2) or 'long' (f/4) offset : 2-tuple RA/Dec offset from the host in arcmin kwargs are passed into `select_targets` """ import targeting if camera == 'short': fov = 27.20 fovrad = 36.4 elif camera == 'long': fov = 15.46 fovrad = None else: raise ValueError('unrecognized camera "{0}"'.format(camera)) targets = targeting.select_targets(host, **kwargs) dra = (targets['ra'] - host.ra) * 60 * np.cos(np.radians(targets['dec'])) ddec = (targets['dec'] - host.dec) * 60 if clf: plt.clf() plt.plot(dra, ddec, '.', ms=1) xcorners = [offset[0] - fov / 2, offset[0] + fov / 2] xcorners = [ xcorners[0], xcorners[1], xcorners[1], xcorners[0], xcorners[0] ] ycorners = [offset[1] - fov / 2, offset[1] + fov / 2] ycorners = [ ycorners[1], ycorners[1], ycorners[0], ycorners[0], ycorners[1] ] plt.plot(xcorners, ycorners, 'k-')
def count_targets(hsts, verbose=True, remove_cached=True, rvir=300, targetingkwargs={}): """ Generates a count of targets for each field. Parameters ---------- hsts A list of `NSAHost` objects verbose : bool Whether or not to print a message when each host is examined remove_cached : bool Whether or not to remove the cached sdss catalog for each host after counting. This may be necessary to prevent running out of memory, depending on the number of hosts involved. rvir : float "virial radius" in kpc for the arcmin transform targetingkwargs : dict or list of dicts passed into ` targeting.select_targets` if a single dictionary, otherwise the targeting will Returns ------- ntargs : astropy.Table a table object with the names of the hosts and the target counts. """ import sys import collections from astropy import table if isinstance(targetingkwargs, collections.Mapping): colnames = ['ntarg'] targetingkwargs = [targetingkwargs.copy()] else: colnames = [('ntarg_' + t.get('colname', str(i))) for i, t in enumerate(targetingkwargs)] targetingkwargs = [t.copy() for t in targetingkwargs] for t in targetingkwargs: t.setdefault('outercutrad', 300) t.setdefault('removegama', False) if 'colname' in t: del t['colname'] nms = [] dists = [] rvs = [] cnts = [[] for t in targetingkwargs] for i, h in enumerate(hsts): if verbose: print 'Generating target count for', h.name, '#', i + 1, 'of', len( hsts) sys.stdout.flush() nms.append(h.name) dists.append(h.distmpc) rvs.append(h.physical_to_projected(300)) for j, t in enumerate(targetingkwargs): if verbose: print 'Targeting parameters:', t sys.stdout.flush() tcat = targeting.select_targets(h, **t) cnts[j].append(len(tcat)) if remove_cached: h._cached_sdss = None t = table.Table() t.add_column(table.Column(name='name', data=nms)) t.add_column(table.Column(name='distmpc', data=dists, units='Mpc')) t.add_column(table.Column(name='rvirarcmin', data=rvs, units='arcmin')) for cnm, cnt in zip(colnames, cnts): t.add_column(table.Column(name=cnm, data=cnt)) return t
def count_targets(hsts, verbose=True, remove_cached=True, rvir=300, targetingkwargs={}): """ Generates a count of targets for each field. Parameters ---------- hsts A list of `NSAHost` objects verbose : bool Whether or not to print a message when each host is examined remove_cached : bool Whether or not to remove the cached sdss catalog for each host after counting. This may be necessary to prevent running out of memory, depending on the number of hosts involved. rvir : float "virial radius" in kpc for the arcmin transform targetingkwargs : dict or list of dicts passed into ` targeting.select_targets` if a single dictionary, otherwise the targeting will Returns ------- ntargs : astropy.Table a table object with the names of the hosts and the target counts. """ import sys import collections from astropy import table if isinstance(targetingkwargs, collections.Mapping): colnames = ['ntarg'] targetingkwargs = [targetingkwargs.copy()] else: colnames = [('ntarg_' + t.get('colname', str(i))) for i, t in enumerate(targetingkwargs)] targetingkwargs = [t.copy() for t in targetingkwargs] for t in targetingkwargs: t.setdefault('outercutrad', 300) t.setdefault('removegama', False) if 'colname' in t: del t['colname'] nms = [] dists = [] rvs = [] cnts = [[] for t in targetingkwargs] for i, h in enumerate(hsts): if verbose: print 'Generating target count for', h.name, '#', i + 1, 'of', len(hsts) sys.stdout.flush() nms.append(h.name) dists.append(h.distmpc) rvs.append(h.physical_to_projected(300)) for j, t in enumerate(targetingkwargs): if verbose: print 'Targeting parameters:', t sys.stdout.flush() tcat = targeting.select_targets(h, **t) cnts[j].append(len(tcat)) if remove_cached: h._cached_sdss = None t = table.Table() t.add_column(table.Column(name='name', data=nms)) t.add_column(table.Column(name='distmpc', data=dists, units='Mpc')) t.add_column(table.Column(name='rvirarcmin', data=rvs, units='arcmin')) for cnm, cnt in zip(colnames, cnts): t.add_column(table.Column(name=cnm, data=cnt)) return t
def make_catalog(host, fnout=None, targetfaintlim=(21.,22.), targetoutercutrad=300, fluxrng=(17., 17.7), repeatflux=1, guidestarmagrng= (14, 15), removegalsathighz=False, inclspecqsos=True, removespecstars=False, fibermag_faintlimit=(22., 23.), fibermag_brightlimit=17, fibermag_type='fibermag_r', useoutertargets=False): """ Generates a catalog for the Hectospec "XFITFIBS" program. `targetfaintlim` can be just a mag to make everything "primary", or a 2-tuple that is (prisecboundary, faintestsec) `useoutertargets` means include targets beyond `targetoutercutrad`, but with a rank below where they would usually be Writes catalog to `fnout` if `fnout` is not None Returns the catalog as a `Table` `fibermag_faintlimit` is a lower limit *or* a two-tuple of limits for primary and secondary targets (secondary ignored if `targetfainlim` is just a single number) can also be None (`fibermag_brightlimit` can also be None) """ fluxrank = 1 hostrank = 2 prisatrank = 3 secsatrank = 5 if useoutertargets else 4 #the outer primaries get 4 if `useoutertargets` is True #add the host as the first entry rastr = Angle(host.ra, 'deg').to_string('hr', sep=':', precision=3) decstr = Angle(host.dec, 'deg').to_string('deg', sep=':', precision=3) mag = '{0:.2f}'.format(host.r + host.distmod) tabentries.append([rastr, decstr, host.name, str(hostrank), 'TARGET', mag]) catlines.append('\t'.join(tabentries[-1])) try: prisecbounday, seclimit = targetfaintlim except TypeError: prisecbounday = seclimit = targetfaintlim if useoutertargets: targs = targeting.select_targets(host, faintlimit=seclimit, outercutrad=None, innercutrad=20, removegalsathighz=removegalsathighz, removespecstars=removespecstars, inclspecqsos=inclspecqsos) if targetoutercutrad < 0: # arcmin outercutraddeg = -targetoutercutrad / 60. else: # kpc outercutraddeg = np.degrees(targetoutercutrad / (1000 * host.distmpc)) outermsk = targs['rhost'] > outercutraddeg #just used for counting purposes else: targs = targeting.select_targets(host, faintlimit=seclimit, outercutrad=targetoutercutrad, removegalsathighz=removegalsathighz, removespecstars=removespecstars, inclspecqsos=inclspecqsos) outermsk = None print('Found', len(targs), 'targets') if outermsk is not None: print((~outermsk).sum(), 'are in the inner zone') if prisecbounday != seclimit: print(np.sum(targs['r'] < prisecbounday), 'Primaries and',np.sum((targs['r'] > prisecbounday) & (targs['r'] < seclimit)),'Secondaries') if outermsk is not None: inrtargs = targs[~outermsk] print(np.sum(inrtargs['r'] < prisecbounday), 'Primaries and',np.sum((inrtargs['r'] > prisecbounday) & (inrtargs['r'] < seclimit)),'Secondaries are in the inner zone') if fibermag_faintlimit is not None: try: prifiberlimit, secfiberlimit = fibermag_faintlimit except TypeError: prifiberlimit = secfiberlimit = fibermag_faintlimit fibmag = targs[fibermag_type] #filter things that have faint fiber mags in the primary targets primsk = (targs['r'] < prisecbounday) & (fibmag < prifiberlimit) #filter things that have faint fiber mags in the secondart targets secmsk = (targs['r'] > prisecbounday) & (targs['r'] < seclimit) & (fibmag < secfiberlimit) print('Accepting', primsk.sum(), 'primary targets and', secmsk.sum(), 'secondaries according to fiber faint limit') targs = targs[primsk | secmsk] if fibermag_brightlimit is not None: msk = targs[fibermag_type] > fibermag_brightlimit targs = targs[msk] print('Filtering', msk.sum(), ' targets due to fiber bright limit') targranks = [] for t in targs: targranks.append(prisatrank if t['r'] < prisecbounday else secsatrank) if t['rhost'] > outercutraddeg: targranks[-1] += 1 targranks = np.array(targranks) return generate_catalog(host, targs, targranks, fluxrng=fluxrng, repeatflux=repeatflux, fluxrank=fluxrank, guidestarmagrng=guidestarmagrng, fnout=fnout)
for h in hs.values(): print 'on',h.name sys.stdout.flush() ds[h.name] = h.distmpc h.fnsdss = 'saga_catalogs/'+h.name+'.dat' #tcat=targeting.select_targets(h,outercutrad=300) #cnts[h.name] = len(tcat) h cnts={} ds={} for h in hs.values(): print 'on',h.name sys.stdout.flush() ds[h.name] = h.distmpc h.fnsdss = 'saga_catalogs/'+h.name+'.dat' tcat=targeting.select_targets(h,outercutrad=300) cnts[h.name] = len(tcat) h0=hs.values()[0] h0._cached_sdss h0._cached_sdss; cnts={} ds={} for h in hs.values(): print 'on',h.name sys.stdout.flush() ds[h.name] = h.distmpc h.fnsdss = 'saga_catalogs/'+h.name+'.dat' tcat=targeting.select_targets(h,outercutrad=300) cnts[h.name] = len(tcat) h._cached_sdss = None cnts={}
def construct_master_catalog(host, fnout=None, targetcat={}, fopcat=None, skyradec=None, faintlimit=None, fibermaglimit=None, orderby=None, usnosdssoffsettol=0.5): """ This function produces the "master" catalog for each host for WIYN/hydra observations. The master catalog contains lines for all the objects/sky/fops and potential targets. It is laid out such that the rows can simply be extracted as-is for .ast files for input to WIYN's `whydra` program. Parameters ---------- host : NSAHost the host object to use to construct this catalog. Note that SDSS and USNO data must be already downloaded for this host. fnout : str or None The filename to save as the master catalog or None to use a default based on the host's name targetcat : str or dict The catalog of targets or a dict to use `targeting.select_targets` to generate one (the dict is used as the kwargs). fopcat : str or None The catalog of FOP stars or None to use the default options to generate one. skyradec : 2xN array or None (ra, dec) for locations of sky fibers or if None, will use `select_sky_positions` to find good sky fiber locations. faintlimit : float or None The faint-end cutoff for r-band magnitudes in the target catalog, or None to have no cutoff fibermaglimit : float or None The faint-end cutoff for fiber2mag_r in the target catalog, or None to have no cutoff orderby: str or list of str Order the target list in order by field(2) in the target catalog. If prefixed with '-', it's in *decreasing* order, otherwise increasing (i.e., without '-', smallest number first). The special 'lowphotz' means to change order to blocks of [photz<.1, nophotz, photz>.1] usnosdssoffsettol : float The number of arcseconds median offset acceptable between the SDSS and USNO-B frames Returns ------- targetcat The catalog of targets used to generate the object list """ import os from collections import Mapping from targeting import usno_vs_sdss_offset, select_targets if fnout is None: fnout = os.path.join('hydra_targets', host.name + '.cat') if isinstance(targetcat, Mapping): if faintlimit is not None: if 'faintlimit' in targetcat: raise ValueError( 'cannot give both faintlimit kwarg and in targetcat dict') targetcat['faintlimit'] = faintlimit targetcat = select_targets(host, **targetcat) elif faintlimit is not None: #do the faintlimit cut manually if not using `select_targets` targetcat = targetcat[targetcat['r'] < faintlimit] if fibermaglimit is not None: fmsk = targetcat['fiber2mag_r'] < fibermaglimit print('Fiber mag cut removes', np.sum(~fmsk), 'of', len(fmsk), 'objects') targetcat = targetcat[fmsk] print(len(targetcat), 'objects') if fopcat is None: fopcat = select_fops(host) print(len(fopcat), 'FOPS') if skyradec is None: skyradec = select_sky_positions(host) if orderby: if isinstance(orderby, six.string_types): orderby = [orderby] for field in orderby: if field == 'lowphotz': pz = targetcat['photz'] highz = np.where(pz > .1)[0] lowz = np.where((-1 < pz) & (pz < .1))[0] noz = np.where(pz == -1)[0] print('Found {0} objects at low photz, {1} at high, and {2} ' 'without photz'.format(len(lowz), len(highz), len(noz))) sorti = np.concatenate([lowz, noz, highz]) elif field.startswith('-'): sorti = np.argsort(targetcat[field[1:]])[::-1] else: sorti = np.argsort(targetcat[field]) targetcat = targetcat[sorti] if len(targetcat) > 1999: # 1999 because the central object also gets one print('whydra cannot handle > 2000 objects, truncating') targetcat = targetcat[:1999] if len(fopcat) > 2000: print('whydra cannot handle > 2000 FOPS, truncating') fopcat = fopcat[:2000] if len(skyradec[0]) > 2000: print('whydra cannot handle > 2000 sky points, truncating') skyradec = skyradec[0][:2000], skyradec[1][:2000] #determine the SDSS vs. USNO offset dra, ddec = usno_vs_sdss_offset(host.get_sdss_catalog(), host.get_usnob_catalog(), raiseerror=usnosdssoffsettol) print('USNO/SDSS offsets:', dra * 3600, ddec * 3600) if os.path.exists(fnout): raise ValueError( 'File for generating master catalog {0} already exists!'.format( fnout)) print('Constucting catalog in', fnout) with open(fnout, 'w') as fw: #first add host as center, and as object fw.write( _whydra_file_line(0001, 'Center'.format(host.nsaid), host.ra, host.dec, 'C')) fw.write('\n') fw.write( _whydra_file_line(1000, 'NSA{0}'.format(host.nsaid), host.ra, host.dec, 'O')) fw.write('\n') i = 2000 for obj in targetcat: ln = _whydra_file_line(i, 'SDSS', obj['ra'], obj['dec'], 'O') i += 1 fw.write(ln) fw.write(' # mag_r={0:.2f}'.format(obj['r'])) fw.write('\n') i = 5000 for fop in fopcat: ln = _whydra_file_line(i, 'USNO' + fop['id'], fop['RA'] - dra, fop['DEC'] - ddec, 'F') fw.write(ln) fw.write(' # mag_R2={0:.2f}'.format(fop['R2'])) i += 1 fw.write('\n') i = 8000 j = 1 for skyra, skydec in zip(*skyradec): ln = _whydra_file_line(i, 'sky{0}'.format(j), skyra, skydec, 'S') fw.write(ln) i += 1 j += 1 fw.write('\n') return targetcat
for h in hs.values(): print 'on', h.name sys.stdout.flush() ds[h.name] = h.distmpc h.fnsdss = 'saga_catalogs/' + h.name + '.dat' #tcat=targeting.select_targets(h,outercutrad=300) #cnts[h.name] = len(tcat) h cnts = {} ds = {} for h in hs.values(): print 'on', h.name sys.stdout.flush() ds[h.name] = h.distmpc h.fnsdss = 'saga_catalogs/' + h.name + '.dat' tcat = targeting.select_targets(h, outercutrad=300) cnts[h.name] = len(tcat) h0 = hs.values()[0] h0._cached_sdss h0._cached_sdss cnts = {} ds = {} for h in hs.values(): print 'on', h.name sys.stdout.flush() ds[h.name] = h.distmpc h.fnsdss = 'saga_catalogs/' + h.name + '.dat' tcat = targeting.select_targets(h, outercutrad=300) cnts[h.name] = len(tcat) h._cached_sdss = None cnts = {}
def build_imacs_targeting_files(host, observername, date=None, onlygals=True, refmagrange={'r': (17, 19)}, overwrite=False, selectkws={}, targs=None, pdecide=None, weakdlimit=False, inclhost=True): """ Generates the target catalog and initial observation file for IMACS Parameters ---------- host : NSAHost The host to target observername : str The name of the observer (for the .obs file) date : str The data of the observation - should be parsable by `astropy.time.Time` onlygals : bool If True, only generate targets that SDSS calls galaxies refmagrange: dict of 2-tuples. Magnitude range for reference stars - dict keys are band. http://www.lco.cl/telescopes-information/magellan/instruments/imacs/user-manual/the-imacs-user-manual#prepobs suggests 17 < R< 19. overwrite : bool If True, existing files will be overwritten. Otherwise, an error will be raised if the files are present. selectkws : dict Keywords to be passed into `targeting.select_targets` targs : astropy.table.Table The target list to use. If given, will override `selectkws` and `targeting.select_targets` will be ignored. Format should be the same as `targeting.select_targets`'s output - needs to have 'objID, 'type', 'ra', 'dec', and 'r'. If the column 'imacs_pri' is present, that will be included as a priority for the object pdecide : float or None The priority to use as 'PDECIDE', or None to go with the default weakdlimit : bool If True, set the 'DLIMIT' such that only the center wl (6750) is forced to be on the detector. inclhost : bool If True, always add a (priority 0) target for the host. """ import os import targeting from astropy.coordinates import Angle from astropy.time import Time from astropy import units as u if targs is None: targs = targeting.select_targets(host, **selectkws) elif selectkws: raise ValueError('Cannot give both `targs` and `selectkws` arguments') cat = host.get_sdss_catalog() # needed for ref stars if onlygals: if 'type' in targs.colnames: galmsk = targs['type'] == 3 targs = targs[galmsk] else: print( 'onlygals was set, but no "type" in the catalog. Not cutting.' ) refmsk = np.ones(len(cat), dtype=bool) for band in 'gri': refmsk & (np.abs(cat[band] - cat['psf_' + band]) < 0.25) for band, rng in refmagrange.items(): refmsk = refmsk & (min(rng) < cat['psf_' + band]) & (cat['psf_' + band] < max(rng)) fncat = 'imacs_targets/{0}.cat'.format(host.shortname) fnobs = 'imacs_targets/{0}_ini.obs'.format(host.shortname) if not overwrite: if os.path.exists(fncat): if os.path.exists(fnobs): raise IOError( 'Object catalog and obs file ("{0}" and "{1}") already exist!' .format(fncat, fnobs)) else: raise IOError( 'Object catalog ({0}) already exists!'.format(fncat)) elif os.path.exists(fnobs): raise IOError( 'Observation file ({0}) already exists!'.format(fnobs)) with open(fncat, 'w') as f: f.write('&RADEGREE\n') if inclhost: f.write('@{0} {1} {2} -10 Pri=0\n'.format(host.name, host.ra, host.dec)) if 'imacs_pri' in targs.colnames: for t in targs: f.write('@{0} {1} {2} {3} Pri={4}\n'.format( *[t[n] for n in 'objID,ra,dec,r,imacs_pri'.split(',')])) else: for t in targs: f.write('@{0} {1} {2} {3}\n'.format( *[t[n] for n in 'objID,ra,dec,r'.split(',')])) #now the reference stars for t in cat[refmsk]: f.write('*{0} {1} {2} #r={3}\n'.format( *[t[n] for n in 'objID,ra,dec,r'.split(',')])) print('Wrote catalog to', fncat) hra = Angle(host.ra, u.degree) hdec = Angle(host.dec, u.degree) obsmjd = int(Time(date, scale='utc').mjd) obsfile = _obsfile_template.format( title=host.shortname + '_ini', cenra=hra.to_string(u.hour, precision=3, sep=':', pad=True), cendec=hdec.to_string(u.degree, precision=2, sep=':', pad=True), observer=observername, obsmjd=obsmjd, catfile=host.shortname + '.cat', pdecide='' if pdecide is None else ('\nPDECIDE {0:.2f}'.format(pdecide)), dlimit='\nDLIMIT 5000 7500' if weakdlimit else '') with open(fnobs, 'w') as f: f.write(obsfile) print('Wrote obs file to', fnobs)
def construct_master_catalog(host, fnout=None, targetcat={}, fopcat=None, skyradec=None, faintlimit=None, fibermaglimit=None, orderby=None, usnosdssoffsettol=0.5): """ This function produces the "master" catalog for each host for WIYN/hydra observations. The master catalog contains lines for all the objects/sky/fops and potential targets. It is laid out such that the rows can simply be extracted as-is for .ast files for input to WIYN's `whydra` program. Parameters ---------- host : NSAHost the host object to use to construct this catalog. Note that SDSS and USNO data must be already downloaded for this host. fnout : str or None The filename to save as the master catalog or None to use a default based on the host's name targetcat : str or dict The catalog of targets or a dict to use `targeting.select_targets` to generate one (the dict is used as the kwargs). fopcat : str or None The catalog of FOP stars or None to use the default options to generate one. skyradec : 2xN array or None (ra, dec) for locations of sky fibers or if None, will use `select_sky_positions` to find good sky fiber locations. faintlimit : float or None The faint-end cutoff for r-band magnitudes in the target catalog, or None to have no cutoff fibermaglimit : float or None The faint-end cutoff for fiber2mag_r in the target catalog, or None to have no cutoff orderby: str or list of str Order the target list in order by field(2) in the target catalog. If prefixed with '-', it's in *decreasing* order, otherwise increasing (i.e., without '-', smallest number first). The special 'lowphotz' means to change order to blocks of [photz<.1, nophotz, photz>.1] usnosdssoffsettol : float The number of arcseconds median offset acceptable between the SDSS and USNO-B frames Returns ------- targetcat The catalog of targets used to generate the object list """ import os from collections import Mapping from targeting import usno_vs_sdss_offset, select_targets if fnout is None: fnout = os.path.join('hydra_targets', host.name + '.cat') if isinstance(targetcat, Mapping): if faintlimit is not None: if 'faintlimit' in targetcat: raise ValueError('cannot give both faintlimit kwarg and in targetcat dict') targetcat['faintlimit'] = faintlimit targetcat = select_targets(host, **targetcat) elif faintlimit is not None: #do the faintlimit cut manually if not using `select_targets` targetcat = targetcat[targetcat['r'] < faintlimit] if fibermaglimit is not None: fmsk = targetcat['fiber2mag_r'] < fibermaglimit print('Fiber mag cut removes', np.sum(~fmsk), 'of', len(fmsk), 'objects') targetcat = targetcat[fmsk] print(len(targetcat), 'objects') if fopcat is None: fopcat = select_fops(host) print(len(fopcat), 'FOPS') if skyradec is None: skyradec = select_sky_positions(host) if orderby: if isinstance(orderby, six.string_types): orderby = [orderby] for field in orderby: if field=='lowphotz': pz = targetcat['photz'] highz = np.where(pz > .1)[0] lowz = np.where((-1 < pz)&(pz < .1))[0] noz = np.where(pz==-1)[0] print('Found {0} objects at low photz, {1} at high, and {2} ' 'without photz'.format(len(lowz), len(highz), len(noz))) sorti = np.concatenate([lowz, noz, highz]) elif field.startswith('-'): sorti = np.argsort(targetcat[field[1:]])[::-1] else: sorti = np.argsort(targetcat[field]) targetcat = targetcat[sorti] if len(targetcat) > 1999: # 1999 because the central object also gets one print('whydra cannot handle > 2000 objects, truncating') targetcat = targetcat[:1999] if len(fopcat) > 2000: print('whydra cannot handle > 2000 FOPS, truncating') fopcat = fopcat[:2000] if len(skyradec[0]) > 2000: print('whydra cannot handle > 2000 sky points, truncating') skyradec = skyradec[0][:2000], skyradec[1][:2000] #determine the SDSS vs. USNO offset dra, ddec = usno_vs_sdss_offset(host.get_sdss_catalog(), host.get_usnob_catalog(), raiseerror=usnosdssoffsettol) print('USNO/SDSS offsets:', dra * 3600, ddec * 3600) if os.path.exists(fnout): raise ValueError('File for generating master catalog {0} already exists!'.format(fnout)) print('Constucting catalog in', fnout) with open(fnout, 'w') as fw: #first add host as center, and as object fw.write(_whydra_file_line(0001, 'Center'.format(host.nsaid), host.ra, host.dec, 'C')) fw.write('\n') fw.write(_whydra_file_line(1000, 'NSA{0}'.format(host.nsaid), host.ra, host.dec, 'O')) fw.write('\n') i = 2000 for obj in targetcat: ln = _whydra_file_line(i, 'SDSS', obj['ra'], obj['dec'], 'O') i += 1 fw.write(ln) fw.write(' # mag_r={0:.2f}'.format(obj['r'])) fw.write('\n') i = 5000 for fop in fopcat: ln = _whydra_file_line(i, 'USNO' + fop['id'], fop['RA'] - dra, fop['DEC'] - ddec, 'F') fw.write(ln) fw.write(' # mag_R2={0:.2f}'.format(fop['R2'])) i += 1 fw.write('\n') i = 8000 j = 1 for skyra, skydec in zip(*skyradec): ln = _whydra_file_line(i, 'sky{0}'.format(j), skyra, skydec, 'S') fw.write(ln) i += 1 j += 1 fw.write('\n') return targetcat