def showSipSolutions(srcs, wcs0, andDir, x0, y0, W, H, filterName, plotPrefix): ''' srcs: afw Catalog of sources wcs0: original WCS andDir: astrometry_net_data directory ''' imargs = dict(imageSize=(W, H), filterName=filterName, x0=x0, y0=y0) # Set up astrometry_net_data os.environ['ASTROMETRY_NET_DATA_DIR'] = andDir andConfig = measAstrom.AstrometryNetDataConfig() fn = os.path.join(andDir, 'andConfig.py') andConfig.load(fn) # Set up meas_astrom conf = measAstrom.ANetBasicAstrometryConfig(sipOrder=4) ast = measAstrom.ANetBasicAstrometryTask(conf, andConfig, logLevel=Log.DEBUG) # What reference sources are in the original WCS refs = ast.getReferenceSourcesForWcs(wcs0, **imargs) print('Got', len(refs), 'reference objects for initial WCS') # How does a straight TAN solution look? conf2 = measAstrom.ANetBasicAstrometryConfig(sipOrder=4, calculateSip=False) ast2 = measAstrom.ANetBasicAstrometryTask(conf2, andConfig, logLevel=Log.DEBUG) solve = ast2.determineWcs2(srcs, **imargs) tanwcs = solve.tanWcs # How about if we fit a SIP WCS using the *original* WCS? wcs2 = ast.getSipWcsFromWcs(wcs0, (W, H), x0=x0, y0=y0) # (We determineWcs() for a SIP solution below...) # Make some plots in pixel space by pushing ref sources through WCSes rx0, ry0 = [], [] rx2, ry2 = [], [] rx3, ry3 = [], [] for src in refs: xy = wcs0.skyToPixel(src.getCoord()) rx0.append(xy[0]) ry0.append(xy[1]) xy = tanwcs.skyToPixel(src.getCoord()) rx2.append(xy[0]) ry2.append(xy[1]) xy = wcs2.skyToPixel(src.getCoord()) rx3.append(xy[0]) ry3.append(xy[1]) rx0 = np.array(rx0) ry0 = np.array(ry0) rx2 = np.array(rx2) ry2 = np.array(ry2) rx3 = np.array(rx3) ry3 = np.array(ry3) x = np.array([src.getX() for src in srcs]) y = np.array([src.getY() for src in srcs]) from astrometry.libkd.spherematch import match from astrometry.util.plotutils import plothist, PlotSequence ps = PlotSequence(plotPrefix) # Match up various sources... R = 2. II, d = match(np.vstack((x, y)).T, np.vstack((rx0, ry0)).T, R) I = II[:, 0] J = II[:, 1] pa = dict(range=((-R, R), (-R, R))) plt.clf() plothist(x[I] - rx0[J], y[I] - ry0[J], 200, **pa) plt.title('Source positions - Reference positions (initial WCS)') plt.xlabel('delta-X (pixels)') plt.ylabel('delta-Y (pixels)') ps.savefig() II, d = match(np.vstack((x, y)).T, np.vstack((rx2, ry2)).T, R) I = II[:, 0] J = II[:, 1] plt.clf() plothist(x[I] - rx2[J], y[I] - ry2[J], 200, **pa) plt.title('Source positions - Reference positions (TAN WCS)') plt.xlabel('delta-X (pixels)') plt.ylabel('delta-Y (pixels)') ps.savefig() II, d = match(np.vstack((x, y)).T, np.vstack((rx3, ry3)).T, R) I = II[:, 0] J = II[:, 1] plt.clf() plothist(x[I] - rx3[J], y[I] - ry3[J], 200, **pa) plt.title('Source positions - Reference positions (SIP WCS #2)') plt.xlabel('delta-X (pixels)') plt.ylabel('delta-Y (pixels)') ps.savefig() II, d = match(np.vstack((rx0, ry0)).T, np.vstack((rx3, ry3)).T, R) I = II[:, 0] J = II[:, 1] plt.clf() plothist(rx0[I] - rx3[J], ry0[I] - ry3[J], 200, **pa) plt.title( 'Reference positions (Original WCS) - Reference positions (SIP WCS #2)' ) plt.xlabel('delta-X (pixels)') plt.ylabel('delta-Y (pixels)') ps.savefig() matches = solve.tanMatches msx, msy = [], [] mrx, mry = [], [] for m in matches: ref, src = m.first, m.second xy = tanwcs.skyToPixel(ref.getCoord()) mrx.append(xy[0]) mry.append(xy[1]) msx.append(src.getX()) msy.append(src.getY()) plt.clf() plt.plot(x, y, 'r.') plt.plot(msx, msy, 'o', mec='r') plt.plot(rx0, ry0, 'g.') plt.plot(mrx, mry, 'gx') plt.title('TAN matches') ps.savefig() # Get SIP solution (4th order) solve = ast.determineWcs2(srcs, **imargs) wcs1 = solve.sipWcs matches = solve.sipMatches msx, msy = [], [] mrx, mry = [], [] for m in matches: ref, src = m.first, m.second xy = tanwcs.skyToPixel(ref.getCoord()) mrx.append(xy[0]) mry.append(xy[1]) msx.append(src.getX()) msy.append(src.getY()) plt.clf() plt.plot(x, y, 'r.') plt.plot(msx, msy, 'o', mec='r') plt.plot(rx0, ry0, 'g.') plt.plot(mrx, mry, 'gx') plt.title('SIP matches') ps.savefig() rx1, ry1 = [], [] for src in refs: xy = wcs1.skyToPixel(src.getCoord()) rx1.append(xy[0]) ry1.append(xy[1]) rx1 = np.array(rx1) ry1 = np.array(ry1) plt.clf() plt.plot(x, y, 'o', mec='r', mfc='none') plt.plot(rx0, ry0, 'bx') plt.plot(rx1, ry1, 'g+') plt.plot(rx2, ry2, 'mx') plt.plot(rx3, ry3, 'r+') ps.savefig() plt.axis([x0, x0 + 500, y0, y0 + 500]) ps.savefig() II, d = match(np.vstack((x, y)).T, np.vstack((rx1, ry1)).T, R) I = II[:, 0] J = II[:, 1] plt.clf() plothist(x[I] - rx1[J], y[I] - ry1[J], 200, **pa) plt.title('Source positions - Reference positions (SIP WCS)') plt.xlabel('delta-X (pixels)') plt.ylabel('delta-Y (pixels)') ps.savefig()
def run(self, dataRefList, ct=None, debug=False, verbose=False): ccdSet = self.readCcd(dataRefList) self.removeNonExistCcd(dataRefList, ccdSet) sourceSet = [] matchList = [] astrom = measAstrom.ANetBasicAstrometryTask(self.config.astrom) ssVisit = dict() mlVisit = dict() dataRefListUsed = list() wcsDic = dict() calibDic = dict() ffpDic = dict() for dataRef in dataRefList: if dataRef.dataId['visit'] not in ssVisit: ssVisit[dataRef.dataId['visit']] = list() mlVisit[dataRef.dataId['visit']] = list() wcsDic[dataRef.dataId['visit']] = dict() calibDic[dataRef.dataId['visit']] = dict() ffpDic[dataRef.dataId['visit']] = dict() try: if not dataRef.datasetExists('src'): raise RuntimeError("no data for src %s" % (dataRef.dataId)) if not dataRef.datasetExists('jointcal_wcs'): raise RuntimeError("no data for wcs %s" % (dataRef.dataId)) if not dataRef.datasetExists('fcr'): raise RuntimeError("no data for fcr %s" % (dataRef.dataId)) wcs = dataRef.get('jointcal_wcs') md = dataRef.get('calexp_md') filterName = afwImage.Filter(md).getName() md = dataRef.get('fcr_md') ffp = measMosaic.FluxFitParams(md) photoCalib = afwImage.makePhotoCalibFromMetadata(md) sources = dataRef.get('src', flags=afwTable.SOURCE_IO_NO_FOOTPRINTS, immediate=True) icSrces = dataRef.get('icSrc', flags=afwTable.SOURCE_IO_NO_FOOTPRINTS, immediate=True) packedMatches = dataRef.get('icMatch') matches = astrom.joinMatchListWithCatalog(packedMatches, icSrces) matches = [m for m in matches if m[0] is not None] if matches: refSchema = matches[0][0].schema if ct: # Add a "flux" field to the match records which contains the # colorterm-corrected reference flux. The field name is hard-coded in # lsst::meas::mosaic::Source. mapper = afwTable.SchemaMapper(refSchema) for key, field in refSchema: mapper.addMapping(key) key_f = mapper.editOutputSchema().addField("flux", type=float, doc="Reference flux") table = afwTable.SimpleTable.make(mapper.getOutputSchema()) table.preallocate(len(matches)) for match in matches: newMatch = table.makeRecord() newMatch.assign(match[0], mapper) match[0] = newMatch key_p = refSchema.find(refSchema.join(ct.primary, "flux")).key key_s = refSchema.find(refSchema.join(ct.secondary, "flux")).key refFlux1 = numpy.array([m[0].get(key_p) for m in matches]) refFlux2 = numpy.array([m[0].get(key_s) for m in matches]) refMag1 = -2.5*numpy.log10(refFlux1) refMag2 = -2.5*numpy.log10(refFlux2) refMag = ct.transformMags(refMag1, refMag2) refFlux = numpy.power(10.0, -0.4*refMag) matches = [setCatFlux(m, f, key_f) for m, f in zip(matches, refFlux) if f == f] else: # No colorterm; we can get away with aliasing the reference flux. refFluxField = measAlg.getRefFluxField(refSchema, filterName) refSchema.getAliasMap().set("flux", refFluxField) sources = self.selectStars(sources) matches = self.selectStars(matches, True) except Exception as e: print("Failed to read: %s" % (e)) sources = None continue if sources is not None: for s in sources: if numpy.isfinite(s.getRa().asDegrees()): # get rid of NaN src = measMosaic.Source(s) src.setExp(dataRef.dataId['visit']) src.setChip(dataRef.dataId['ccd']) ssVisit[dataRef.dataId['visit']].append(src) for m in matches: if m[0] is not None and m[1] is not None: match = (measMosaic.Source(m[0], wcs), measMosaic.Source(m[1])) match[1].setExp(dataRef.dataId['visit']) match[1].setChip(dataRef.dataId['ccd']) mlVisit[dataRef.dataId['visit']].append(match) wcsDic[dataRef.dataId['visit']][dataRef.dataId['ccd']] = wcs calibDic[dataRef.dataId['visit']][dataRef.dataId['ccd']] = photoCalib ffpDic[dataRef.dataId['visit']][dataRef.dataId['ccd']] = ffp dataRefListUsed.append(dataRef) for visit in ssVisit: sourceSet.append(ssVisit[visit]) matchList.append(mlVisit[visit]) d_lim = afwGeom.Angle(self.config.radXMatch, afwGeom.arcseconds) nbrightest = self.config.nBrightest allMat, allSource = self.mergeCatalog(sourceSet, matchList, ccdSet, d_lim) dx_m, dy_m, dx_s, dy_s, m0_m, dm_m, m0_s, dm_s = self.makeDiffPosFlux(allMat, allSource, wcsDic, calibDic, ffpDic) self.plotFlux(m0_m, dm_m, m0_s, dm_s) self.makeFluxStat(allMat, allSource, calibDic, ffpDic, wcsDic) self.plotPos(dx_m, dy_m, dx_s, dy_s) self.plotPosAsMag(m0_s, dx_s, dy_s) self.writeCatalog(allSource, wcsDic, calibDic, ffpDic)