def setUp(self): rawPath = os.path.join(testDataDirectory, "hsc", "raw") calibPath = os.path.join(testDataDirectory, "hsc", "calib") self.repoPath = createDataRepository("lsst.obs.hsc.HscMapper", rawPath, calibPath) self.butler = dafPersist.Butler(root=self.repoPath, calibRoot=calibPath) # The following properties of the provided data are known a priori. self.visit = 904024 self.ccdNum = 50 self.filter = 'i' self.rawSize = (2144, 4241) self.ccdSize = (2048, 4176) self.exptime = 30.0 self.darktime = self.exptime # No explicit darktime dateBeg = DateTime(56598.26106374757, DateTime.MJD, DateTime.UTC) dateAvgNSec = dateBeg.nsecs() + int(0.5e9*self.exptime) self.dateAvg = DateTime(dateAvgNSec, DateTime.TAI) self.boresightRaDec = afwGeom.SpherePoint(320.7499250000, 0.500019444, degrees) self.boresightAzAlt = afwGeom.SpherePoint(226.68922661, 63.04359233, degrees) self.boresightAirmass = 1.121626027604189 self.boresightRotAngle = 270.0*degrees self.rotType = RotType.SKY self.obs_longitude = -155.476667*degrees self.obs_latitude = 19.825556*degrees self.obs_elevation = 4139 self.weath_airTemperature = MakeRawVisitInfo.centigradeFromKelvin(272.35) self.weath_airPressure = MakeRawVisitInfo.pascalFromMmHg(621.7) self.weath_humidity = 33.1 # NOTE: if we deal with DM-8053 and get UT1 implemented, ERA will change slightly. lst = 340.189608333*degrees self.era = lst - self.obs_longitude
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 setUp(self): rawPath = os.path.join(testDataDirectory, "hsc", "raw") calibPath = os.path.join(testDataDirectory, "hsc", "calib") self.repoPath = createDataRepository("lsst.obs.hsc.HscMapper", rawPath, calibPath) self.butler = dafPersist.Butler(root=self.repoPath, calibRoot=calibPath) # The following properties of the provided data are known a priori. self.visit = 904024 self.ccdNum = 50 self.filter = 'i' self.rawSize = (2144, 4241) self.ccdSize = (2048, 4176) self.exptime = 30.0 self.darktime = self.exptime # No explicit darktime self.dateAvg = DateTime(56598.26165414352, DateTime.MJD, DateTime.TAI) self.boresightRaDec = afwGeom.SpherePoint(320.7499250000, 0.500019444, degrees) self.boresightAzAlt = afwGeom.SpherePoint(226.68922661, 63.04359233, degrees) self.boresightAirmass = 1.121626027604189 self.boresightRotAngle = 270.0*degrees self.rotType = RotType.SKY self.obs_longitude = -155.476667*degrees self.obs_latitude = 19.825556*degrees self.obs_elevation = 4139 self.weath_airTemperature = -0.8 self.weath_airPressure = 62170. self.weath_humidity = 33.1 # NOTE: if we deal with DM-8053 and get UT1 implemented, ERA will change slightly. self.era = 2.3659570321481826*radians
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 = afwGeom.makeSkyWcs( crpix=afwGeom.Point2D(0, 0), crval=afwGeom.SpherePoint(359, 0, afwGeom.degrees), cdMatrix=afwGeom.makeCdMatrix(scale=1.0e-8*afwGeom.degrees), ) fromExp = afwImage.ExposureF(afwImage.MaskedImageF(1, 1), fromWcs) toWcs = afwGeom.makeSkyWcs( crpix=afwGeom.Point2D(0, 0), crval=afwGeom.SpherePoint(358, 0, afwGeom.degrees), cdMatrix=afwGeom.makeCdMatrix(scale=1.1e-8*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 calculateAstropyDcr(visitInfo, wcs, filterInfo, dcrNumSubfilters): """Calculate the DCR shift using astropy coordinate transformations. Parameters ---------- visitInfo : `lsst.afw.image.VisitInfo` VisitInfo for the exposure. wcs : `lsst.afw.geom.skyWcs.SkyWcs` A wcs that matches the inputs. filterInfo : `lsst.afw.image.Filter` The filter definition, set in the current instruments' obs package. dcrNumSubfilters : `int` Number of sub-filters used to model chromatic effects within a band. Returns ------- dcrShift : `tuple` of two `float` The 2D shift due to DCR, in pixels. Uses numpy axes ordering (Y, X). """ elevation = visitInfo.getBoresightAzAlt().getLatitude() azimuth = visitInfo.getBoresightAzAlt().getLongitude() lambdaEff = filterInfo.getFilterProperty().getLambdaEff() loc = EarthLocation(lat=visitInfo.getObservatory().getLatitude().asDegrees()*u.degree, lon=visitInfo.getObservatory().getLongitude().asDegrees()*u.degree, height=visitInfo.getObservatory().getElevation()*u.m) date = visitInfo.getDate() time = Time(date.get(date.MJD, date.TAI), format='mjd', location=loc, scale='tai') altaz = SkyCoord(alt=elevation.asDegrees(), az=azimuth.asDegrees(), unit='deg', obstime=time, frame='altaz', location=loc) # The DCR calculations are performed at the boresight ra0 = altaz.icrs.ra.degree*degrees dec0 = altaz.icrs.dec.degree*degrees x0, y0 = wcs.skyToPixel(afwGeom.SpherePoint(ra0, dec0)) dcrShift = [] # We divide the filter into "subfilters" with the full wavelength range # divided into equal sub-ranges. for wl0, wl1 in wavelengthGenerator(filterInfo, dcrNumSubfilters): # Note that diffRefractAmp can be negative, # since it is relative to the midpoint of the full band diffRefractAmp0 = differentialRefraction(wavelength=wl0, wavelengthRef=lambdaEff, elevation=elevation, observatory=visitInfo.getObservatory(), weather=visitInfo.getWeather()) diffRefractAmp1 = differentialRefraction(wavelength=wl1, wavelengthRef=lambdaEff, elevation=elevation, observatory=visitInfo.getObservatory(), weather=visitInfo.getWeather()) diffRefractAmp = (diffRefractAmp0 + diffRefractAmp1)/2. elevation1 = elevation + diffRefractAmp altaz = SkyCoord(alt=elevation1.asDegrees(), az=azimuth.asDegrees(), unit='deg', obstime=time, frame='altaz', location=loc) ra1 = altaz.icrs.ra.degree*degrees dec1 = altaz.icrs.dec.degree*degrees x1, y1 = wcs.skyToPixel(afwGeom.SpherePoint(ra1, dec1)) dcrShift.append((y1-y0, x1-x0)) return dcrShift
def testAssertSpherePointsAlmostEqual(self): """Test assertSpherePointsAlmostEqual""" for raDecDeg in ((45, 45), (-70, 89), (130, -89.5)): raDecDeg = [val * afwGeom.degrees for val in raDecDeg] sp0 = afwGeom.SpherePoint(*raDecDeg) self.assertSpherePointsAlmostEqual(sp0, sp0, maxSep=1e-7 * afwGeom.arcseconds) # make sure specifying msg is acceptable self.assertSpherePointsAlmostEqual(sp0, sp0, maxSep=1e-7 * afwGeom.arcseconds, msg="any") for offAng in (0, 45, 90): offAng = offAng * afwGeom.degrees for offDist in (0.001, 0.1): offDist = offDist * afwGeom.arcseconds sp1 = sp0.offset(bearing=offAng, amount=offDist) self.assertSpherePointsAlmostEqual(sp0, sp1, maxSep=offDist * 1.00001) with self.assertRaises(AssertionError): self.assertSpherePointsAlmostEqual(sp0, sp1, maxSep=offDist * 0.99999) # make sure msg is appended try: self.assertSpherePointsAlmostEqual(sp0, sp1, maxSep=offDist * 0.99999, msg="boo") self.fail("Sphere point lists should be unequal") except AssertionError as e: errMsg = e.args[0] self.assertTrue(errMsg.endswith("boo")) # test wraparound in RA sp2 = afwGeom.SpherePoint(raDecDeg[0] + 360 * afwGeom.degrees, raDecDeg[1]) self.assertSpherePointsAlmostEqual(sp0, sp2, maxSep=1e-7 * afwGeom.arcseconds)
def runDataRef(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 = [ afwGeom.SpherePoint(ra, 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 testAssertSpherePointListsAlmostEqual(self): """Test assertSpherePointListsAlmostEqual """ splist0 = [ afwGeom.SpherePoint(val[0] * afwGeom.degrees, val[1] * afwGeom.degrees) for val in ((45, 45), (-70, 89), (130, -89.5)) ] self.assertSpherePointListsAlmostEqual(splist0, splist0) offDist = 1.1 * afwGeom.arcseconds splist1 = [ sp0.offset(bearing=bearDeg * afwGeom.degrees, amount=offDist) for sp0, bearDeg in zip(splist0, (-10, 78, 123)) ] self.assertSpherePointListsAlmostEqual(splist0, splist1, maxSep=offDist * 1.00001) with self.assertRaises(AssertionError): self.assertSpherePointListsAlmostEqual(splist0, splist1, maxSep=offDist * 0.99999) # make sure msg is appended try: self.assertSpherePointListsAlmostEqual(splist0, splist1, maxSep=offDist * 0.99999, msg="boo") self.fail("Sphere point lists should be unequal") except AssertionError as e: errMsg = e.args[0] self.assertTrue(errMsg.endswith("boo"))
def setUp(self): self.crval = afwGeom.SpherePoint(44.0, 45.0, afwGeom.degrees) self.crpix = afwGeom.Point2D(15000, 4000) arcsecPerPixel = 1 / 3600.0 cdMatrix = afwGeom.makeCdMatrix(arcsecPerPixel * afwGeom.arcseconds) self.wcs = afwGeom.makeSkyWcs(crval=self.crval, crpix=self.crpix, cdMatrix=cdMatrix) refSchema = afwTable.SimpleTable.makeMinimalSchema() self.refCentroidKey = afwTable.Point2DKey.addFields( refSchema, "centroid", "centroid", "pixels") self.refCoordKey = afwTable.CoordKey(refSchema["coord"]) self.refHasCentroidKey = refSchema.addField("hasCentroid", type="Flag") self.refCat = afwTable.SimpleCatalog(refSchema) # an alias is required to make src.getCentroid() work; # simply defining a field named "slot_Centroid" doesn't suffice srcSchema = afwTable.SourceTable.makeMinimalSchema() self.srcCentroidKey = afwTable.Point2DKey.addFields( srcSchema, "base_SdssCentroid", "centroid", "pixels") srcAliases = srcSchema.getAliasMap() srcAliases.set("slot_Centroid", "base_SdssCentroid") self.srcCoordKey = afwTable.CoordKey(srcSchema["coord"]) self.sourceCat = afwTable.SourceCatalog(srcSchema)
def cutout_coadd_ra_dec(butler, ra, dec, filter='r', datasetType='deepCoadd', **kwargs): """ Produce a cutout from coadd from the given butler at the given RA, Dec in decimal degrees. Notes ----- Trivial wrapper around 'cutout_coadd_spherepoint' Parameters ---------- butler: lsst.daf.persistence.Butler Servant providing access to a data repository ra: float Right ascension of the center of the cutout, degrees dec: float Declination of the center of the cutout, degrees filter: string Filter of the image to load Returns ------- MaskedImage """ radec = afwGeom.SpherePoint(float(ra), float(dec), afwGeom.degrees) return cutout_coadd_spherepoint(butler, radec, filter=filter, datasetType=datasetType)
def joinMatchListWithCatalog(self, matchCat, sourceCat): """!Relink an unpersisted match list to sources and reference objects A match list is persisted and unpersisted as a catalog of IDs produced by afw.table.packMatches(), with match metadata (as returned by the astrometry tasks) in the catalog's metadata attribute. This method converts such a match catalog into a match list (an lsst.afw.table.ReferenceMatchVector) with links to source records and reference object records. @param[in] matchCat Unperisted packed match list (an lsst.afw.table.BaseCatalog). matchCat.table.getMetadata() must contain match metadata, as returned by the astrometry tasks. @param[in,out] sourceCat Source catalog (an lsst.afw.table.SourceCatalog). As a side effect, the catalog will be sorted by ID. @return the match list (an lsst.afw.table.ReferenceMatchVector) """ matchmeta = matchCat.table.getMetadata() version = matchmeta.getInt('SMATCHV') if version != 1: raise ValueError('SourceMatchVector version number is %i, not 1.' % version) filterName = matchmeta.getString('FILTER').strip() ctrCoord = afwGeom.SpherePoint(matchmeta.getDouble('RA'), matchmeta.getDouble('DEC'), afwGeom.degrees) rad = matchmeta.getDouble('RADIUS') * afwGeom.degrees refCat = self.loadSkyCircle(ctrCoord, rad, filterName).refCat refCat.sort() sourceCat.sort() return afwTable.unpackMatches(matchCat, refCat, sourceCat)
def _transformAndCheck(self, measConf, schema, transformTask): """Check the results of applying transformTask to a SourceCatalog. @param[in] measConf Measurement plugin configuration. @param[in] schema Input catalog schema. @param[in] transformTask Instance of TransformTask to be applied. For internal use by this test case. """ # There should now be one transformation registered per measurement plugin. self.assertEqual(len(measConf.plugins.names), len(transformTask.transforms)) # Rather than do a real measurement, we use a dummy source catalog # containing a source at an arbitrary position. inCat = afwTable.SourceCatalog(schema) r = inCat.addNew() r.setCoord(afwGeom.SpherePoint(0.0, 11.19, afwGeom.degrees)) r[PLUGIN_NAME] = 1.0 wcs, photoCalib = Placeholder(), Placeholder() outCat = transformTask.run(inCat, wcs, photoCalib) # Check that all sources have been transformed appropriately. for inSrc, outSrc in zip(inCat, outCat): self.assertEqual(outSrc[PLUGIN_NAME], inSrc[PLUGIN_NAME]) self.assertEqual(outSrc[PLUGIN_NAME + "_transform"], inSrc[PLUGIN_NAME] * -1.0) for field in transformTask.config.toDict()['copyFields']: self.assertEqual(outSrc.get(field), inSrc.get(field)) # Check that the wcs and photoCalib objects were accessed once per transform. self.assertEqual(wcs.count, len(transformTask.transforms)) self.assertEqual(photoCalib.count, len(transformTask.transforms))
def setUp(self): # define the position and size of one CCD in the focal plane self.pixelSizeMm = 0.024 # mm/pixel self.ccdOrientation = 5 * degrees # orientation of pixel w.r.t. focal plane self.plateScale = 0.15 * arcseconds # angle/pixel self.bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(2000, 4000)) self.crpix = afwGeom.Point2D(1000, 2000) self.crval = afwGeom.SpherePoint(10 * degrees, 40 * degrees) self.orientation = -45 * degrees self.scale = 1.0 * arcseconds # position of 0,0 pixel position in focal plane self.ccdPositionMm = afwGeom.Point2D(25.0, 10.0) self.pixelToFocalPlane = self.makeAffineTransform( offset=afwGeom.Extent2D(self.ccdPositionMm), rotation=self.ccdOrientation, scale=self.pixelSizeMm, ) cdMatrix = makeCdMatrix(scale=self.scale, orientation=self.orientation) self.tanWcs = makeSkyWcs(crpix=self.crpix, crval=self.crval, cdMatrix=cdMatrix) self.radPerMm = self.plateScale.asRadians( ) / self.pixelSizeMm # at center of field bboxD = afwGeom.Box2D(self.bbox) self.pixelPoints = bboxD.getCorners() self.pixelPoints.append(bboxD.getCenter())
def testTicket2872(self): """Test that CoaddPsf.getAveragePosition() is always a position at which we can call computeImage(). """ scale = 0.2 * afwGeom.arcseconds cdMatrix = afwGeom.makeCdMatrix(scale=scale) wcs = afwGeom.makeSkyWcs( crpix=afwGeom.Point2D(50, 50), crval=afwGeom.SpherePoint(45.0, 45.0, afwGeom.degrees), cdMatrix=cdMatrix, ) kernel = measAlg.DoubleGaussianPsf(7, 7, 2.0).getKernel() psf1 = measAlg.KernelPsf(kernel, afwGeom.Point2D(0, 50)) psf2 = measAlg.KernelPsf(kernel, afwGeom.Point2D(100, 50)) record1 = self.mycatalog.addNew() record1.setPsf(psf1) record1.setWcs(wcs) record1.setD(self.weightKey, 1.0) record1.setBBox( afwGeom.Box2I(afwGeom.Point2I(-40, 0), afwGeom.Point2I(40, 100))) record2 = self.mycatalog.addNew() record2.setPsf(psf2) record2.setWcs(wcs) record2.setD(self.weightKey, 1.0) record2.setBBox( afwGeom.Box2I(afwGeom.Point2I(60, 0), afwGeom.Point2I(140, 100))) coaddPsf = measAlg.CoaddPsf(self.mycatalog, wcs) naiveAvgPos = afwGeom.Point2D(50, 50) with self.assertRaises(pexExceptions.InvalidParameterError): coaddPsf.computeKernelImage(naiveAvgPos) # important test is that this doesn't throw: coaddPsf.computeKernelImage()
def test(self): schema = afwTable.ExposureTable.makeMinimalSchema() schema.addField("ccd", np.int32, doc="CCD number") schema.addField("visit", np.int32, doc="Visit number") schema.addField("goodpix", np.int32, doc="Number of good pixels") schema.addField("weight", float, doc="Weighting for this CCD") ccds = afwTable.ExposureCatalog(schema) scale = 1.0e-4*afwGeom.degrees wcs = afwGeom.makeSkyWcs(crpix=afwGeom.Point2D(0.0, 0.0), crval=afwGeom.SpherePoint(0.0, 0.0, afwGeom.degrees), cdMatrix=afwGeom.makeCdMatrix(scale=scale)) new = ccds.addNew() new.set("id", 0) new.set("bbox_min_x", 0) new.set("bbox_min_y", 0) new.set("bbox_max_x", 1024) new.set("bbox_max_y", 1024) # The following lines are critical for reproducing the bug, because # the code is reading a double starting at the 'ccd' (offset 24), and # it sees a zero (from the zero in 'ccd' and the leading zeros in 'visit'). new.set("ccd", 0) new.set("visit", 6789) new.set("goodpix", 987654321) new.set("weight", 1.0) new.setPsf(measAlg.SingleGaussianPsf(23, 23, 2.345)) new.setWcs(wcs) # In the presence of the bug, the following fails with # lsst::pex::exceptions::RuntimeError thrown in src/CoaddPsf.cc # with message: "Could not find a valid average position for CoaddPsf" measAlg.CoaddPsf(ccds, wcs)
def get_coadd_id_for_ra_dec(skymap, ra, dec): """ Return a dict suitable for use as a data ID for a DM Butler Parameters ---------- skymap: lsst.afw.skyMap.SkyMap [optional] Pass in to avoid the Butler read. Useful if you have lots of such reads. The skymap is just used to get the appropriate tract, patch. If you want to warp to a different frame, see `wcs`. ra: float Right ascension of the center of the cutout, degrees dec: float Declination of the center of the cutout, degrees Returns ------- dict - Suitable for use as a DM Butler data ID. """ # Look up the tract, patch for the RA, Dec radec = afwGeom.SpherePoint(ra, dec, afwGeom.degrees) tract_info = skymap.findTract(radec) patch_info = tract_info.findPatch(radec) coadd_id = { 'tract': tract_info.getId(), 'patch': "%d,%d" % patch_info.getIndex() } return coadd_id
def getExp(self, ra, dec, **kwargs): """Get the exposure and pixel position corresponding to sky position Parameters ----------- ra, dec : float Coordinates in degrees Returns ------- exp : afw.Exposure xy : afwCoord.PixelCoord Pixel coordinates in `exp` corresponding to ra, dec Additional keyword arguments passed to `_get_dataId`. """ dataId = self._get_dataId(ra, dec, **kwargs) exp = self._expFromId(dataId) if self.dmap is not None: obj = find_closest(self.dmap, ra, dec) ra, dec = obj.ra, obj.dec pos = afwGeom.SpherePoint(ra, dec, afwGeom.degrees) wcs = self._WcsFromId(dataId) xy = wcs.skyToPixel(pos) print(ra, dec, xy) return exp, xy
def display_cutout_image(butler, ra, dec, vmin=None, vmax=None, label=None, frame=None, display=None, backend='matplotlib', show=True, saveplot=False, savefits=False, old_matplotlib=False, filter='r', datasetType='deepCoadd'): """ Display a postage stamp for a given RA, Dec using LSST lsst.afw.display. Parameters ---------- backend: string Backend can be anything that lsst.afw.display and your =configuration supports: e.g. matplotlib, ds9, ginga, firefly. Returns ------- MaskedImage Notes ----- Parameters are the same as for make_cutout_image, except for the backend. You definitely have the matplotlib backend. ds9, ginga, and firefly can be set up but are non-trivial on the scale of a simple Notebook. """ cutout_image = cutout_coadd_ra_dec(butler, ra, dec, filter=filter, datasetType='deepCoadd') if savefits: if isinstance(savefits, str): filename = savefits else: filename = 'postage-stamp.fits' cutout_image.writeFits(filename) if display is None: display = afwDisplay.Display(frame=frame, backend=backend) radec = afwGeom.SpherePoint(ra, dec, afwGeom.degrees) xy = cutout_image.getWcs().skyToPixel(radec) display.mtv(cutout_image) display.scale("asinh", "zscale") display.dot('o', xy.getX(), xy.getY(), ctype='red') display.show_colorbar() return cutout_image
def cutout_from_exposure(src_image, ra, dec, width, height, unit="pixel"): """ Get the Exposure cutout including wcs headers. Parameters ---------- src_image : `afwImage.Exposure` the source image. ra : `float` in degrees. dec : `float` in degrees. width : int in pixels. height : int in pixels Returns ------- cutout : `afwImage.Exposure` """ if unit == "arcsec": # pixel scale is defined as Angle/pixel wcs = src_image.getWcs() ps = wcs.getPixelScale().asArcseconds() if ps != 0: width = width / ps height = height / ps else: raise Exception("Unexpected: pixel scale = 0") center = afwGeom.SpherePoint(ra, dec, afwGeom.degrees) size = afwGeom.Extent2I(width, height) cutout = src_image.getCutout(center, size) return cutout
def cutout_from_skymap_id(self, skymap_id, filt, center_x, center_y, center_unit, size_x, size_y, size_unit): """ Parameters ---------- skymap_id : string filt : filter center_x : float center_y : float center_unit : string [ 'px', 'pix', 'pixel', 'pixels', 'arcsec', 'arcmin', 'deg' ] size_x : float size_y : float size_unit : string [ 'px', 'pix', 'pixel', 'pixels', 'arcsec', 'arcmin', 'deg' ] Returns ------- lsst.afw.Image or None """ ra_deg, dec_deg = center_x, center_y width, height = size_x, size_y skymap = SkymapImage(self._butler, skymap_id, self._log) center_coord = afw_geom.SpherePoint(ra_deg, dec_deg, afw_geom.degrees) image = skymap.get(center_coord, width, height, filt, center_unit) return image
def setUp(self): # Construct an arbitrary WCS for testing. crval = afwGeom.SpherePoint(45.0, 45.0, afwGeom.degrees) scale = 0.2*afwGeom.arcseconds crpix = afwGeom.PointD(100, 100) self.wcs = afwGeom.makeSkyWcs(crpix=crpix, crval=crval, cdMatrix=afwGeom.makeCdMatrix(scale=scale))
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 makeVisitInfo(): """Return a non-NaN visitInfo.""" return afwImage.VisitInfo(exposureId=10313423, exposureTime=10.01, darkTime=11.02, date=dafBase.DateTime(65321.1, dafBase.DateTime.MJD, dafBase.DateTime.TAI), ut1=12345.1, era=45.1*afwGeom.degrees, boresightRaDec=afwGeom.SpherePoint(23.1, 73.2, afwGeom.degrees), boresightAzAlt=afwGeom.SpherePoint(134.5, 33.3, afwGeom.degrees), boresightAirmass=1.73, boresightRotAngle=73.2*afwGeom.degrees, rotType=afwImage.RotType.SKY, observatory=Observatory(11.1*afwGeom.degrees, 22.2*afwGeom.degrees, 0.333), weather=Weather(1.1, 2.2, 34.5), )
def makeMatches(self, refCat, srcCat, nSrc): for i in range(nSrc): refSrc = refCat.addNew() srcSrc = srcCat.addNew() raDeg, decDeg = np.random.randn(2) coord = afwGeom.SpherePoint(raDeg, decDeg, afwGeom.degrees) refSrc.set("g_flux", 10**(-0.4*18)) refSrc.set("r_flux", 10**(-0.4*18)) refSrc.set("resolved", False) refSrc.set("photometric", True) refSrc.setCoord(coord) srcSrc.setCoord(coord) srcSrc.set(srcSrc.getTable().getPsfFluxKey(), 10.) srcSrc.set(srcSrc.getTable().getPsfFluxErrKey(), 1.) for flag in self.sourceSelector.config.badFlags: srcSrc.set(flag, False) mc = afwTable.MatchControl() mc.symmetricMatch = False mat = afwTable.matchRaDec(refCat, srcCat, 1.0 * afwGeom.arcseconds, mc) self.assertEqual(len(mat), nSrc) return mat
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 testTransform(self): dims = afwGeom.Extent2I(512, 512) bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), dims) radius = 5 offset = afwGeom.Extent2D(123, 456) crval = afwGeom.SpherePoint(0 * afwGeom.degrees, 0 * afwGeom.degrees) crpix = afwGeom.Point2D(0, 0) cdMatrix = np.array([1.0e-5, 0.0, 0.0, 1.0e-5]) cdMatrix.shape = (2, 2) source = afwGeom.makeSkyWcs(crval=crval, crpix=crpix, cdMatrix=cdMatrix) target = afwGeom.makeSkyWcs(crval=crval, crpix=crpix + offset, cdMatrix=cdMatrix) sourceSpanSet = afwGeom.SpanSet.fromShape(radius, afwGeom.Stencil.CIRCLE) sourceSpanSet = sourceSpanSet.shiftedBy(12, 34) fpSource = afwDetect.Footprint(sourceSpanSet, bbox) fpTarget = fpSource.transform(source, target, bbox) self.assertEqual(len(fpSource.getSpans()), len(fpTarget.getSpans())) self.assertEqual(fpSource.getArea(), fpTarget.getArea()) imSource = afwImage.ImageU(dims) fpSource.spans.setImage(imSource, 1) imTarget = afwImage.ImageU(dims) fpTarget.spans.setImage(imTarget, 1) subSource = imSource.Factory(imSource, fpSource.getBBox()) subTarget = imTarget.Factory(imTarget, fpTarget.getBBox()) self.assertTrue(np.all(subSource.getArray() == subTarget.getArray())) # make a bbox smaller than the target footprint bbox2 = afwGeom.Box2I(fpTarget.getBBox()) bbox2.grow(-1) fpTarget2 = fpSource.transform(source, target, bbox2) # this one clips fpTarget3 = fpSource.transform(source, target, bbox2, False) # this one doesn't self.assertTrue(bbox2.contains(fpTarget2.getBBox())) self.assertFalse(bbox2.contains(fpTarget3.getBBox())) self.assertNotEqual(fpTarget.getArea(), fpTarget2.getArea()) self.assertEqual(fpTarget.getArea(), fpTarget3.getArea()) # Test that peakCatalogs get Transformed correctly truthList = [(x, y, 10) for x, y in zip(range(-2, 2), range(-1, 3))] for value in truthList: fpSource.addPeak(*value) scaleFactor = 2 linTrans = afwGeom.LinearTransform( np.matrix([[scaleFactor, 0], [0, scaleFactor]], dtype=float)) linTransFootprint = fpSource.transform(linTrans, fpSource.getBBox(), False) for peak, truth in zip(linTransFootprint.peaks, truthList): # Multiplied by two because that is the linear transform scaling # factor self.assertEqual(peak.getIx(), truth[0] * scaleFactor) self.assertEqual(peak.getIy(), truth[1] * scaleFactor)
def makeFakeWcs(): '''!Make a wcs to put in an exposure @return a Wcs object ''' return afwGeom.makeSkyWcs(crpix=afwGeom.Point2D(0.0, 0.0), crval=afwGeom.SpherePoint(45.0, 45.0, afwGeom.degrees), cdMatrix=afwGeom.makeCdMatrix(scale=1.0*afwGeom.degrees), )
def setUp(self): crval = afwGeom.SpherePoint(44, 45, afwGeom.degrees) crpix = afwGeom.Point2D(15000, 4000) scale = 1 * afwGeom.arcseconds cdMatrix = afwGeom.makeCdMatrix(scale=scale, flipX=True) self.tanWcs = afwGeom.makeSkyWcs(crpix=crpix, crval=crval, cdMatrix=cdMatrix) self.loadData()
def makeSimpleImage(): wcs = afwGeom.makeSkyWcs( crpix=afwGeom.Point2D(0, 0), crval=afwGeom.SpherePoint(0, 0, afwGeom.degrees), cdMatrix=afwGeom.makeCdMatrix(scale=2 * afwGeom.arcseconds), ) im = afwImage.ExposureF(100, 100, wcs) im.writeFits("simple.fits")
def _apply_cutout(self, data_id, src_img, ra, dec, width, height, unit="pixel"): """Return an image centered on ra and dec (in degrees) with dimensions height and width (in arcseconds by default). - Determine approximate pixels per arcsec in the image by calculating the length of line from the upper right corner of the image to the lower left corner in pixels and arcsecs. (This will fail at or very near the pole.) - Use that to define a box for the cutout. - Trim the box so it is entirely within the source image. Parameters ---------- src_img : `afwImage.Exposure` the source image. data_id : `dict` the image id. ra : float dec : float in degrees. height, width : float, float Height and width are in pixels, by default. Returns ------- cutout: `afwImage.Exposure` """ self._log.debug("apply_cutout %f %f %f %f", ra, dec, width, height) # False: do not remove FITS keywords from metadata wcs = None if isinstance(src_img, afwImage.Exposure): wcs = src_img.getWcs() elif data_id: # Get the metadata for the source image. metadata = self._metadata_from_data_id(data_id) wcs = afwGeom.makeSkyWcs(metadata, strip=False) if wcs is None: raise Exception("wcs missing in source image") radec = afwGeom.SpherePoint(ra, dec, afwGeom.degrees) xy_wcs = wcs.skyToPixel(radec) xy_center_x = xy_wcs.getX() xy_center_y = xy_wcs.getY() self._log.debug("ra=%f dec=%f xy_center=(%f,%f)", ra, dec, xy_center_x, xy_center_y) if unit == "arcsec": # pixel scale is defined as Angle/pixel ps = wcs.getPixelScale().asArcseconds() if ps != 0: width = width / ps height = height / ps else: self._log.debug("pixel scale = 0!") cutout = self.cutout_from_src(src_img, xy_center_x, xy_center_y, width, height, wcs) return cutout