Coverage for tests/test_hsm.py : 22%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
#!/usr/bin/env python # # LSST Data Management System # # Copyright 2008-2016 AURA/LSST. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see <https://www.lsstcorp.org/LegalNotices/>. #
# The following values are pulled directly from GalSim's test_hsm.py: # Note: expected results give shear for KSB and distortion for others, but the results below have # converted KSB expected results to distortion for the sake of consistency [0.467603106752, 0.381211727, 0.398856937, 0.401755571], [0.28618443944, 0.199222784, 0.233883543, 0.234257525], [0.271533794146, 0.158049396, 0.183517068, 0.184893412], [-0.293754156071, -0.457024541, 0.123946584, -0.609233462], [0.557720893779, 0.374143023, 0.714147448, 0.435404409]]) [-0.867225166489, -0.734855778, -0.777027588, -0.774684891], [-0.469354341577, -0.395520479, -0.502540961, -0.464466257], [-0.519775291311, -0.471589061, -0.574750641, -0.529664935], [0.345688365839, -0.342047099, 0.120603755, -0.44609129428863525], [0.525728304099, 0.370691830, 0.702724807, 0.433999442]]) [0.796144249, 0.835624917, 0.835624917, 0.827796187], [0.685023735, 0.699602704, 0.699602704, 0.659457638], [0.634736458, 0.651040481, 0.651040481, 0.614663396], [0.477027015, 0.477210752, 0.477210752, 0.423157447], [0.595205998, 0.611824797, 0.611824797, 0.563582092]]) [0.016924826, 0.014637648, 0.014637648, 0.014465546], [0.075769504, 0.073602324, 0.073602324, 0.064414520], [0.110253112, 0.106222900, 0.106222900, 0.099357106], [0.185276702, 0.184300955, 0.184300955, 0.173478300], [0.073020065, 0.070270966, 0.070270966, 0.061856263]]) # End of GalSim's values
# These values calculated using GalSim's HSM as part of GalSim [0.399292618036, 0.381213068962, 0.398856908083, 0.401749581099], [0.155929282308, 0.199228107929, 0.233882278204, 0.234371587634], [0.150018423796, 0.158052951097, 0.183515056968, 0.184561833739], [-2.6984937191, -0.457033962011, 0.123932465911, -0.60886412859], [0.33959621191, 0.374140143394, 0.713756918907, 0.43560180068], ]) [-0.74053555727, -0.734855830669, -0.777024209499, -0.774700462818], [-0.25573053956, -0.395517915487, -0.50251352787, -0.464388132095], [-0.287168383598, -0.471584022045, -0.574719130993, -0.5296921134], [3.1754450798, -0.342054128647, 0.120592080057, -0.446093201637], [0.320115834475, 0.370669454336, 0.702303349972, 0.433968126774], ]) [0.79614430666, 0.835625052452, 0.835625052452, 0.827822327614], [0.685023903847, 0.699601829052, 0.699601829052, 0.659438848495], [0.634736537933, 0.651039719582, 0.651039719582, 0.614759743214], [0.477026551962, 0.47721144557, 0.47721144557, 0.423227936029], [0.595205545425, 0.611821532249, 0.611821532249, 0.563564240932], ]) [0.0169247947633, 0.0146376201883, 0.0146376201883, 0.0144661813974], [0.0757696777582, 0.0736026018858, 0.0736026018858, 0.0644160583615], [0.110252402723, 0.106222368777, 0.106222368777, 0.0993555411696], [0.185278102756, 0.184301897883, 0.184301897883, 0.17346136272], [0.0730196461082, 0.0702708885074, 0.0702708885074, 0.0618583671749], ])
[2.24490427971, 0.336240686301, -0.627372910656], [1.9031778574, 0.150566105384, -0.245272792302], [1.77790760994, 0.112286123389, -0.286203939641], [1.45464873314, -0.155597168978, -0.102008266223], [1.63144648075, 0.22886961923, 0.228813588897], ]) [36.218247328, 20.5678722157], [20.325744838, 25.4176650386], [9.54257706283, 12.6134786199], [20.6407850048, 39.5864802706], [58.5008586442, 28.2850942049], ])
[2.40270376205, 0.197810277343, -0.372329413891, 3740.22436523, 36.4032272633, 20.4847916447], [1.89714717865, 0.046496052295, -0.0987404286861, 776.709594727, 20.2893584046, 25.4230368047], [1.77995181084, 0.0416346564889, -0.143147706985, 534.59197998, 9.51994111869, 12.6250775205], [1.46549296379, -0.0831127092242, -0.0628845766187, 348.294403076, 20.6242279632, 39.5941625731], [1.64031589031, 0.0867517963052, 0.0940798297524, 793.374450684, 58.4728765002, 28.2686937854], ])
print("Making plugin ", alg, name) if control is None: control = alg.ConfigClass() schema = afwTable.SourceTable.makeMinimalSchema() if centroid: schema.addField(centroid + "_x", type=float) schema.addField(centroid + "_y", type=float) schema.addField(centroid + "_flag", type='Flag') schema.getAliasMap().set("slot_Centroid", centroid) if metadata: plugin = alg(control, name, schema, PropertySet()) else: plugin = alg(control, name, schema) cat = afwTable.SourceCatalog(schema) if centroid: cat.defineCentroid(centroid) return plugin, cat
"""A test case for shape measurement"""
# load the known values self.dataDir = os.path.join(os.getenv('MEAS_EXTENSIONS_SHAPEHSM_DIR'), "tests", "data") self.bkgd = 1000.0 # standard for atlas image self.offset = geom.Extent2I(1234, 1234) self.xy0 = geom.Point2I(5678, 9876)
del self.offset del self.xy0
"""Run the measurement algorithm on an image""" # load the test image imgFile = os.path.join(self.dataDir, "image.%d.fits" % imageid) img = afwImage.ImageF(imgFile) img -= self.bkgd nx, ny = img.getWidth(), img.getHeight() msk = afwImage.Mask(geom.Extent2I(nx, ny), 0x0) var = afwImage.ImageF(geom.Extent2I(nx, ny), v) mimg = afwImage.MaskedImageF(img, msk, var) msk.getArray()[:] = np.where(np.fabs(img.getArray()) < 1.0e-8, msk.getPlaneBitMask("BAD"), 0)
# Put it in a bigger image, in case it matters big = afwImage.MaskedImageF(self.offset + mimg.getDimensions()) big.getImage().set(0) big.getMask().set(0) big.getVariance().set(v) subBig = afwImage.MaskedImageF(big, geom.Box2I(big.getXY0() + self.offset, mimg.getDimensions())) subBig <<= mimg mimg = big mimg.setXY0(self.xy0)
exposure = afwImage.makeExposure(mimg) cdMatrix = np.array([1.0/(2.53*3600.0), 0.0, 0.0, 1.0/(2.53*3600.0)]) cdMatrix.shape = (2, 2) exposure.setWcs(afwGeom.makeSkyWcs(crpix=geom.Point2D(1.0, 1.0), crval=geom.SpherePoint(0, 0, geom.degrees), cdMatrix=cdMatrix))
# load the corresponding test psf psfFile = os.path.join(self.dataDir, "psf.%d.fits" % imageid) psfImg = afwImage.ImageD(psfFile) psfImg -= self.bkgd
kernel = afwMath.FixedKernel(psfImg) kernelPsf = algorithms.KernelPsf(kernel) exposure.setPsf(kernelPsf)
# perform the shape measurement msConfig = base.SingleFrameMeasurementConfig() alg = base.SingleFramePlugin.registry[algorithmName].PluginClass.AlgClass control = base.SingleFramePlugin.registry[algorithmName].PluginClass.ConfigClass().makeControl() msConfig.algorithms.names = [algorithmName] # Note: It is essential to remove the floating point part of the position for the # Algorithm._apply. Otherwise, when the PSF is realised it will have been warped # to account for the sub-pixel offset and we won't get *exactly* this PSF. plugin, table = makePluginAndCat(alg, algorithmName, control, centroid="centroid") center = geom.Point2D(int(x), int(y)) + geom.Extent2D(self.offset + geom.Extent2I(self.xy0)) source = table.makeRecord() source.set("centroid_x", center.getX()) source.set("centroid_y", center.getY()) source.setFootprint(afwDetection.Footprint(afwGeom.SpanSet(exposure.getBBox(afwImage.PARENT)))) plugin.measure(source, exposure)
return source
"""Test that we can instantiate and play with a measureShape"""
nFail = 0 msg = ""
for (algNum, algName), (i, imageid) in itertools.product(enumerate(correction_methods), enumerate(file_indices)): algorithmName = "ext_shapeHSM_HsmShape" + algName[0:1].upper() + algName[1:].lower()
source = self.runMeasurement(algorithmName, imageid, x_centroid[i], y_centroid[i], sky_var[i])
########################################## # see how we did if algName in ("KSB"): # Need to convert g1,g2 --> e1,e2 because GalSim has done that # for the expected values ("for consistency") g1 = source.get(algorithmName + "_g1") g2 = source.get(algorithmName + "_g2") scale = 2.0/(1.0 + g1**2 + g2**2) e1 = g1*scale e2 = g2*scale sigma = source.get(algorithmName + "_sigma") else: e1 = source.get(algorithmName + "_e1") e2 = source.get(algorithmName + "_e2") sigma = 0.5*source.get(algorithmName + "_sigma") resolution = source.get(algorithmName + "_resolution") flags = source.get(algorithmName + "_flag")
tests = [ # label known-value measured tolerance ["e1", float(e1_expected[i][algNum]), e1, 0.5*10**-SHAPE_DECIMALS], ["e2", float(e2_expected[i][algNum]), e2, 0.5*10**-SHAPE_DECIMALS], ["resolution", float(resolution_expected[i][algNum]), resolution, 0.5*10**-SIZE_DECIMALS],
# sigma won't match exactly because # we're using skyvar=mean(var) instead of measured value ... expected a difference ["sigma", float(sigma_e_expected[i][algNum]), sigma, 0.07], ["shapeStatus", 0, flags, 0], ]
for test in tests: label, know, hsm, limit = test err = hsm - know msgTmp = "%-12s %s %5s: %6.6f %6.6f (val-known) = %.3g\n" % (algName, imageid, label, know, hsm, err) if not np.isfinite(err) or abs(err) > limit: msg += msgTmp nFail += 1
self.assertAlmostEqual(g1 if algName in ("KSB") else e1, galsim_e1[i][algNum], SHAPE_DECIMALS) self.assertAlmostEqual(g2 if algName in ("KSB") else e2, galsim_e2[i][algNum], SHAPE_DECIMALS) self.assertAlmostEqual(resolution, galsim_resolution[i][algNum], SIZE_DECIMALS) self.assertAlmostEqual(sigma, galsim_err[i][algNum], delta=0.07)
self.assertEqual(nFail, 0, "\n"+msg)
for (i, imageid) in enumerate(file_indices): source = self.runMeasurement("ext_shapeHSM_HsmSourceMoments", imageid, x_centroid[i], y_centroid[i], sky_var[i]) x = source.get("ext_shapeHSM_HsmSourceMoments_x") y = source.get("ext_shapeHSM_HsmSourceMoments_y") xx = source.get("ext_shapeHSM_HsmSourceMoments_xx") yy = source.get("ext_shapeHSM_HsmSourceMoments_yy") xy = source.get("ext_shapeHSM_HsmSourceMoments_xy")
# Centroids from GalSim use the FITS lower-left corner of 1,1 offset = self.xy0 + self.offset self.assertAlmostEqual(x - offset.getX(), centroid_expected[i][0] - 1, 3) self.assertAlmostEqual(y - offset.getY(), centroid_expected[i][1] - 1, 3)
expected = afwEll.Quadrupole(afwEll.SeparableDistortionDeterminantRadius( moments_expected[i][1], moments_expected[i][2], moments_expected[i][0]))
self.assertAlmostEqual(xx, expected.getIxx(), SHAPE_DECIMALS) self.assertAlmostEqual(xy, expected.getIxy(), SHAPE_DECIMALS) self.assertAlmostEqual(yy, expected.getIyy(), SHAPE_DECIMALS)
for (i, imageid) in enumerate(file_indices): source = self.runMeasurement("ext_shapeHSM_HsmSourceMomentsRound", imageid, x_centroid[i], y_centroid[i], sky_var[i]) x = source.get("ext_shapeHSM_HsmSourceMomentsRound_x") y = source.get("ext_shapeHSM_HsmSourceMomentsRound_y") xx = source.get("ext_shapeHSM_HsmSourceMomentsRound_xx") yy = source.get("ext_shapeHSM_HsmSourceMomentsRound_yy") xy = source.get("ext_shapeHSM_HsmSourceMomentsRound_xy") flux = source.get("ext_shapeHSM_HsmSourceMomentsRound_Flux")
# Centroids from GalSim use the FITS lower-left corner of 1,1 offset = self.xy0 + self.offset self.assertAlmostEqual(x - offset.getX(), round_moments_expected[i][4] - 1, 3) self.assertAlmostEqual(y - offset.getY(), round_moments_expected[i][5] - 1, 3)
expected = afwEll.Quadrupole(afwEll.SeparableDistortionDeterminantRadius( round_moments_expected[i][1], round_moments_expected[i][2], round_moments_expected[i][0])) self.assertAlmostEqual(xx, expected.getIxx(), SHAPE_DECIMALS) self.assertAlmostEqual(xy, expected.getIxy(), SHAPE_DECIMALS) self.assertAlmostEqual(yy, expected.getIyy(), SHAPE_DECIMALS)
self.assertAlmostEqual(flux, round_moments_expected[i][3], SHAPE_DECIMALS)
for width in (2.0, 3.0, 4.0): psf = afwDetection.GaussianPsf(35, 35, width) exposure = afwImage.ExposureF(45, 56) exposure.getMaskedImage().set(1.0, 0, 1.0) exposure.setPsf(psf)
# perform the shape measurement msConfig = base.SingleFrameMeasurementConfig() msConfig.algorithms.names = ["ext_shapeHSM_HsmPsfMoments"] plugin, cat = makePluginAndCat(lsst.meas.extensions.shapeHSM.HsmPsfMomentsAlgorithm, "ext_shapeHSM_HsmPsfMoments", centroid="centroid", control=lsst.meas.extensions.shapeHSM.HsmPsfMomentsControl()) source = cat.addNew() source.set("centroid_x", 23) source.set("centroid_y", 34) offset = geom.Point2I(23, 34) tmpSpans = afwGeom.SpanSet.fromShape(int(width), offset=offset) source.setFootprint(afwDetection.Footprint(tmpSpans)) plugin.measure(source, exposure) x = source.get("ext_shapeHSM_HsmPsfMoments_x") y = source.get("ext_shapeHSM_HsmPsfMoments_y") xx = source.get("ext_shapeHSM_HsmPsfMoments_xx") yy = source.get("ext_shapeHSM_HsmPsfMoments_yy") xy = source.get("ext_shapeHSM_HsmPsfMoments_xy")
self.assertAlmostEqual(x, 0.0, 3) self.assertAlmostEqual(y, 0.0, 3)
expected = afwEll.Quadrupole(afwEll.Axes(width, width, 0.0))
self.assertAlmostEqual(xx, expected.getIxx(), SHAPE_DECIMALS) self.assertAlmostEqual(xy, expected.getIxy(), SHAPE_DECIMALS) self.assertAlmostEqual(yy, expected.getIyy(), SHAPE_DECIMALS)
lsst.utils.tests.init()
lsst.utils.tests.init() unittest.main() |