def testTicket2441(self): """Test ticket 2441: warpExposure sometimes mishandles zero-extent dest exposures""" fromWcs = makeWcs( pixelScale=afwGeom.Angle(1.0e-8, afwGeom.degrees), projection="TAN", crPixPos=(0, 0), crValCoord=afwCoord.IcrsCoord(afwGeom.Point2D(359, 0), afwGeom.degrees), ) fromExp = afwImage.ExposureF(afwImage.MaskedImageF(10, 10), fromWcs) toWcs = makeWcs( pixelScale=afwGeom.Angle(0.00011, afwGeom.degrees), projection="CEA", crPixPos=(410000.0, 11441.0), crValCoord=afwCoord.IcrsCoord(afwGeom.Point2D(45, 0), afwGeom.degrees), doFlipX=True, ) toExp = afwImage.ExposureF(afwImage.MaskedImageF(0, 0), toWcs) warpControl = afwMath.WarpingControl("lanczos3") # if a bug described in ticket #2441 is present, this will raise an # exception: numGoodPix = afwMath.warpExposure(toExp, fromExp, warpControl) self.assertEqual(numGoodPix, 0)
def testSmallSrc(self): """Verify that a source image that is too small will not raise an exception This tests another bug that was fixed in ticket #2441 """ fromWcs = makeWcs( pixelScale=afwGeom.Angle(1.0e-8, afwGeom.degrees), projection="TAN", crPixPos=(0, 0), crValCoord=afwCoord.IcrsCoord(afwGeom.Point2D(359, 0), afwGeom.degrees), ) fromExp = afwImage.ExposureF(afwImage.MaskedImageF(1, 1), fromWcs) toWcs = makeWcs( pixelScale=afwGeom.Angle(1.1e-8, afwGeom.degrees), projection="TAN", crPixPos=(0, 0), crValCoord=afwCoord.IcrsCoord(afwGeom.Point2D(358, 0), afwGeom.degrees), ) toExp = afwImage.ExposureF(afwImage.MaskedImageF(10, 10), toWcs) warpControl = afwMath.WarpingControl("lanczos3") # if a bug described in ticket #2441 is present, this will raise an # exception: numGoodPix = afwMath.warpExposure(toExp, fromExp, warpControl) self.assertEqual(numGoodPix, 0) imArr, maskArr, varArr = toExp.getMaskedImage().getArrays() self.assertTrue(np.all(np.isnan(imArr))) self.assertTrue(np.all(np.isinf(varArr))) noDataBitMask = afwImage.Mask.getPlaneBitMask("NO_DATA") self.assertTrue(np.all(maskArr == noDataBitMask))
def __call__(self, gc, band, max_mag): # Retrieve the desired columns and filter on magnitude values. bandname = 'mag_true_{}_lsst'.format(band) filter_ = '{} < {}'.format(bandname, max_mag) print(filter_) gc_cols = gc.get_quantities( ['galaxy_id', 'ra_true', 'dec_true', bandname], filters=[filter_]) print(len(gc_cols[bandname])) # Rotate to the Run1.2p field. gc_ra_rot, gc_dec_rot \ = self.field_rotator.transform(gc_cols['ra_true'], gc_cols['dec_true']) # Select the galaxies within the patch. index = np.where((gc_ra_rot > self.ra_range[0]) & (gc_ra_rot < self.ra_range[1]) & (gc_dec_rot > self.dec_range[0]) & (gc_dec_rot < self.dec_range[1])) galaxy_id = gc_cols['galaxy_id'][index] gc_ra = gc_ra_rot[index] gc_dec = gc_dec_rot[index] gc_mag = gc_cols[bandname][index] print(len(galaxy_id)) # Create a SourceCatalog with the galaxy_ids, coordinates, magnitudes galaxy_catalog = make_SourceCatalog(mag_cols((band, ))) for id_, ra, dec, mag in zip(galaxy_id, gc_ra, gc_dec, gc_mag): record = galaxy_catalog.addNew() record.set('id', id_) record.set('coord_ra', afw_geom.Angle(ra, afw_geom.degrees)) record.set('coord_dec', afw_geom.Angle(dec, afw_geom.degrees)) record.set('mag_{}'.format(band), mag) return galaxy_catalog
def __init__(self, config=None): """Construct a DodecaSkyMap @param[in] config: an instance of self.ConfigClass; if None the default config is used """ BaseSkyMap.__init__(self, config) self._dodecahedron = detail.Dodecahedron( withFacesOnPoles=self.config.withTractsOnPoles) tractOverlap = afwGeom.Angle(self.config.tractOverlap, afwGeom.degrees) for id in range(12): tractVec = self._dodecahedron.getFaceCtr(id) tractCoord = detail.coordFromVec(tractVec, defRA=afwGeom.Angle(0)) tractRA = tractCoord.getLongitude() vertexVecList = self._dodecahedron.getVertices(id) # make initial WCS; don't worry about crPixPos because TractInfo will shift it as required wcs = self._wcsFactory.makeWcs(crPixPos=afwGeom.Point2D(0, 0), crValCoord=tractCoord) self._tractInfoList.append( TractInfo( id=id, patchInnerDimensions=self.config.patchInnerDimensions, patchBorder=self.config.patchBorder, ctrCoord=tractCoord, vertexCoordList=[ detail.coordFromVec(vec, defRA=tractRA) for vec in vertexVecList ], tractOverlap=tractOverlap, wcs=wcs, ))
def __init__(self, result): """Set exposure information based on a query result from a db connection """ self._ind = -1 dataId = dict( run=result[self._nextInd], rerun=result[self._nextInd], camcol=result[self._nextInd], field=result[self._nextInd], filter=result[self._nextInd], ) coordList = [] for i in range(4): coordList.append( IcrsCoord( afwGeom.Angle(result[self._nextInd], afwGeom.degrees), afwGeom.Angle(result[self._nextInd], afwGeom.degrees), )) BaseExposureInfo.__init__(self, dataId, coordList) self.strip = result[self._nextInd] self.fwhm = result[self._nextInd] self.sky = result[self._nextInd] self.airmass = result[self._nextInd] self.quality = result[self._nextInd] self.isBlacklisted = result[self._nextInd] # compute RHL quality factors self.q = self.sky * (self.fwhm**2) self.qscore = None # not known yet
def testFlatFocalPlane(self): """Test an undistorted focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.03) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) fpPosition = afwGeom.Point2D(50, 25) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D(-0.5, -0.5) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform((0.0, plateScaleRad)) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToPupil=focalPlaneToPupil, pixelSizeMm=pixelSizeMm, ) # with no distortion, this should be a unity transform for pointPix in ( afwGeom.Point2D(0, 0), afwGeom.Point2D(1000, 2000), afwGeom.Point2D(-100.5, 27.23), ): pointTanPix = pixelToTanPixel.forwardTransform(pointPix) self.assertPairsNearlyEqual(pointTanPix, pointPix)
def _bbox_for_coords(self, wcs, center_coord, width, height, units): """Returns a Box2I object representing the bounding box in pixels of the target region. @wcs: WCS object for the target region. @center_coord: ICRS RA and Dec coordinate for the center of the target region. @width: Width of the target region with units indicated by 'units' below. @height: Height of the target region with units indicated by 'units' below. @units: Units for height and width. 'pixel' or 'arcsecond' """ if units == "arcsec": # center_coord center, RA and Dec with width and height in arcseconds width_half_a = afw_geom.Angle((width / 2.0), afw_geom.arcseconds) height_half_a = afw_geom.Angle((height / 2.0), afw_geom.arcseconds) min_ra = center_coord.getLongitude() - width_half_a min_dec = center_coord.getLatitude() - height_half_a max_ra = center_coord.getLongitude() + width_half_a max_dec = center_coord.getLatitude() + height_half_a ll_coord = afw_geom.SpherePoint(min_ra, min_dec) ll_coord_pix = wcs.skyToPixel(ll_coord) ur_coord = afw_geom.SpherePoint(max_ra, max_dec) ur_coord_pix = wcs.skyToPixel(ur_coord) p2i_min = afw_geom.Point2I(ll_coord_pix) p2i_max = afw_geom.Point2I(ur_coord_pix) bbox = afw_geom.Box2I(p2i_min, p2i_max) elif units == "pixel": # center_coord center, RA and Dec with width and height in pixels ctr_coord_pix = wcs.skyToPixel(center_coord) min_ra_pix = int(ctr_coord_pix.getX() - width // 2) min_dec_pix = int(ctr_coord_pix.getY() - height // 2) p2i = afw_geom.Point2I(min_ra_pix, min_dec_pix) bbox = afw_geom.Box2I(p2i, afw_geom.Extent2I(width, height)) else: raise Exception("invalid units {}".format(units)) return bbox
def averageRaDec(ra, dec): """Calculate average RA, Dec from input lists using spherical geometry. Parameters ---------- ra : list of float RA in [radians] dec : list of float Dec in [radians] Returns ------- float, float meanRa, meanDec -- Tuple of average RA, Dec [radians] """ assert (len(ra) == len(dec)) angleRa = [afwGeom.Angle(r, afwGeom.radians) for r in ra] angleDec = [afwGeom.Angle(d, afwGeom.radians) for d in dec] coords = [ afwGeom.SpherePoint(ar, ad, afwGeom.radians) for (ar, ad) in zip(angleRa, angleDec) ] meanRa, meanDec = afwGeom.averageSpherePoint(coords) return meanRa.asRadians(), meanDec.asRadians()
def testCurvedFocalPlane(self): """Test a curved focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.03) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) fpPosition = afwGeom.Point2D( 50, 25) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D( -0.5, -0.5) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform( (0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad)) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToPupil=focalPlaneToPupil, pixelSizeMm=pixelSizeMm, plateScale=plateScale, ) # the center point of the detector should not move ctrPointPix = afwGeom.Box2D(bbox).getCenter() ctrPointTanPix = pixelToTanPixel.forwardTransform(ctrPointPix) for i in range(2): self.assertAlmostEquals(ctrPointTanPix[i], ctrPointPix[i]) # two points separated by x pixels in tan pixels coordinates # should be separated x * rad/tanPix in pupil coordinates, # where rad/tanPix = plate scale in rad/MM * mean pixel size in mm radPerTanPixel = plateScaleRad * (pixelSizeMm[0] + pixelSizeMm[1]) / 2.0 pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm) pixelToPupil = afwGeom.MultiXYTransform( (pixelToFocalPlane, focalPlaneToPupil)) prevPointPupil = None prevPointTanPix = None for pointPix in ( afwGeom.Point2D(0, 0), afwGeom.Point2D(1000, 2000), afwGeom.Point2D(-100.5, 27.23), afwGeom.Point2D(-95.3, 0.0), ): pointPupil = pixelToPupil.forwardTransform(pointPix) pointTanPix = pixelToTanPixel.forwardTransform(pointPix) if prevPointPupil: pupilSep = numpy.linalg.norm(pointPupil - prevPointPupil) tanPixSep = numpy.linalg.norm(pointTanPix - prevPointTanPix) self.assertAlmostEquals(tanPixSep * radPerTanPixel, pupilSep) prevPointPupil = pointPupil prevPointTanPix = pointTanPix
def run(self, dataRef): """Report tracts and patches that are within a given region of a skymap @param dataRef: data reference for sky map. @return: a pipeBase.Struct with fields: - ccdInfoSetDict: a dict of (tractId, patchIndex): set of CcdExposureInfo """ skyMap = dataRef.get(self.config.coaddName + "Coadd_skyMap") # make coords in the correct order to form an enclosed space raRange = (self.config.raDecRange[0], self.config.raDecRange[2]) decRange = (self.config.raDecRange[1], self.config.raDecRange[3]) raDecList = [ (raRange[0], decRange[0]), (raRange[1], decRange[0]), (raRange[1], decRange[1]), (raRange[0], decRange[1]), ] coordList = [ afwCoord.IcrsCoord(afwGeom.Angle(ra, afwGeom.degrees), afwGeom.Angle(dec, afwGeom.degrees)) for ra, dec in raDecList ] tractPatchList = skyMap.findTractPatchList(coordList) for tractInfo, patchInfoList in tractPatchList: for patchInfo in patchInfoList: patchIndex = patchInfo.getIndex() print("tract=%d patch=%d,%d" % (tractInfo.getId(), patchIndex[0], patchIndex[1]))
def makeHSCExposure(self, galData, psfData, pixScale, variance): ny, nx = galData.shape exposure = afwImg.ExposureF(nx, ny) exposure.getMaskedImage().getImage().getArray()[:, :] = galData exposure.getMaskedImage().getVariance().getArray()[:, :] = variance #Set the PSF ngridPsf = psfData.shape[0] psfLsst = afwImg.ImageF(ngridPsf, ngridPsf) psfLsst.getArray()[:, :] = psfData psfLsst = psfLsst.convertD() kernel = afwMath.FixedKernel(psfLsst) kernelPSF = meaAlg.KernelPsf(kernel) exposure.setPsf(kernelPSF) #prepare the wcs #Rotation cdelt = (pixScale * afwGeom.arcseconds) CD = afwGeom.makeCdMatrix(cdelt, afwGeom.Angle(0.)) #no rotation #wcs crval = afwGeom.SpherePoint(afwGeom.Angle(0., afwGeom.degrees), afwGeom.Angle(0., afwGeom.degrees)) #crval = afwCoord.IcrsCoord(0.*afwGeom.degrees, 0.*afwGeom.degrees) # hscpipe6 crpix = afwGeom.Point2D(0.0, 0.0) dataWcs = afwGeom.makeSkyWcs(crpix, crval, CD) exposure.setWcs(dataWcs) #prepare the frc dataCalib = afwImg.makePhotoCalibFromCalibZeroPoint(63095734448.0194) exposure.setPhotoCalib(dataCalib) return exposure
def makeWcs(pixScale, nx, ny, rotation=0., raCen=180.0, decCen=0.0): """Create a TAN WCS with pixScale/nx/ny, plus rotation (degrees) and RA/Dec center (degrees). """ #Hardcoding TAN projection since this application is for focal plane size at most wcsFactory = WcsFactory(pixScale, 'TAN', rotation=rotation*afwGeom.radians) crpix_x = float(nx-1)/2. crpix_y = float(ny-1)/2. crval = afwCoord.Coord(afwGeom.Angle(raCen*afwGeom.degrees), afwGeom.Angle(decCen*afwGeom.degrees)) return wcsFactory.makeWcs(afwGeom.Point2D(crpix_x, crpix_y), crval)
def pixel(wcs, ra, dec): """ Use the Wcs object, wcs, to return the Pixel object corresponding to ra, dec, both in degrees. """ ra_angle = afwGeom.Angle(ra, afwGeom.degrees) dec_angle = afwGeom.Angle(dec, afwGeom.degrees) return wcs.skyToPixel(ra_angle, dec_angle)
def testCurvedFocalPlane(self): """Test a curved focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.03) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) # focal-plane position of ref position on detector (mm) fpPosition = afwGeom.Point2D(50, 25) # ref position on detector (pos of lower left corner) refPoint = afwGeom.Point2D(-0.5, -0.5) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToField = afwGeom.makeRadialTransform( (0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad)) pixelToField = pixelToFocalPlane.then(focalPlaneToField) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToField=focalPlaneToField, pixelSizeMm=pixelSizeMm, ) # the center point of the field angle frame should not move pixAtFieldCtr = pixelToField.applyInverse(afwGeom.Point2D(0, 0)) tanPixAtFieldCr = pixelToTanPixel.applyForward(pixAtFieldCtr) self.assertPairsAlmostEqual(pixAtFieldCtr, tanPixAtFieldCr) # build same camera geometry transforms without optical distortion focalPlaneToFieldNoDistortion = afwGeom.makeRadialTransform( (0.0, plateScaleRad)) pixelToFieldNoDistortion = pixelToFocalPlane.then( focalPlaneToFieldNoDistortion) for x in (100, 200, 1000): for y in (100, 500, 800): pixPos = afwGeom.Point2D(x, y) tanPixPos = pixelToTanPixel.applyForward(pixPos) # for a given field angle (which, together with a pointing, gives a position on the sky): # - field angle to pixels gives pixPos # - undistorted field angle to pixels gives tanPixPos fieldPos = pixelToField.applyForward(pixPos) desTanPixPos = pixelToFieldNoDistortion.applyInverse(fieldPos) # use a degraded accuracy because small Jacobian errors accumulate this far from the center self.assertPairsAlmostEqual(desTanPixPos, tanPixPos, maxDiff=1e-5)
def testCtor(self): self.assertEqual(self.pi, math.pi) self.assertEqual(self.pi, afwGeom.Angle(math.pi)) self.assertEqual(self.pi, self.d) dd = afwGeom.Angle(180, afwGeom.degrees) self.assertEqual(self.d, dd) dd = afwGeom.Angle(60*180, afwGeom.arcminutes) self.assertEqual(self.d, dd) dd = afwGeom.Angle(60*60*180, afwGeom.arcseconds) self.assertEqual(self.d, dd)
def makeOrientation(detectorConfig): """!Make an Orientation instance from a detector config @param detectorConfig config for this detector (an lsst.pex.config.Config) @return orientation (an lsst.afw.cameraGeom.Orientation) """ offset = afwGeom.Point2D(detectorConfig.offset_x, detectorConfig.offset_y) refPos = afwGeom.Point2D(detectorConfig.refpos_x, detectorConfig.refpos_y) yaw = afwGeom.Angle(detectorConfig.yawDeg, afwGeom.degrees) pitch = afwGeom.Angle(detectorConfig.pitchDeg, afwGeom.degrees) roll = afwGeom.Angle(detectorConfig.rollDeg, afwGeom.degrees) return Orientation(offset, refPos, yaw, pitch, roll)
def __init__(self, fpPosition = afwGeom.Point2D(0, 0), refPoint = afwGeom.Point2D(-0.5, -0.5), yaw = afwGeom.Angle(0), pitch = afwGeom.Angle(0), roll = afwGeom.Angle(0), ): self.fpPosition = fpPosition self.refPoint = refPoint self.yaw = yaw self.pitch = pitch self.roll = roll self.orient = Orientation(fpPosition, refPoint, yaw, pitch, roll)
def checkResults(self, fitRes, catsUpdated): """Check results @param[in] fitRes a object with two fields: - wcs fit TAN-SIP WCS, an lsst.afw.image.TanWcs - scatterOnSky median on-sky scatter, an lsst.afw.geom.Angle @param[in] catsUpdated if True then coord field of self.sourceCat and centroid fields of self.refCat have been updated """ self.assertLess(fitRes.scatterOnSky.asArcseconds(), 0.001) tanSipWcs = fitRes.wcs maxAngSep = afwGeom.Angle(0) maxPixSep = 0 refCoordKey = afwTable.CoordKey(self.refCat.schema["coord"]) if catsUpdated: refCentroidKey = afwTable.Point2DKey( self.refCat.schema["centroid"]) maxDistErr = afwGeom.Angle(0) for refObj, src, distRad in self.matches: srcPixPos = src.get(self.srcCentroidKey) refCoord = refObj.get(refCoordKey) if catsUpdated: refPixPos = refObj.get(refCentroidKey) srcCoord = src.get(self.srcCoordKey) else: refPixPos = tanSipWcs.skyToPixel(refCoord) srcCoord = tanSipWcs.pixelToSky(srcPixPos) angSep = refCoord.angularSeparation(srcCoord) dist = distRad * afwGeom.radians distErr = abs(dist - angSep) maxDistErr = max(maxDistErr, distErr) maxAngSep = max(maxAngSep, angSep) self.assertLess(angSep.asArcseconds(), 0.001) pixSep = math.hypot(*(srcPixPos - refPixPos)) maxPixSep = max(maxPixSep, pixSep) self.assertLess(pixSep, 0.001) print("max angular separation = %0.4f arcsec" % (maxAngSep.asArcseconds(), )) print("max pixel separation = %0.3f" % (maxPixSep, )) if catsUpdated: allowedDistErr = 1e-7 else: allowedDistErr = 0.001 self.assertLess( maxDistErr.asArcseconds(), allowedDistErr, "Computed distance in match list is off by %s arcsec" % (maxDistErr.asArcseconds(), ))
def get_hsc_regions(box_coords, butler=None): """ Get hsc regions within a polygonal region (box) of the sky. Here, hsc regions means the tracts and patches within the 'skybox'. Parameters ---------- box_coords : list of tuples The four coordinates for the box corners. This is the output of the skybox function. If only one coordinate is given, will return a single tract and patch. butler : Butler object, optional If None, then a will be created in this function. Default is None. Returns ------- regions : structured ndarray The tracts and patches within the skybox. The columns of the array are 'tract' and 'patch'. Note ---- This may give incorrect answers on regions that are larger than a tract, which is ~1.5 degree = 90 arcminute. """ import lsst.afw.coord as afwCoord import lsst.afw.geom as afwGeom if butler is None: import lsst.daf.persistence from myPipe import dataDIR butler = lsst.daf.persistence.Butler(dataDIR) if len(box_coords)==4: from toolbox.astro import angsep (ra1, dec1), (ra2, dec2) = box_coords[0], box_coords[2] if angsep(ra1, dec1, ra2, dec2, sepunits='arcmin') > 90.0: print('\n********* WARNING *********') print('Region larger than a tract') print('***************************\n') skymap = butler.get('deepCoadd_skyMap', immediate=True) coordList = [afwCoord.IcrsCoord(afwGeom.Angle(ra, afwGeom.degrees),\ afwGeom.Angle(dec, afwGeom.degrees)) for ra, dec in box_coords] tractPatchList = skymap.findClosestTractPatchList(coordList) regions = [] for tractInfo, patchInfoList in tractPatchList: for patchInfo in patchInfoList: patchIndex = patchInfo.getIndex() regions.append((tractInfo.getId(), str(patchIndex[0])+','+str(patchIndex[1]))) return np.array(regions, dtype=[('tract', int), ('patch', 'S4')])
def _minimumBoundingBox(self, wcs): """Calculate the minimum bounding box for the tract, given the WCS The bounding box is created in the frame of the supplied WCS, so that it's OK if the coordinates are negative. We compute the bounding box that holds all the vertices and the desired overlap. """ minBBoxD = afwGeom.Box2D() halfOverlap = self._tractOverlap / 2.0 for vertexCoord in self._vertexCoordList: vertexDeg = vertexCoord.getPosition(afwGeom.degrees) if self._tractOverlap == 0: minBBoxD.include(wcs.skyToPixel(vertexCoord)) else: numAngles = 24 angleIncr = afwGeom.Angle(360.0, afwGeom.degrees) / float(numAngles) for i in range(numAngles): offAngle = angleIncr * i offCoord = vertexCoord.clone() offCoord.offset(offAngle, halfOverlap) pixPos = wcs.skyToPixel(offCoord) minBBoxD.include(pixPos) return minBBoxD
def testAngleAliases(self): with self.assertWarns(FutureWarning): self.assertEqual(afwGeom.Angle(1), lsst.geom.Angle(1)) self.assertIs(afwGeom.radians, lsst.geom.radians) self.assertIs(afwGeom.degrees, lsst.geom.degrees) self.assertIs(afwGeom.hours, lsst.geom.hours) self.assertIs(afwGeom.arcminutes, lsst.geom.arcminutes) self.assertIs(afwGeom.arcseconds, lsst.geom.arcseconds) self.assertIs(afwGeom.PI, lsst.geom.PI) self.assertIs(afwGeom.TWOPI, lsst.geom.TWOPI) self.assertIs(afwGeom.HALFPI, lsst.geom.HALFPI) self.assertIs(afwGeom.ONE_OVER_PI, lsst.geom.ONE_OVER_PI) self.assertIs(afwGeom.SQRTPI, lsst.geom.SQRTPI) self.assertIs(afwGeom.INVSQRTPI, lsst.geom.INVSQRTPI) self.assertIs(afwGeom.ROOT2, lsst.geom.ROOT2) with self.assertWarns(FutureWarning): self.assertEqual(afwGeom.degToRad(1), lsst.geom.degToRad(1)) with self.assertWarns(FutureWarning): self.assertEqual(afwGeom.radToDeg(1), lsst.geom.radToDeg(1)) with self.assertWarns(FutureWarning): self.assertEqual(afwGeom.radToArcsec(1), lsst.geom.radToArcsec(1)) with self.assertWarns(FutureWarning): self.assertEqual(afwGeom.radToMas(1), lsst.geom.radToMas(1)) with self.assertWarns(FutureWarning): self.assertEqual(afwGeom.arcsecToRad(1), lsst.geom.arcsecToRad(1)) with self.assertWarns(FutureWarning): self.assertEqual(afwGeom.masToRad(1), lsst.geom.masToRad(1))
def __init__(self, result): """Set exposure information based on a query result from a db connection """ result = list(result) dataId = dict( run=result.pop(0), camcol=result.pop(0), field=result.pop(0), filter=result.pop(0), ) coordList = [IcrsCoord(afwGeom.Angle(result.pop(0), afwGeom.degrees), afwGeom.Angle(result.pop(0), afwGeom.degrees)) for i in range(4)] BaseExposureInfo.__init__(self, dataId=dataId, coordList=coordList) self.fluxMag0 = result.pop(0) self.fluxMag0Sigma = result.pop(0)
def testGetters(self): """Test getters """ ow = OrientationWrapper( fpPosition = afwGeom.Point2D(0.1, -0.2), refPoint = afwGeom.Point2D(-5.7, 42.3), yaw = afwGeom.Angle(-0.53), pitch = afwGeom.Angle(0.234), roll = afwGeom.Angle(1.2), ) for i in range(2): self.assertAlmostEquals(ow.fpPosition[i], ow.orient.getFpPosition()[i]) self.assertAlmostEquals(ow.refPoint[i], ow.orient.getReferencePoint()[i]) self.assertAlmostEquals(ow.yaw, ow.orient.getYaw()) self.assertAlmostEquals(ow.roll, ow.orient.getRoll()) self.assertAlmostEquals(ow.pitch, ow.orient.getPitch())
def setUp(self): self._NumTracts = 12 # Number of tracts to expect self._NeighborAngularSeparation = afwGeom.Angle(180.0, afwGeom.degrees) \ - _DihedralAngle # Tract separation self._SkyMapClass = DodecaSkyMap # Class of SkyMap to test self._SkyMapName = "dodeca" # Name of SkyMap class to test self._numNeighbors = 6 # Number of neighbours
def build_matched_dataset(repo, dataIds, matchRadius=None, safeSnr=50., useJointCal=False, skipTEx=False): blob = Blob('MatchedMultiVisitDataset') if not matchRadius: matchRadius = afwGeom.Angle(1, afwGeom.arcseconds) # Extract single filter blob['filterName'] = Datum(quantity=set([dId['filter'] for dId in dataIds]).pop(), description='Filter name') # Record important configuration blob['useJointCal'] = Datum( quantity=useJointCal, description='Whether jointcal/meas_mosaic calibrations were used') # Match catalogs across visits blob._catalog, blob._matchedCatalog = \ _loadAndMatchCatalogs(repo, dataIds, matchRadius, useJointCal=useJointCal, skipTEx=False) blob.magKey = blob._matchedCatalog.schema.find("base_PsfFlux_mag").key # Reduce catalogs into summary statistics. # These are the serialiable attributes of this class. _reduceStars(blob, blob._matchedCatalog, safeSnr) return blob
def __init__(self, config=None): """Construct a BaseSkyMap @param[in] config: an instance of self.ConfigClass; if None the default config is used """ if config is None: config = self.ConfigClass() config.freeze() # just to be sure, e.g. for pickling self.config = config self._tractInfoList = [] self._wcsFactory = detail.WcsFactory( pixelScale=afwGeom.Angle(self.config.pixelScale, afwGeom.arcseconds), projection=self.config.projection, rotation=afwGeom.Angle(self.config.rotation, afwGeom.degrees), )
def testCurvedFocalPlane(self): """Test a curved focal plane (with rectangular pixels) """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.03) plateScale = 25.0 # arcsec/mm yaw = afwGeom.Angle(20, afwGeom.degrees) fpPosition = afwGeom.Point2D(50, 25) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D(-0.5, -0.5) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform((0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad)) pixelToPupil = afwGeom.MultiXYTransform((pixelToFocalPlane, focalPlaneToPupil)) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToPupil=focalPlaneToPupil, pixelSizeMm=pixelSizeMm, ) # the center point of the pupil frame should not move pixAtPupilCtr = pixelToPupil.reverseTransform(afwGeom.Point2D(0, 0)) tanPixAtPupilCr = pixelToTanPixel.forwardTransform(pixAtPupilCtr) self.assertPairsNearlyEqual(pixAtPupilCtr, tanPixAtPupilCr) # build same camera geometry transforms without optical distortion focalPlaneToPupilNoDistortion = afwGeom.RadialXYTransform((0.0, plateScaleRad)) pixelToPupilNoDistortion = afwGeom.MultiXYTransform( (pixelToFocalPlane, focalPlaneToPupilNoDistortion)) for x in (100, 200, 1000): for y in (100, 500, 800): pixPos = afwGeom.Point2D(x, y) tanPixPos = pixelToTanPixel.forwardTransform(pixPos) # for a given pupil position (which, together with a pointing, gives a position on the sky): # - pupil to pixels gives pixPos # - undistorted pupil to pixels gives tanPixPos pupilPos = pixelToPupil.forwardTransform(pixPos) desTanPixPos = pixelToPupilNoDistortion.reverseTransform(pupilPos) self.assertPairsNearlyEqual(desTanPixPos, tanPixPos)
def __init__(self, result): """Set exposure information based on a query result from a db connection """ self._ind = -1 dataId = dict(raft=result[self._nextInd], visit=result[self._nextInd], sensor=result[self._nextInd], filter=result[self._nextInd]) coordList = [] for i in range(4): coordList.append( IcrsCoord( afwGeom.Angle(result[self._nextInd], afwGeom.degrees), afwGeom.Angle(result[self._nextInd], afwGeom.degrees), )) self.fwhm = result[self._nextInd] BaseExposureInfo.__init__(self, dataId, coordList)
def makeWcs(pixelScale=0.2 * afwGeom.arcseconds, crPixPos=(2000.0, 1520.5), crValDeg=(27.53, 87.123), posAng=afwGeom.Angle(0.0), doFlipX=False, projection="TAN", coordSys=afwCoord.ICRS, equinox=2000): """Make an simple TAN WCS with sensible defaults @param[in] pixelScale: desired scale, as sky/pixel, an afwGeom.Angle @param[in] crPixPos: crPix for WCS, using the LSST standard; a pair of floats @param[in] crValDeg: crVal for WCS, in degrees; a pair of floats @param[in] posAng: position angle (afwGeom.Angle) @param[in] doFlipX: flip X axis? @param[in] projection: WCS projection (e.g. "TAN" or "STG") @param[in] coordSys: coordinate system enum @param[in] equinox: date of equinox; should be 2000 for ICRS or GALACTIC """ if len(projection) != 3: raise RuntimeError("projection=%r; must have length 3" % (projection, )) csysPrefixes, radesys = { afwCoord.ICRS: (("RA", "DEC"), "ICRS"), afwCoord.FK5: (("RA", "DEC"), "FK5"), afwCoord.ECLIPTIC: (("ELON", "ELAT"), None), afwCoord.GALACTIC: (("GLON", "GLAT"), None), }[coordSys] ctypeList = [ ("%-4s-%3s" % (csysPrefixes[i], projection)).replace(" ", "-") for i in range(2) ] ps = dafBase.PropertySet() # convert pix position to FITS standard crPixFits = [ind + 1.0 for ind in crPixPos] posAngRad = posAng.asRadians() pixelScaleDeg = pixelScale.asDegrees() cdMat = np.array( [[math.cos(posAngRad), math.sin(posAngRad)], [-math.sin(posAngRad), math.cos(posAngRad)]], dtype=float) * pixelScaleDeg if doFlipX: cdMat[:, 0] = -cdMat[:, 0] for i in range(2): ip1 = i + 1 ps.add("CTYPE%1d" % (ip1, ), ctypeList[i]) ps.add("CRPIX%1d" % (ip1, ), crPixFits[i]) ps.add("CRVAL%1d" % (ip1, ), crValDeg[i]) if radesys: ps.add("RADESYS", radesys) ps.add("EQUINOX", equinox) ps.add("CD1_1", cdMat[0, 0]) ps.add("CD2_1", cdMat[1, 0]) ps.add("CD1_2", cdMat[0, 1]) ps.add("CD2_2", cdMat[1, 1]) return afwImage.makeWcs(ps)
def testSimpleCurvedFocalPlane(self): """Test a trivial curved focal plane with square pixels The CCD's lower left pixel is centered on the boresight pupil center = focal plane center CCD x is along focal plane x """ bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) pixelSizeMm = afwGeom.Extent2D(0.02, 0.02) plateScale = 25.0 # arcsec/mm yaw = 0 * afwGeom.degrees fpPosition = afwGeom.Point2D(0, 0) # focal-plane position of ref position on detector (mm) refPoint = afwGeom.Point2D(0, 0) # ref position on detector (pos of lower left corner) orientation = cameraGeom.Orientation( fpPosition, refPoint, yaw, ) pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm) plateScaleRad = afwGeom.Angle(plateScale, afwGeom.arcseconds).asRadians() focalPlaneToPupil = afwGeom.RadialXYTransform((0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad)) pixelToPupil = afwGeom.MultiXYTransform((pixelToFocalPlane, focalPlaneToPupil)) pixelToTanPixel = makePixelToTanPixel( bbox=bbox, orientation=orientation, focalPlaneToPupil=focalPlaneToPupil, pixelSizeMm=pixelSizeMm, ) # pupil center should be pixel position 0, 0 and tan pixel position 0, 0 pixAtPupilCtr = pixelToPupil.reverseTransform(afwGeom.Point2D(0, 0)) self.assertPairsNearlyEqual(pixAtPupilCtr, [0, 0]) tanPixAtPupilCr = pixelToTanPixel.forwardTransform(pixAtPupilCtr) self.assertPairsNearlyEqual(tanPixAtPupilCr, [0, 0]) # build same camera geometry transforms without optical distortion focalPlaneToPupilNoDistortion = afwGeom.RadialXYTransform((0.0, plateScaleRad)) pixelToPupilNoDistortion = afwGeom.MultiXYTransform( (pixelToFocalPlane, focalPlaneToPupilNoDistortion)) for x in (100, 200, 1000): for y in (100, 500, 800): pixPos = afwGeom.Point2D(x, y) tanPixPos = pixelToTanPixel.forwardTransform(pixPos) # pix to tan pix should be radial self.assertAlmostEqual( math.atan2(pixPos[1], pixPos[0]), math.atan2(tanPixPos[1], tanPixPos[0]), ) # for a given pupil angle (which, together with a pointing, gives a position on the sky): # - pupil to pixels gives pixPos # - undistorted pupil to pixels gives tanPixPos pupilPos = pixelToPupil.forwardTransform(pixPos) desTanPixPos = pixelToPupilNoDistortion.reverseTransform(pupilPos) self.assertPairsNearlyEqual(desTanPixPos, tanPixPos)