def getPositionAtTime(self, t): from astrometry.util.starutil_numpy import radectoxyz, arcsecperrad, axistilt, xyztoradec dt = (t - self.epoch).toYears() # Assume "pos" is an RaDecPos p = self.pos + dt * self.pm suntheta = t.getSunTheta() # print 'dt', dt, 'pos', self.pos, 'pm', self.pm, 'dt*pm:', dt * self.pm # print 'p0: (%.8f, %.8f)' % (self.pos.ra, self.pos.dec) # print 'p1: (%.8f, %.8f)' % (p.ra, p.dec) xyz = radectoxyz(p.ra, p.dec) xyz = xyz[0] # d(celestial coords)/d(parallax) # - takes numerical derivatives when it could take analytic ones # output is in [degrees / arcsec]. Yep. Crazy but true. # HACK: fmods dRA when it should do something continuous. # rd2xyz(0,0) is a unit vector; 1/arcsecperrad is (a good approximation to) # the distance on the unit sphere spanned by an angle of 1 arcsec. # We take a step of that length and return the change in RA,Dec. # It's about 1e-5 so we don't renormalize the xyz unit vector. dxyz1 = radectoxyz(0., 0.) / arcsecperrad dxyz1 = dxyz1[0] # - imprecise angle of obliquity # - implicitly assumes circular orbit # output is in [degrees / arcsec]. Yep. Crazy but true. dxyz2 = radectoxyz(90., axistilt) / arcsecperrad dxyz2 = dxyz2[0] xyz += self.parallax.getValue() * (dxyz1 * np.cos(suntheta) + dxyz2 * np.sin(suntheta)) r,d = xyztoradec(xyz) return RaDecPos(r,d)
def match_kdtree_catalog(wcs, catfn): from astrometry.libkd.spherematch import ( tree_open, tree_close, tree_build_radec, tree_free, trees_match, tree_permute, ) from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys rc, dc = wcs.get_center() rr = wcs.get_radius() kd = tree_open(catfn) kd2 = tree_build_radec(np.array([rc]), np.array([dc])) r = deg2dist(rr) I, J, nil = trees_match(kd, kd2, r, permuted=False) # HACK # I2,J,d = trees_match(kd, kd2, r) xyz = spherematch_c.kdtree_get_positions(kd, I.astype(np.uint32)) # print 'I', I I2 = tree_permute(kd, I) # print 'I2', I2 tree_free(kd2) tree_close(kd) tra, tdec = xyztoradec(xyz) return tra, tdec, I2
def cat_sdss(req, ver): import json import numpy as np from astrometry.util.starutil_numpy import degrees_between, radectoxyz, xyztoradec from map.views import sdss_ccds_near from astrometry.util.fits import fits_table, merge_tables tag = 'sdss-cat' ralo = float(req.GET['ralo']) rahi = float(req.GET['rahi']) declo = float(req.GET['declo']) dechi = float(req.GET['dechi']) ver = int(ver) if not ver in catversions[tag]: raise RuntimeError('Invalid version %i for tag %s' % (ver, tag)) rad = degrees_between(ralo, declo, rahi, dechi) / 2. xyz1 = radectoxyz(ralo, declo) xyz2 = radectoxyz(rahi, dechi) xyz = (xyz1 + xyz2) xyz /= np.sqrt(np.sum(xyz**2)) rc,dc = xyztoradec(xyz) rad = rad + np.hypot(10.,14.)/2./60. ccds = sdss_ccds_near(rc[0], dc[0], rad) if ccds is None: print('No SDSS CCDs nearby') return HttpResponse(json.dumps(dict(rd=[])), content_type='application/json') print(len(ccds), 'SDSS CCDs') T = [] for ccd in ccds: # env/BOSS_PHOTOOBJ/301/2073/3/photoObj-002073-3-0088.fits fn = os.path.join(settings.SDSS_BASEDIR, 'env', 'BOSS_PHOTOOBJ', str(ccd.rerun), str(ccd.run), str(ccd.camcol), 'photoObj-%06i-%i-%04i.fits' % (ccd.run, ccd.camcol, ccd.field)) print('Reading', fn) T.append(fits_table(fn, columns='ra dec objid mode objc_type objc_flags objc_flags nchild tai expflux devflux psfflux cmodelflux fracdev mjd'.split())) T = merge_tables(T) T.cut((T.dec >= declo) * (T.dec <= dechi)) # FIXME T.cut((T.ra >= ralo) * (T.ra <= rahi)) # primary T.cut(T.mode == 1) types = ['P' if t == 6 else 'C' for t in T.objc_type] fluxes = [p if t == 6 else c for t,p,c in zip(T.objc_type, T.psfflux, T.cmodelflux)] return HttpResponse(json.dumps(dict( rd=[(float(o.ra),float(o.dec)) for o in T], sourcetype=types, fluxes = [dict(u=float(f[0]), g=float(f[1]), r=float(f[2]), i=float(f[3]), z=float(f[4])) for f in fluxes], )), content_type='application/json')
def match_kdtree_catalog(wcs, catfn): from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match, tree_permute from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys rc,dc = wcs.get_center() rr = wcs.get_radius() kd = tree_open(catfn) kd2 = tree_build_radec(np.array([rc]), np.array([dc])) r = deg2dist(rr) I,J,nil = trees_match(kd, kd2, r, permuted=False) del kd2 xyz = kd.get_data(I.astype(np.uint32)) I = kd.permute(I) del kd tra,tdec = xyztoradec(xyz) return tra, tdec, I
def cat_kd(req, ver, tag, fn): tag = 'spec' ralo = float(req.GET['ralo']) rahi = float(req.GET['rahi']) declo = float(req.GET['declo']) dechi = float(req.GET['dechi']) ver = int(ver) if not ver in catversions[tag]: raise RuntimeError('Invalid version %i for tag %s' % (ver, tag)) import numpy as np from astrometry.util.fits import fits_table, merge_tables from astrometry.libkd.spherematch import tree_open, tree_search_radec from astrometry.util.starutil_numpy import radectoxyz, xyztoradec, degrees_between xyz1 = radectoxyz(ralo, declo) xyz2 = radectoxyz(rahi, dechi) xyz = (xyz1 + xyz2) / 2. xyz /= np.sqrt(np.sum(xyz**2)) rc, dc = xyztoradec(xyz) rc = rc[0] dc = dc[0] rad = degrees_between(rc, dc, ralo, declo) kd = tree_open(fn) I = tree_search_radec(kd, rc, dc, rad) print('Matched', len(I), 'from', fn) if len(I) == 0: return None T = fits_table(fn, rows=I) debug(len(T), 'spectra') if ralo > rahi: # RA wrap T.cut( np.logical_or(T.ra > ralo, T.ra < rahi) * (T.dec > declo) * (T.dec < dechi)) else: T.cut( (T.ra > ralo) * (T.ra < rahi) * (T.dec > declo) * (T.dec < dechi)) debug(len(T), 'in cut') return T
def cat_targets_dr2(req, ver): import json tag = 'targets-dr2' ralo = float(req.GET['ralo']) rahi = float(req.GET['rahi']) declo = float(req.GET['declo']) dechi = float(req.GET['dechi']) ver = int(ver) if not ver in catversions[tag]: raise RuntimeError('Invalid version %i for tag %s' % (ver, tag)) from astrometry.util.fits import fits_table, merge_tables import numpy as np from cat.models import DR2_Target as Target from astrometry.util.starutil_numpy import radectoxyz, xyztoradec, degrees_between xyz1 = radectoxyz(ralo, declo) xyz2 = radectoxyz(rahi, dechi) xyz = (xyz1 + xyz2) / 2. xyz /= np.sqrt(np.sum(xyz**2)) rc, dc = xyztoradec(xyz) rc = rc[0] dc = dc[0] rad = degrees_between(rc, dc, ralo, declo) objs = Target.objects.extra(where=[ 'q3c_radial_query(target.ra, target.dec, %.4f, %.4f, %g)' % (rc, dc, rad * 1.01) ]) print('Got', objs.count(), 'targets') print('types:', np.unique([o.type for o in objs])) print('versions:', np.unique([o.version for o in objs])) return HttpResponse(json.dumps( dict( rd=[(float(o.ra), float(o.dec)) for o in objs], name=[o.type for o in objs], )), content_type='application/json')
def cat_kd(req, ver, tag, fn): tag = 'spec' ralo = float(req.GET['ralo']) rahi = float(req.GET['rahi']) declo = float(req.GET['declo']) dechi = float(req.GET['dechi']) ver = int(ver) if not ver in catversions[tag]: raise RuntimeError('Invalid version %i for tag %s' % (ver, tag)) import numpy as np from astrometry.util.fits import fits_table, merge_tables from astrometry.libkd.spherematch import tree_open, tree_search_radec from astrometry.util.starutil_numpy import radectoxyz, xyztoradec, degrees_between xyz1 = radectoxyz(ralo, declo) xyz2 = radectoxyz(rahi, dechi) xyz = (xyz1 + xyz2)/2. xyz /= np.sqrt(np.sum(xyz**2)) rc,dc = xyztoradec(xyz) rc = rc[0] dc = dc[0] rad = degrees_between(rc, dc, ralo, declo) kd = tree_open(fn) I = tree_search_radec(kd, rc, dc, rad) print('Matched', len(I), 'from', fn) if len(I) == 0: return None T = fits_table(fn, rows=I) debug(len(T), 'spectra') if ralo > rahi: # RA wrap T.cut(np.logical_or(T.ra > ralo, T.ra < rahi) * (T.dec > declo) * (T.dec < dechi)) else: T.cut((T.ra > ralo) * (T.ra < rahi) * (T.dec > declo) * (T.dec < dechi)) debug(len(T), 'in cut') return T
def cat_targets_dr2(req, ver): import json tag = 'targets-dr2' ralo = float(req.GET['ralo']) rahi = float(req.GET['rahi']) declo = float(req.GET['declo']) dechi = float(req.GET['dechi']) ver = int(ver) if not ver in catversions[tag]: raise RuntimeError('Invalid version %i for tag %s' % (ver, tag)) from astrometry.util.fits import fits_table, merge_tables import numpy as np from cat.models import DR2_Target as Target from astrometry.util.starutil_numpy import radectoxyz, xyztoradec, degrees_between xyz1 = radectoxyz(ralo, declo) xyz2 = radectoxyz(rahi, dechi) xyz = (xyz1 + xyz2)/2. xyz /= np.sqrt(np.sum(xyz**2)) rc,dc = xyztoradec(xyz) rc = rc[0] dc = dc[0] rad = degrees_between(rc, dc, ralo, declo) objs = Target.objects.extra(where=[ 'q3c_radial_query(target.ra, target.dec, %.4f, %.4f, %g)' % (rc, dc, rad * 1.01)]) print('Got', objs.count(), 'targets') print('types:', np.unique([o.type for o in objs])) print('versions:', np.unique([o.version for o in objs])) return HttpResponse(json.dumps(dict( rd=[(float(o.ra),float(o.dec)) for o in objs], name=[o.type for o in objs], )), content_type='application/json')
def match_kdtree_catalog(wcs, catfn): from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match, tree_permute from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys rc, dc = wcs.get_center() rr = wcs.get_radius() kd = tree_open(catfn) kd2 = tree_build_radec(np.array([rc]), np.array([dc])) r = deg2dist(rr) I, J, nil = trees_match(kd, kd2, r, permuted=False) # HACK #I2,J,d = trees_match(kd, kd2, r) xyz = spherematch_c.kdtree_get_positions(kd, I.astype(np.uint32)) #print 'I', I I2 = tree_permute(kd, I) #print 'I2', I2 tree_free(kd2) tree_close(kd) tra, tdec = xyztoradec(xyz) return tra, tdec, I2
from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys wcs = plot.wcs rc,dc = wcs.get_center() rr = wcs.get_radius() kd = tree_open(opt.t2cat) kd2 = tree_build_radec(np.array([rc]), np.array([dc])) r = deg2dist(rr) I,J,d = trees_match(kd, kd2, r, permuted=False) # HACK I2,J,d = trees_match(kd, kd2, r) xyz = spherematch_c.kdtree_get_positions(kd, I) tree_free(kd2) tree_close(kd) tra,tdec = xyztoradec(xyz) T = fits_table(opt.t2cat, hdu=6) for r,d,t1,t2,t3 in zip(tra,tdec, T.tyc1[I2], T.tyc2[I2], T.tyc3[I2]): if not plot.wcs.is_inside(r, d): continue ann.add_target(r, d, 'Tycho-2 %i-%i-%i' % (t1,t2,t3)) plot.color = opt.textcolor plot.fontsize = opt.textsize plot.lw = opt.lw plot.valign = opt.valign plot.halign = opt.halign plot.label_offset_x = opt.tox; plot.label_offset_y = opt.toy;
def plot_wcs_outline(wcsfn, plotfn, W=256, H=256, width=36, zoom=True, zoomwidth=3.6, grid=10, hd=False, hd_labels=False, tycho2=False): anutil.log_init(3) #anutil.log_set_level(3) wcs = anutil.Tan(wcsfn, 0) ra, dec = wcs.radec_center() plot = ps.Plotstuff(outformat='png', size=(W, H), rdw=(ra, dec, width)) plot.linestep = 1. plot.color = 'verydarkblue' plot.plot('fill') plot.fontsize = 12 #plot.color = 'gray' # dark gray plot.rgb = (0.3, 0.3, 0.3) if grid is not None: plot.plot_grid(*([grid] * 4)) plot.rgb = (0.4, 0.6, 0.4) ann = plot.annotations ann.NGC = ann.bright = ann.HD = 0 ann.constellations = 1 ann.constellation_labels = 1 ann.constellation_labels_long = 1 plot.plot('annotations') plot.stroke() ann.constellation_labels = 0 ann.constellation_labels_long = 0 ann.constellation_lines = 0 ann.constellation_markers = 1 plot.markersize = 3 plot.rgb = (0.4, 0.6, 0.4) plot.plot('annotations') plot.fill() ann.constellation_markers = 0 ann.bright_labels = False ann.bright = True plot.markersize = 2 if zoom >= 2: ann.bright_labels = True plot.plot('annotations') ann.bright = False ann.bright_labels = False plot.fill() if hd: ann.HD = True ann.HD_labels = hd_labels ps.plot_annotations_set_hd_catalog(ann, settings.HENRY_DRAPER_CAT) plot.plot('annotations') plot.stroke() ann.HD = False ann.HD_labels = False if tycho2 and settings.TYCHO2_KD: from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys kd = tree_open(settings.TYCHO2_KD) # this is a bit silly: build a tree with a single point, then do match() kd2 = tree_build_radec(np.array([ra]), np.array([dec])) r = deg2dist(width * np.sqrt(2.) / 2.) #r = deg2dist(wcs.radius()) I, nil, nil = trees_match(kd, kd2, r, permuted=False) del nil #print 'Matched', len(I) xyz = spherematch_c.kdtree_get_positions(kd, I) del I tree_free(kd2) tree_close(kd) #print >>sys.stderr, 'Got', xyz.shape, xyz tra, tdec = xyztoradec(xyz) #print >>sys.stderr, 'RA,Dec', ra,dec plot.apply_settings() for r, d in zip(tra, tdec): plot.marker_radec(r, d) plot.fill() ann.NGC = 1 plot.plot('annotations') ann.NGC = 0 plot.color = 'white' plot.lw = 3 out = plot.outline out.wcs_file = wcsfn plot.plot('outline') if zoom: # MAGIC width, height are arbitrary zoomwcs = anutil.anwcs_create_box(ra, dec, zoomwidth, 1000, 1000) out.wcs = zoomwcs plot.lw = 1 plot.dashed(3) plot.plot('outline') plot.write(plotfn)
def cat_targets_drAB(req, ver, cats=None, tag='', bgs=False, sky=False, bright=False, dark=False, color_name_func=desitarget_color_names): ''' color_name_func: function that selects names and colors for targets (eg based on targeting bit values) ''' if cats is None: cats = [] import json ralo = float(req.GET['ralo']) rahi = float(req.GET['rahi']) declo = float(req.GET['declo']) dechi = float(req.GET['dechi']) ver = int(ver) if not ver in catversions[tag]: raise RuntimeError('Invalid version %i for tag %s' % (ver, tag)) from astrometry.util.fits import fits_table, merge_tables from astrometry.libkd.spherematch import tree_open, tree_search_radec import numpy as np from astrometry.util.starutil_numpy import radectoxyz, xyztoradec, degrees_between xyz1 = radectoxyz(ralo, declo) xyz2 = radectoxyz(rahi, dechi) xyz = (xyz1 + xyz2)/2. xyz /= np.sqrt(np.sum(xyz**2)) rc,dc = xyztoradec(xyz) rc = rc[0] dc = dc[0] rad = degrees_between(rc, dc, ralo, declo) ''' startree -i /project/projectdirs/desi/target/catalogs/targets-dr4-0.20.0.fits -o data/targets-dr4-0.20.0.kd.fits -P -k -T ''' TT = [] for fn in cats: kd = tree_open(fn) I = tree_search_radec(kd, rc, dc, rad) print('Matched', len(I), 'from', fn) if len(I) == 0: continue T = fits_table(fn, rows=I) TT.append(T) if len(TT) == 0: return HttpResponse(json.dumps(dict(rd=[], name=[])), content_type='application/json') T = merge_tables(TT, columns='fillzero') if bgs: T.cut(T.bgs_target > 0) if bright: T.cut(np.logical_or(T.bgs_target > 0, T.mws_target > 0)) if dark: T.cut(T.desi_target > 0) names = None colors = None if color_name_func is not None: names,colors = color_name_func(T) if sky: fluxes = [dict(g=float(g), r=float(r), z=float(z)) for (g,r,z) in zip(T.apflux_g[:,0], T.apflux_r[:,0], T.apflux_z[:,0])] nobs = None else: fluxes = [dict(g=float(g), r=float(r), z=float(z), W1=float(W1), W2=float(W2)) for (g,r,z,W1,W2) in zip(T.flux_g, T.flux_r, T.flux_z, T.flux_w1, T.flux_w2)] nobs=[dict(g=int(g), r=int(r), z=int(z)) for g,r,z in zip(T.nobs_g, T.nobs_r, T.nobs_z)], rtn = dict(rd=[(t.ra, t.dec) for t in T], targetid=[int(t) for t in T.targetid], fluxes=fluxes, ) if names is not None: rtn.update(name=names) if colors is not None: rtn.update(color=colors) if nobs is not None: rtn.update(nobs=nobs) # Convert targetid to string to prevent rounding errors rtn['targetid'] = [str(s) for s in rtn['targetid']] return HttpResponse(json.dumps(rtn), content_type='application/json')
def cat_targets_drAB(req, ver, cats=[], tag='', bgs=False, sky=False, bright=False, dark=False, color_name_func=desitarget_color_names): ''' color_name_func: function that selects names and colors for targets (eg based on targeting bit values) ''' import json ralo = float(req.GET['ralo']) rahi = float(req.GET['rahi']) declo = float(req.GET['declo']) dechi = float(req.GET['dechi']) ver = int(ver) if not ver in catversions[tag]: raise RuntimeError('Invalid version %i for tag %s' % (ver, tag)) from astrometry.util.fits import fits_table, merge_tables from astrometry.libkd.spherematch import tree_open, tree_search_radec import numpy as np from astrometry.util.starutil_numpy import radectoxyz, xyztoradec, degrees_between xyz1 = radectoxyz(ralo, declo) xyz2 = radectoxyz(rahi, dechi) xyz = (xyz1 + xyz2) / 2. xyz /= np.sqrt(np.sum(xyz**2)) rc, dc = xyztoradec(xyz) rc = rc[0] dc = dc[0] rad = degrees_between(rc, dc, ralo, declo) ''' startree -i /project/projectdirs/desi/target/catalogs/targets-dr4-0.20.0.fits -o data/targets-dr4-0.20.0.kd.fits -P -k -T ''' TT = [] for fn in cats: kd = tree_open(fn) I = tree_search_radec(kd, rc, dc, rad) print('Matched', len(I), 'from', fn) if len(I) == 0: continue T = fits_table(fn, rows=I) TT.append(T) if len(TT) == 0: return HttpResponse(json.dumps(dict(rd=[], name=[])), content_type='application/json') T = merge_tables(TT, columns='fillzero') if bgs: T.cut(T.bgs_target > 0) if bright: T.cut(np.logical_or(T.bgs_target > 0, T.mws_target > 0)) if dark: T.cut(T.desi_target > 0) names = None colors = None if color_name_func is not None: names, colors = color_name_func(T) if sky: fluxes = [ dict(g=float(g), r=float(r), z=float(z)) for (g, r, z) in zip(T.apflux_g[:, 0], T.apflux_r[:, 0], T.apflux_z[:, 0]) ] nobs = None else: fluxes = [ dict(g=float(g), r=float(r), z=float(z), W1=float(W1), W2=float(W2)) for (g, r, z, W1, W2) in zip(T.flux_g, T.flux_r, T.flux_z, T.flux_w1, T.flux_w2) ] nobs = [ dict(g=int(g), r=int(r), z=int(z)) for g, r, z in zip(T.nobs_g, T.nobs_r, T.nobs_z) ], rtn = dict( rd=[(t.ra, t.dec) for t in T], targetid=[int(t) for t in T.targetid], fluxes=fluxes, ) if names is not None: rtn.update(name=names) if colors is not None: rtn.update(color=colors) if nobs is not None: rtn.update(nobs=nobs) return HttpResponse(json.dumps(rtn), content_type='application/json')
def cat_sdss(req, ver): import json import numpy as np from astrometry.util.starutil_numpy import degrees_between, radectoxyz, xyztoradec from map.views import sdss_ccds_near from astrometry.util.fits import fits_table, merge_tables tag = 'sdss-cat' ralo = float(req.GET['ralo']) rahi = float(req.GET['rahi']) declo = float(req.GET['declo']) dechi = float(req.GET['dechi']) ver = int(ver) if not ver in catversions[tag]: raise RuntimeError('Invalid version %i for tag %s' % (ver, tag)) rad = degrees_between(ralo, declo, rahi, dechi) / 2. xyz1 = radectoxyz(ralo, declo) xyz2 = radectoxyz(rahi, dechi) xyz = (xyz1 + xyz2) xyz /= np.sqrt(np.sum(xyz**2)) rc, dc = xyztoradec(xyz) rad = rad + np.hypot(10., 14.) / 2. / 60. ccds = sdss_ccds_near(rc[0], dc[0], rad) if ccds is None: print('No SDSS CCDs nearby') return HttpResponse(json.dumps(dict(rd=[])), content_type='application/json') print(len(ccds), 'SDSS CCDs') T = [] for ccd in ccds: # env/BOSS_PHOTOOBJ/301/2073/3/photoObj-002073-3-0088.fits fn = os.path.join( settings.SDSS_BASEDIR, 'env', 'BOSS_PHOTOOBJ', str(ccd.rerun), str(ccd.run), str(ccd.camcol), 'photoObj-%06i-%i-%04i.fits' % (ccd.run, ccd.camcol, ccd.field)) print('Reading', fn) T.append( fits_table( fn, columns= 'ra dec objid mode objc_type objc_flags objc_flags nchild tai expflux devflux psfflux cmodelflux fracdev mjd' .split())) T = merge_tables(T) T.cut((T.dec >= declo) * (T.dec <= dechi)) # FIXME T.cut((T.ra >= ralo) * (T.ra <= rahi)) # primary T.cut(T.mode == 1) types = ['P' if t == 6 else 'C' for t in T.objc_type] fluxes = [ p if t == 6 else c for t, p, c in zip(T.objc_type, T.psfflux, T.cmodelflux) ] return HttpResponse(json.dumps( dict( rd=[(float(o.ra), float(o.dec)) for o in T], sourcetype=types, fluxes=[ dict(u=float(f[0]), g=float(f[1]), r=float(f[2]), i=float(f[3]), z=float(f[4])) for f in fluxes ], )), content_type='application/json')
def build_groupcat_sky(parent, linking_length=2, verbose=True, groupcatfile='groupcat.fits', parentfile='parent.fits'): """Build a group catalog based on just RA, Dec coordinates. """ from astropy.table import Column, Table from astrometry.util.starutil_numpy import radectoxyz, xyztoradec, arcsec_between grp, mult, frst, nxt = fof_groups(parent, linking_length=linking_length, verbose=verbose) ngrp = max(grp) + 1 groupid = np.arange(ngrp) groupcat = Table() groupcat.add_column(Column(name='groupid', dtype='i4', length=ngrp, data=groupid)) # unique ID number #groupcat.add_column(Column(name='galaxy', dtype='S1000', length=ngrp)) groupcat.add_column(Column(name='nmembers', dtype='i4', length=ngrp)) groupcat.add_column(Column(name='ra', dtype='f8', length=ngrp)) # average RA groupcat.add_column(Column(name='dec', dtype='f8', length=ngrp)) # average Dec groupcat.add_column(Column(name='width', dtype='f4', length=ngrp)) # maximum separation groupcat.add_column(Column(name='d25max', dtype='f4', length=ngrp)) groupcat.add_column(Column(name='d25min', dtype='f4', length=ngrp)) groupcat.add_column(Column(name='fracmasked', dtype='f4', length=ngrp)) # Add the groupid to the input catalog. outparent = parent.copy() #t0 = time.time() npergrp, _ = np.histogram(grp, bins=len(grp), range=(0, len(grp))) #print('Time to build the histogram = {:.3f} minutes.'.format( (time.time() - t0) / 60 ) ) big = np.where( npergrp > 1 )[0] small = np.where( npergrp == 1 )[0] if len(small) > 0: groupcat['nmembers'][small] = 1 groupcat['groupid'][small] = groupid[small] groupcat['ra'][small] = parent['ra'][grp[small]] groupcat['dec'][small] = parent['dec'][grp[small]] groupcat['d25max'][small] = parent['d25'][grp[small]] groupcat['d25min'][small] = parent['d25'][grp[small]] groupcat['width'][small] = parent['d25'][grp[small]] outparent['groupid'][grp[small]] = groupid[small] for igrp in range(len(big)): jj = frst[big[igrp]] ig = list() ig.append(jj) while (nxt[jj] != -1): ig.append(nxt[jj]) jj = nxt[jj] ig = np.array(ig) ra1, dec1 = parent['ra'][ig].data, parent['dec'][ig].data ra2, dec2 = xyztoradec(np.mean(radectoxyz(ra1, dec1), axis=0)) groupcat['ra'][big[igrp]] = ra2 groupcat['dec'][big[igrp]] = dec2 d25min, d25max = np.min(parent['d25'][ig]), np.max(parent['d25'][ig]) groupcat['d25max'][big[igrp]] = d25max groupcat['d25min'][big[igrp]] = d25min groupcat['nmembers'][big[igrp]] = len(ig) outparent['groupid'][ig] = groupcat['groupid'][big[igrp]] # Get the distance of each object from every other object. #diff = arcsec_between(ra1, dec1, ra2, dec2) / 60 # [arcmin] # group center diff = list() for _ra, _dec in zip(ra1, dec1): diff.append(arcsec_between(ra1, dec1, _ra, _dec) / 60) # [arcmin] #if len(ig) > 2: # import pdb ; pdb.set_trace() diameter = np.hstack(diff).max() groupcat['width'][big[igrp]] = diameter print('Writing {}'.format(groupcatfile)) groupcat.write(groupcatfile, overwrite=True) print('Writing {}'.format(parentfile)) outparent.write(parentfile, overwrite=True) return groupcat, outparent
def plot_wcs_outline(wcsfn, plotfn, W=256, H=256, width=36, zoom=True, zoomwidth=3.6, grid=10, hd=False, hd_labels=False, tycho2=False): anutil.log_init(3) #anutil.log_set_level(3) wcs = anutil.Tan(wcsfn, 0) ra,dec = wcs.radec_center() plot = ps.Plotstuff(outformat='png', size=(W, H), rdw=(ra,dec,width)) plot.linestep = 1. plot.color = 'verydarkblue' plot.plot('fill') plot.fontsize = 12 #plot.color = 'gray' # dark gray plot.rgb = (0.3,0.3,0.3) if grid is not None: plot.plot_grid(*([grid]*4)) plot.rgb = (0.4, 0.6, 0.4) ann = plot.annotations ann.NGC = ann.bright = ann.HD = 0 ann.constellations = 1 ann.constellation_labels = 1 ann.constellation_labels_long = 1 plot.plot('annotations') plot.stroke() ann.constellation_labels = 0 ann.constellation_labels_long = 0 ann.constellation_lines = 0 ann.constellation_markers = 1 plot.markersize = 3 plot.rgb = (0.4, 0.6, 0.4) plot.plot('annotations') plot.fill() ann.constellation_markers = 0 ann.bright_labels = False ann.bright = True plot.markersize = 2 if zoom >= 2: ann.bright_labels = True plot.plot('annotations') ann.bright = False ann.bright_labels = False plot.fill() if hd: ann.HD = True ann.HD_labels = hd_labels ps.plot_annotations_set_hd_catalog(ann, settings.HENRY_DRAPER_CAT) plot.plot('annotations') plot.stroke() ann.HD = False ann.HD_labels = False if tycho2: from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys kd = tree_open(settings.TYCHO2_KD) # this is a bit silly: build a tree with a single point, then do match() kd2 = tree_build_radec(np.array([ra]), np.array([dec])) r = deg2dist(width * np.sqrt(2.) / 2.) #r = deg2dist(wcs.radius()) I,J,d = trees_match(kd, kd2, r, permuted=False) del J del d #print 'Matched', len(I) xyz = spherematch_c.kdtree_get_positions(kd, I) del I tree_free(kd2) tree_close(kd) #print >>sys.stderr, 'Got', xyz.shape, xyz tra,tdec = xyztoradec(xyz) #print >>sys.stderr, 'RA,Dec', ra,dec plot.apply_settings() for r,d in zip(tra,tdec): plot.marker_radec(r,d) plot.fill() ann.NGC = 1 plot.plot('annotations') ann.NGC = 0 plot.color = 'white' plot.lw = 3 out = plot.outline out.wcs_file = wcsfn plot.plot('outline') if zoom: # MAGIC width, height are arbitrary zoomwcs = anutil.anwcs_create_box(ra, dec, zoomwidth, 1000,1000) out.wcs = zoomwcs plot.lw = 1 plot.dashed(3) plot.plot('outline') plot.write(plotfn)