def testIgnoreKeywords(self): """Check that certain keywords are ignored in read/write of headers""" # May not appear at all in the FITS file (cfitsio doesn't write these by default) notAtAll = [ # FITS core keywords "GCOUNT", "PCOUNT", "XTENSION", "BSCALE", "BZERO", "TZERO", "TSCAL", # FITS compression keywords "ZBITPIX", "ZIMAGE", "ZCMPTYPE", "ZSIMPLE", "ZEXTEND", "ZBLANK", "ZDATASUM", "ZHECKSUM", "ZNAXIS", "ZTILE", "ZNAME", "ZVAL", "ZQUANTIZ", # Not essential these be excluded, but will prevent fitsverify warnings "DATASUM", "CHECKSUM", ] # Additional keywords to check; these should go straight through # Some of these are longer/shorter versions of strings above, # to test that the checks for just the start of strings is working. others = ["FOOBAR", "SIMPLETN", "DATASUMX", "NAX", "SIM"] header = PropertyList() for ii, key in enumerate(self.single + notAtAll + others): header.add(key, ii) metadata = self.writeAndRead(header) for key in self.single: self.assertEqual(metadata.valueCount(key), 1, key) for key in notAtAll: self.assertEqual(metadata.valueCount(key), 0, key) for key in others: self.assertEqual(metadata.valueCount(key), 1, key)
def __init__(self, camera=None, detector=None, log=None, **kwargs): self._instrument = None self._raftName = None self._slotName = None self._detectorName = None self._detectorSerial = None self._detectorId = None self._filter = None self._calibId = None self._metadata = PropertyList() self.setMetadata(PropertyList()) self.calibInfoFromDict(kwargs) # Define the required attributes for this calibration. self.requiredAttributes = set(["_OBSTYPE", "_SCHEMA", "_VERSION"]) self.requiredAttributes.update([ "_instrument", "_raftName", "_slotName", "_detectorName", "_detectorSerial", "_detectorId", "_filter", "_calibId", "_metadata" ]) self.log = log if log else logging.getLogger(__name__) if detector: self.fromDetector(detector) self.updateMetadata(camera=camera, detector=detector)
def __init__(self, camera=None, detector=None, log=None, **kwargs): self._instrument = None self._raftName = None self._slotName = None self._detectorName = None self._detectorSerial = None self._detectorId = None self._filter = None self._calibId = None self._metadata = PropertyList() self.setMetadata(PropertyList()) self.calibInfoFromDict(kwargs) # Define the required attributes for this calibration. self.requiredAttributes = set(['_OBSTYPE', '_SCHEMA', '_VERSION']) self.requiredAttributes.update([ '_instrument', '_raftName', '_slotName', '_detectorName', '_detectorSerial', '_detectorId', '_filter', '_calibId', '_metadata' ]) self.log = log if log else Log.getLogger(__name__.partition(".")[2]) if detector: self.fromDetector(detector) self.updateMetadata(camera=camera, detector=detector)
def testReadOldTanFits(self): """Test reading a FITS file containing data for an lsst::afw::image::TanWcs That file was made using the same metadata follows (like self.metadata without the distortion) """ tanMetadata = PropertyList() # the following was fit using CreateWcsWithSip from meas_astrom # and is valid over this bbox: (minimum=(0, 0), maximum=(3030, 3030)) # This same metadata was used to create testdata/oldTanSipwWs.fits for name, value in ( ("RADESYS", "ICRS"), ("CTYPE1", "RA---TAN"), ("CTYPE2", "DEC--TAN"), ("CRPIX1", 1531.1824767147), ("CRPIX2", 1531.1824767147), ("CRVAL1", 43.035511801383), ("CRVAL2", 44.305697682784), ("CUNIT1", "deg"), ("CUNIT2", "deg"), ("CD1_1", 0.00027493991598151), ("CD1_2", -3.2758487104158e-06), ("CD2_1", 3.2301310675830e-06), ("CD2_2", 0.00027493937506632), ): tanMetadata.set(name, value) dataDir = os.path.join(os.path.split(__file__)[0], "data") filePath = os.path.join(dataDir, "oldTanWcs.fits") wcsFromFits = SkyWcs.readFits(filePath) wcsFromMetadata = makeSkyWcs(tanMetadata) bbox = Box2D(Point2D(-1000, -1000), Extent2D(3000, 3000)) self.assertWcsAlmostEqualOverBBox(wcsFromFits, wcsFromMetadata, bbox)
def testBasics(self): """Check basic formatting and skipping bad values """ metadata = PropertyList() dataList = [ ("ABOOL", True), ("AFLOAT", 1.2e25), ("ANINT", -5), ("LONGNAME1", 1), # name is longer than 8 characters; skip it ("LONGSTR", "skip this item because the formatted value " "is too long: longer than 80 characters "), ("ASTRING1", "value for string"), ] for name, value in dataList: metadata.set(name, value) header = makeLimitedFitsHeader(metadata) expectedLines = [ # without padding to 80 chars "ABOOL = 1", "AFLOAT = 1.2E+25", "ANINT = -5", "ASTRING1= 'value for string'", ] expectedHeader = "".join("%-80s" % val for val in expectedLines) self.assertEqual(header, expectedHeader) self.checkExcludeNames(metadata, expectedLines)
def testArrayValues(self): """Check that only the final value is used from an array """ metadata = PropertyList() # work around DM-13232 by setting ABOOL one value at a time for value in [True, True, True, False]: metadata.add("ABOOL", value) dataList = [ ("AFLOAT", [1.2e25, -5.6]), ("ANINT", [-5, 752, 1052]), ("ASTRING1", ["value for string", "more"]), ] for name, value in dataList: metadata.set(name, value) header = makeLimitedFitsHeader(metadata) expectedLines = [ # without padding to 80 chars "ABOOL = F", "AFLOAT = -5.6", "ANINT = 1052", "ASTRING1= 'more'", ] expectedHeader = "".join("%-80s" % val for val in expectedLines) self.assertHeadersEqual(header, expectedHeader) self.checkExcludeNames(metadata, expectedLines)
def testSetVisitInfoMetadataMissingValues(self): """If a value is unknown then it should not be written to the metadata""" visitInfo = afwImage.VisitInfo() # only rot type is known metadata = PropertyList() afwImage.setVisitInfoMetadata(metadata, visitInfo) self.assertEqual(metadata.getScalar("ROTTYPE"), RotTypeEnumNameDict[afwImage.RotType.UNKNOWN]) self.assertEqual(metadata.nameCount(), 1)
def testDecoratedImage(self): image = self.maskedImage.getImage() decoImage = afwImage.DecoratedImageF(image) metadata = PropertyList() metadata.set("FOO", "BAR") decoImage.setMetadata(metadata) exposure = exposureFromImage(decoImage) self.assertImagesEqual(exposure.getMaskedImage().getImage(), image) md = exposure.getMetadata() self.assertEqual(md.get("FOO"), "BAR")
def testCD_PC(self): """Test that we can read a FITS file with both CD and PC keys (like early Suprimecam files)""" md = PropertyList() for k, v in ( ("EQUINOX", 2000.0), ("RADESYS", "ICRS"), ("CRPIX1", 5353.0), ("CRPIX2", -35.0), ("CD1_1", 0.0), ("CD1_2", -5.611E-05), ("CD2_1", -5.611E-05), ("CD2_2", -0.0), ("CRVAL1", 4.5789875), ("CRVAL2", 16.30004444), ("CUNIT1", "deg"), ("CUNIT2", "deg"), ("CTYPE1", "RA---TAN"), ("CTYPE2", "DEC--TAN"), ("CDELT1", -5.611E-05), ("CDELT2", 5.611E-05), ): md.set(k, v) wcs = makeSkyWcs(md, strip=False) pixPos = Point2D(1000, 2000) pred_skyPos = SpherePoint(4.459815023498577 * degrees, 16.544199850984768 * degrees) skyPos = wcs.pixelToSky(pixPos) self.assertSpherePointsAlmostEqual(skyPos, pred_skyPos) for badPC in (False, True): for k, v in ( ("PC001001", 0.0), ("PC001002", -1.0 if badPC else 1.0), ("PC002001", 1.0 if badPC else -1.0), ("PC002002", 0.0), ): md.set(k, v) # Check Greisen and Calabretta A&A 395 1061 (2002), Eq. 3 if not badPC: for i in ( 1, 2, ): for j in ( 1, 2, ): self.assertEqual( md.get("CD%d_%d" % (i, j)), md.get("CDELT%d" % i) * md.get("PC00%d00%d" % (i, j))) wcs2 = makeSkyWcs(md, strip=False) skyPos2 = wcs2.pixelToSky(pixPos) self.assertSpherePointsAlmostEqual(skyPos2, pred_skyPos)
def make_dm_wcs(galsim_wcs): """ convert galsim wcs to stack wcs Parameters ---------- galsim_wcs: galsim WCS Should be TAN or TAN-SIP Returns ------- DM Stack sky wcs """ if galsim_wcs.wcs_type == 'TAN': crpix = galsim_wcs.crpix # DM uses 0 offset, galsim uses FITS 1 offset stack_crpix = Point2D(crpix[0] - 1, crpix[1] - 1) cd_matrix = galsim_wcs.cd crval = geom.SpherePoint( galsim_wcs.center.ra / coord.radians, galsim_wcs.center.dec / coord.radians, geom.radians, ) stack_wcs = makeSkyWcs( crpix=stack_crpix, crval=crval, cdMatrix=cd_matrix, ) elif galsim_wcs.wcs_type == 'TAN-SIP': # No currently supported # this works with the 1-offset assumption from galsim # # this is not used if the lower bounds are 1, but the extra keywords # GS_{X,Y}MIN are set which we will remove below fake_bounds = galsim.BoundsI(1, 10, 1, 10) hdr = {} galsim_wcs.writeToFitsHeader(hdr, fake_bounds) del hdr["GS_XMIN"] del hdr["GS_YMIN"] metadata = PropertyList() for key, value in hdr.items(): metadata.set(key, value) stack_wcs = makeSkyWcs(metadata) return stack_wcs
def testDecoratedImageBadWcs(self): """Test that exposureFromImage() attaches a None wcs to the exposure when the WCS cannot be constructed """ image = self.maskedImage.getImage() decoImage = afwImage.DecoratedImageF(image) metadata = PropertyList() metadata.set("CTYPE1", "RA---TPV") metadata.set("CTYPE2", "DEC--TPV") decoImage.setMetadata(metadata) exposure = exposureFromImage(decoImage) self.assertIs(exposure.getWcs(), None)
def testDecoratedImageBadWcs(self): """Test that exposureFromImage() attaches a None wcs to the exposure when makeWcs() raises an invalidParameter error """ image = self.maskedImage.getImage() decoImage = afwImage.DecoratedImageF(image) metadata = PropertyList() metadata.set("CTYPE1", "RA---TPV") metadata.set("CTYPE2", "DEC--TPV") decoImage.setMetadata(metadata) exposure = exposureFromImage(decoImage) self.assertIs(exposure.getWcs(), None)
def testIgnoreKeywords(self): """Check that certain keywords are ignored in read/write of headers""" # May appear only once in the FITS file (because cfitsio will insist on putting them there) single = ["SIMPLE", "BITPIX", "EXTEND", "NAXIS"] # May not appear at all in the FITS file (cfitsio doesn't write these by default) notAtAll = [ # FITS core keywords "GCOUNT", "PCOUNT", "XTENSION", "BSCALE", "BZERO", "TZERO", "TSCAL", # FITS compression keywords "ZBITPIX", "ZIMAGE", "ZCMPTYPE", "ZSIMPLE", "ZEXTEND", "ZBLANK", "ZDATASUM", "ZHECKSUM", "ZNAXIS", "ZTILE", "ZNAME", "ZVAL", # Not essential these be excluded, but will prevent fitsverify warnings "DATASUM", "CHECKSUM", ] # Additional keywords to check; these should go straight through # Some of these are longer/shorter versions of strings above, # to test that the checks for just the start of strings is working. others = ["FOOBAR", "SIMPLETN", "DATASUMX", "NAX", "SIM"] header = PropertyList() for ii, key in enumerate(single + notAtAll + others): header.add(key, ii) fitsFile = lsst.afw.fits.MemFileManager() with lsst.afw.fits.Fits(fitsFile, "w") as fits: fits.createEmpty() fits.writeMetadata(header) with lsst.afw.fits.Fits(fitsFile, "r") as fits: metadata = fits.readMetadata() for key in single: self.assertEqual(metadata.valueCount(key), 1, key) for key in notAtAll: self.assertEqual(metadata.valueCount(key), 0, key) for key in others: self.assertEqual(metadata.valueCount(key), 1, key)
def addRefCatMetadata(catalog): """Add metadata to a new (not yet populated) reference catalog. Parameters ---------- catalog : `lsst.afw.table.SimpleCatalog` Catalog to which metadata should be attached. Will be modified in-place. """ md = catalog.getMetadata() if md is None: md = PropertyList() md.set("REFCAT_FORMAT_VERSION", LATEST_FORMAT_VERSION) catalog.setMetadata(md)
def testGetSipMatrixFromMetadata(self): """Test getSipMatrixFromMetadata and makeSipMatrixMetadata """ for badName in ("X", "AA"): self.assertFalse(hasSipMatrix(self.metadata, badName)) with self.assertRaises(TypeError): getSipMatrixFromMetadata(self.metadata, badName) for name in ("A", "B", "AP", "BP"): self.assertTrue(hasSipMatrix(self.metadata, name)) sipMatrix = getSipMatrixFromMetadata(self.metadata, name) width = self.metadata.getScalar("%s_ORDER" % (name, )) + 1 self.assertEqual(sipMatrix.shape, (width, width)) for i in range(width): for j in range(width): # SIP matrix terms use 0-based indexing cardName = "%s_%d_%d" % (name, i, j) if self.metadata.exists(cardName): self.assertEqual(sipMatrix[i, j], self.metadata.getScalar(cardName)) else: self.assertEqual(sipMatrix[i, j], 0.0) metadata = makeSipMatrixMetadata(sipMatrix, name) for name in metadata.names(False): value = metadata.getScalar(name) if (name.endswith("ORDER")): self.assertEqual(width, value + 1) else: self.assertEqual(value, self.metadata.getScalar(name)) self.assertNotEqual(value, 0.0) # 0s are omitted # try metadata with only the ORDER keyword; the matrix should be all zeros # except for the invalid case of order < 0 for order in (-3, -1, 0, 3): metadata2 = PropertyList() metadata2.set("W_ORDER", order) if order < 0: # invalid order self.assertFalse(hasSipMatrix(metadata2, "W")) with self.assertRaises(TypeError): getSipMatrixFromMetadata(metadata2, "W") else: self.assertTrue(hasSipMatrix(metadata2, "W")) zeroMatrix = getSipMatrixFromMetadata(metadata2, "W") self.assertEqual(zeroMatrix.shape, (order + 1, order + 1)) for i in range(order + 1): for j in range(order + 1): self.assertEqual(zeroMatrix[i, j], 0.0)
def testGetSipMatrixFromMetadata(self): """Test getSipMatrixFromMetadata and makeSipMatrixMetadata """ for badName in ("X", "AA"): self.assertFalse(hasSipMatrix(self.metadata, badName)) with self.assertRaises(TypeError): getSipMatrixFromMetadata(self.metadata, badName) for name in ("A", "B", "AP", "BP"): self.assertTrue(hasSipMatrix(self.metadata, name)) sipMatrix = getSipMatrixFromMetadata(self.metadata, name) width = self.metadata.getScalar("%s_ORDER" % (name,)) + 1 self.assertEqual(sipMatrix.shape, (width, width)) for i in range(width): for j in range(width): # SIP matrix terms use 0-based indexing cardName = "%s_%d_%d" % (name, i, j) if self.metadata.exists(cardName): self.assertEqual(sipMatrix[i, j], self.metadata.getScalar(cardName)) else: self.assertEqual(sipMatrix[i, j], 0.0) metadata = makeSipMatrixMetadata(sipMatrix, name) for name in metadata.names(False): value = metadata.getScalar(name) if (name.endswith("ORDER")): self.assertEqual(width, value + 1) else: self.assertEqual(value, self.metadata.getScalar(name)) self.assertNotEqual(value, 0.0) # 0s are omitted # try metadata with only the ORDER keyword; the matrix should be all zeros # except for the invalid case of order < 0 for order in (-3, -1, 0, 3): metadata2 = PropertyList() metadata2.set("W_ORDER", order) if order < 0: # invalid order self.assertFalse(hasSipMatrix(metadata2, "W")) with self.assertRaises(TypeError): getSipMatrixFromMetadata(metadata2, "W") else: self.assertTrue(hasSipMatrix(metadata2, "W")) zeroMatrix = getSipMatrixFromMetadata(metadata2, "W") self.assertEqual(zeroMatrix.shape, (order + 1, order + 1)) for i in range(order + 1): for j in range(order + 1): self.assertEqual(zeroMatrix[i, j], 0.0)
def testMultiPlaneFitsReaders(self): """Run tests for MaskedImageFitsReader and ExposureFitsReader. """ metadata = PropertyList() metadata.add("FIVE", 5) metadata.add("SIX", 6.0) wcs = makeSkyWcs(Point2D(2.5, 3.75), SpherePoint(40.0*degrees, 50.0*degrees), np.array([[1E-5, 0.0], [0.0, -1E-5]])) defineFilter("test_readers_filter", lambdaEff=470.0) calib = PhotoCalib(2.5E4) psf = GaussianPsf(21, 21, 8.0) polygon = Polygon(Box2D(self.bbox)) apCorrMap = ApCorrMap() visitInfo = VisitInfo(exposureTime=5.0) transmissionCurve = TransmissionCurve.makeIdentity() coaddInputs = CoaddInputs(ExposureTable.makeMinimalSchema(), ExposureTable.makeMinimalSchema()) detector = DetectorWrapper().detector record = coaddInputs.ccds.addNew() record.setWcs(wcs) record.setCalib(calib) record.setPsf(psf) record.setValidPolygon(polygon) record.setApCorrMap(apCorrMap) record.setVisitInfo(visitInfo) record.setTransmissionCurve(transmissionCurve) record.setDetector(detector) for n, dtypeIn in enumerate(self.dtypes): with self.subTest(dtypeIn=dtypeIn): exposureIn = Exposure(self.bbox, dtype=dtypeIn) shape = exposureIn.image.array.shape exposureIn.image.array[:, :] = np.random.randint(low=1, high=5, size=shape) exposureIn.mask.array[:, :] = np.random.randint(low=1, high=5, size=shape) exposureIn.variance.array[:, :] = np.random.randint(low=1, high=5, size=shape) exposureIn.setMetadata(metadata) exposureIn.setWcs(wcs) exposureIn.setFilter(Filter("test_readers_filter")) exposureIn.setCalib(calib) exposureIn.setPsf(psf) exposureIn.getInfo().setValidPolygon(polygon) exposureIn.getInfo().setApCorrMap(apCorrMap) exposureIn.getInfo().setVisitInfo(visitInfo) exposureIn.getInfo().setTransmissionCurve(transmissionCurve) exposureIn.getInfo().setCoaddInputs(coaddInputs) exposureIn.setDetector(detector) with lsst.utils.tests.getTempFilePath(".fits") as fileName: exposureIn.writeFits(fileName) self.checkMaskedImageFitsReader(exposureIn, fileName, self.dtypes[n:]) self.checkExposureFitsReader(exposureIn, fileName, self.dtypes[n:])
def _makeStamps(self, nStamps, stampSize): randState = np.random.RandomState(42) stampList = [] for i in range(nStamps): stamp = afwImage.maskedImage.MaskedImageF(stampSize, stampSize) stamp.image.array += randState.rand(stampSize, stampSize) stamp.mask.array += 10 stamp.variance.array += 100 stampList.append(stamp) ras = np.arange(nStamps) decs = np.arange(nStamps) + 5 centX = np.arange(nStamps) + 20 centY = np.arange(nStamps) + 25 detectorNames = ["R22_S11"] * nStamps camNames = ["LSSTCam"] * nStamps dfcTypes = [DefocalType.Extra.value] * nStamps halfStampIdx = int(nStamps / 2) dfcTypes[:halfStampIdx] = [DefocalType.Intra.value] * halfStampIdx metadata = PropertyList() metadata["RA_DEG"] = ras metadata["DEC_DEG"] = decs metadata["CENT_X"] = centX metadata["CENT_Y"] = centY metadata["DET_NAME"] = detectorNames metadata["CAM_NAME"] = camNames metadata["DFC_TYPE"] = dfcTypes return stampList, metadata
def __init__(self, table=None, detector=None, override=False, log=None): self._detectorName = None self._detectorSerial = None self._detectorId = None self._metadata = PropertyList() self.linearityCoeffs = dict() self.linearityType = dict() self.linearityThreshold = dict() self.linearityMaximum = dict() self.linearityUnits = dict() self.linearityBBox = dict() self.fitParams = dict() self.fitParamsErr = dict() self.linearityFitReducedChiSquared = dict() self.override = override self.populated = False self.log = log self.tableData = None if table is not None: if len(table.shape) != 2: raise RuntimeError( "table shape = %s; must have two dimensions" % (table.shape, )) if table.shape[1] < table.shape[0]: raise RuntimeError("table shape = %s; indices are switched" % (table.shape, )) self.tableData = np.array(table, order="C") if detector: self.fromDetector(detector)
def make_stamps(n_stamps=3, use_archive=False): stampSize = 25 # create dummy stamp stamps stampImages = [ afwImage.maskedImage.MaskedImageF(stampSize, stampSize) for _ in range(n_stamps) ] for stampIm in stampImages: stampImArray = stampIm.image.array stampImArray += np.random.rand(stampSize, stampSize) stampMaskArray = stampIm.mask.array stampMaskArray += 10 stampVarArray = stampIm.variance.array stampVarArray += 1000. ras = np.random.rand(n_stamps) * 360. decs = np.random.rand(n_stamps) * 180 - 90 archive_elements = [ tF.makeTransform(geom.AffineTransform(np.random.rand(2))) if use_archive else None for _ in range(n_stamps) ] stamp_list = [ stamps.Stamp(stamp_im=stampIm, position=geom.SpherePoint(geom.Angle(ra, geom.degrees), geom.Angle(dec, geom.degrees)), archive_element=ae) for stampIm, ra, dec, ae in zip( stampImages, ras, decs, archive_elements) ] metadata = PropertyList() metadata['RA_DEG'] = ras metadata['DEC_DEG'] = decs return stamps.Stamps(stamp_list, metadata=metadata, use_archive=True)
def make_stamps(n_stamps=3): stampSize = 25 # create dummy stamp stamps stampImages = [ afwImage.maskedImage.MaskedImageF(stampSize, stampSize) for _ in range(n_stamps) ] for stampIm in stampImages: stampImArray = stampIm.image.array stampImArray += np.random.rand(stampSize, stampSize) stampMaskArray = stampIm.mask.array stampMaskArray += 10 stampVarArray = stampIm.variance.array stampVarArray += 1000. ras = np.random.rand(n_stamps) * 360. decs = np.random.rand(n_stamps) * 180 - 90 stamp_list = [ stamps.Stamp(stamp_im=stampIm, position=geom.SpherePoint(geom.Angle(ra, geom.degrees), geom.Angle(dec, geom.degrees))) for stampIm, ra, dec in zip(stampImages, ras, decs) ] metadata = PropertyList() metadata['RA_DEG'] = ras metadata['DEC_DEG'] = decs return stamps.Stamps(stamp_list, metadata=metadata)
def testIO(self): """Test the class' write and readFits methods. The ``options`` argument to the read method is only used to read sub-BBoxes, which is handled by the Butler. Tests of this are done in afw. """ with tempfile.NamedTemporaryFile() as f: self.bss.writeFits(f.name) options = PropertyList() bss2 = brightStarStamps.BrightStarStamps.readFitsWithOptions( f.name, options) self.assertEqual(len(self.bss), len(bss2)) for mi1, mi2 in zip(self.bss.getMaskedImages(), bss2.getMaskedImages()): self.assertMaskedImagesAlmostEqual(mi1, mi2) np.testing.assert_almost_equal(self.bss.getMagnitudes(), bss2.getMagnitudes()) np.testing.assert_almost_equal(self.bss.getAnnularFluxes(), bss2.getAnnularFluxes()) for id1, id2 in zip(self.bss.getGaiaIds(), bss2.getGaiaIds()): self.assertEqual(id1, id2) for pos1, pos2 in zip(self.bss.getPositions(), bss2.getPositions()): self.assertEqual(pos1[0], pos2[0]) self.assertEqual(pos1[1], pos2[1]) self.assertEqual(bss2.nb90Rots, self.nb90Rots)
def testFlagDefinitions(self): """ Check flag order. Flags must be added to the flag handler in the same order that they are defined in the algorithm. """ control = photKron.KronFluxControl() name = "kronTest" schema = afwTable.SourceTable.makeMinimalSchema() algMeta = PropertyList() # Add the output fields -- including flags -- to the schema. photKron.KronFluxAlgorithm(control, name, schema, algMeta) # Fetch a list of all flag fields, in the order that they were added # to the schema (and hence the order they were added to the FlagHandler) flagFieldNames = schema.extract("%s_flag*" % (name,), ordered=True).keys() # Iterate over each flag field, checking that they were enumerated in # the algorithm in the same order as in the FlagHandler. for i, flagFieldName in enumerate(flagFieldNames): if flagFieldName == "%s_flag" % (name,): # The generic "failure" flag is written into the schema as $name_flag. self.assertEqual(i, photKron.KronFluxAlgorithm.FAILURE.number) else: # Other flags are referenced by name. We assert that the # enumeration name (e.g. BAD_RADIUS) is an upper-case version # of the schema field name (e.g. flag_bad_radius), with the # "flag_" prefix stripped. flagName = flagFieldName.split(getTableDelimeter(schema), 2)[-1] self.assertEqual(i, getattr(photKron.KronFluxAlgorithm, flagName.upper()).number) # Check that the number of enumerated flags matches the number of flag # fields in the schema. self.assertEqual(len(photKron.KronFluxAlgorithm.getFlagDefinitions()), len(flagFieldNames))
def __init__(self, ctrCoord, radius, filterName): """!Ctor @param[in] ctrCoord: Coordinates of center (lsst.afw.coord.IcrsCoord) @param[in] radius: Minimum radius for selecting sources (lsst.afw.geom.Angle) @param[in] filterName: Name of filter (str) or None """ PropertyList.__init__(self) ctrCoord = ctrCoord.toIcrs() self.add('RA', ctrCoord.getRa().asDegrees(), 'field center in degrees') self.add('DEC', ctrCoord.getDec().asDegrees(), 'field center in degrees') self.add('RADIUS', radius.asDegrees(), 'field radius in degrees, minimum') self.add('SMATCHV', 1, 'SourceMatchVector version number') filterName = "UNKNOWN" if filterName is None else str(filterName) self.add('FILTER', filterName, 'filter name for photometric data')
def testReadFitsWithOptionsMetadataError(self): """Test that error is raised when STAMPCLS returns None """ with tempfile.NamedTemporaryFile() as f: ss = make_stamps() emptyMetadata = PropertyList() stamps.writeFits(f.name, [ss[0]], emptyMetadata, None, True, True) with self.assertRaises(RuntimeError): stamps.StampsBase.readFits(f.name)
def getTanWcsMetata(): metadata = PropertyList() for name, value in ( ("RADESYS", "ICRS"), ("CTYPE1", "RA---TAN"), ("CTYPE2", "DEC--TAN"), ("CRPIX1", 1531.1824767147), ("CRPIX2", 1531.1824767147), ("CRVAL1", 43.035511801383), ("CRVAL2", 44.305697682784), ("CUNIT1", "deg"), ("CUNIT2", "deg"), ("CD1_1", 0.00027493991598151), ("CD1_2", -3.2758487104158e-06), ("CD2_1", 3.2301310675830e-06), ("CD2_2", 0.00027493937506632), ): metadata.set(name, value) return metadata
def testGetCdMatrixFromMetadata(self): cdMatrix = getCdMatrixFromMetadata(self.metadata) for i in range(2): for j in range(2): cardName = "CD%d_%d" % (i + 1, j + 1) self.assertEqual(cdMatrix[i, j], self.metadata.getScalar(cardName)) metadata = PropertyList() with self.assertRaises(TypeError): getCdMatrixFromMetadata(metadata) metadata.add("CD2_1", 0.56) # just one term, with an arbitrary value cdMatrix2 = getCdMatrixFromMetadata(metadata) for i in range(2): for j in range(2): # CD matrix terms use 1-based indexing cardName = "CD%d_%d" % (i + 1, j + 1) if i == 1 and j == 0: self.assertEqual(cdMatrix2[i, j], 0.56) else: self.assertEqual(cdMatrix2[i, j], 0.0)
def testGetCdMatrixFromMetadata(self): cdMatrix = getCdMatrixFromMetadata(self.metadata) for i in range(2): for j in range(2): cardName = "CD%d_%d" % (i + 1, j + 1) self.assertEqual(cdMatrix[i, j], self.metadata.get(cardName)) metadata = PropertyList() with self.assertRaises(TypeError): getCdMatrixFromMetadata(metadata) metadata.add("CD2_1", 0.56) # just one term, with an arbitrary value cdMatrix2 = getCdMatrixFromMetadata(metadata) for i in range(2): for j in range(2): # CD matrix terms use 1-based indexing cardName = "CD%d_%d" % (i + 1, j + 1) if i == 1 and j == 0: self.assertEqual(cdMatrix2[i, j], 0.56) else: self.assertEqual(cdMatrix2[i, j], 0.0)
def setUp(self): metadata = PropertyList() for name, value in ( ("RADESYS", "ICRS"), ("EQUINOX", 2000.), ("CRVAL1", 215.604025685476), ("CRVAL2", 53.1595451514076), ("CRPIX1", 1109.99981456774), ("CRPIX2", 560.018167811613), ("CTYPE1", "RA---TAN"), ("CTYPE2", "DEC--TAN"), ("CUNIT1", "deg"), ("CUNIT2", "deg"), ("CD1_1", 5.10808596133527E-05), ("CD1_2", 1.85579539217196E-07), ("CD2_2", -5.10281493481982E-05), ("CD2_1", -1.85579539217196E-07), ): metadata.set(name, value) self.metadata = metadata
def make_stack_wcs(wcs): """ convert galsim tan wcs to stack wcs """ if wcs.wcs_type == 'TAN': crpix = wcs.crpix stack_crpix = geom.Point2D(crpix[0], crpix[1]) cd_matrix = wcs.cd crval = geom.SpherePoint( wcs.center.ra / coord.radians, wcs.center.dec / coord.radians, geom.radians, ) stack_wcs = makeSkyWcs( crpix=stack_crpix, crval=crval, cdMatrix=cd_matrix, ) elif wcs.wcs_type == 'TAN-SIP': import galsim # this is not used if the lower bounds are 1, but the extra keywords # GS_{X,Y}MIN are set which we will remove below fake_bounds = galsim.BoundsI(1, 10, 1, 10) hdr = {} wcs.writeToFitsHeader(hdr, fake_bounds) del hdr["GS_XMIN"] del hdr["GS_YMIN"] metadata = PropertyList() for key, value in hdr.items(): metadata.set(key, value) stack_wcs = makeSkyWcs(metadata) return stack_wcs
def testBasics(self): """Check basic formatting and skipping bad values """ metadata = PropertyList() dataList = [ ("ABOOL", True), ("AFLOAT", 1.2e25), ("AFLOAT2", 1.0e30), ("ANINT", -5), ("AFLOATZ", 0.0), # ensure a float stays a float ("INTFLOAT", -5.0), ("LONGFLT", 0.0089626337538440005), ("ANUNDEF", None), ("LONGNAME1", 1), # name is longer than 8 characters; skip it ("LONGSTR", "skip this item because the formatted value " "is too long: longer than 80 characters "), ("ASTRING1", "value for string"), ("ANAN", float("NaN")) ] for name, value in dataList: metadata.set(name, value) header = makeLimitedFitsHeader(metadata) expectedLines = [ # without padding to 80 chars "ABOOL = T", "AFLOAT = 1.2E+25", "AFLOAT2 = 1E+30", "ANINT = -5", "AFLOATZ = 0.0", "INTFLOAT= -5.0", "LONGFLT = 0.0089626337538440005", "ANUNDEF =", "ASTRING1= 'value for string'", "ANAN =", ] expectedHeader = "".join("%-80s" % val for val in expectedLines) self.assertHeadersEqual(header, expectedHeader) self.checkExcludeNames(metadata, expectedLines)
def testSinglePrecision(self): """Check that single precision floats do work""" metadata = PropertyList() # Numeric form of single precision floats need smaller precision metadata.setFloat("SINGLE", 3.14159) metadata.setFloat("SINGLEI", 5.0) metadata.setFloat("SINGLEE", -5.9e20) metadata.setFloat("EXP", -5e10) header = makeLimitedFitsHeader(metadata) expectedLines = [ # without padding to 80 chars "SINGLE = 3.14159", "SINGLEI = 5.0", "SINGLEE = -5.9E+20", "EXP = -5E+10", ] expectedHeader = "".join("%-80s" % val for val in expectedLines) self.assertHeadersEqual(header, expectedHeader, rtol=np.finfo(np.float32).resolution)
def testMultiPlaneFitsReaders(self): """Run tests for MaskedImageFitsReader and ExposureFitsReader. """ metadata = PropertyList() metadata.add("FIVE", 5) metadata.add("SIX", 6.0) wcs = makeSkyWcs(Point2D(2.5, 3.75), SpherePoint(40.0 * degrees, 50.0 * degrees), np.array([[1E-5, 0.0], [0.0, -1E-5]])) defineFilter("test_readers_filter", lambdaEff=470.0) calib = PhotoCalib(2.5E4) psf = GaussianPsf(21, 21, 8.0) polygon = Polygon(Box2D(self.bbox)) apCorrMap = ApCorrMap() visitInfo = VisitInfo(exposureTime=5.0) transmissionCurve = TransmissionCurve.makeIdentity() coaddInputs = CoaddInputs(ExposureTable.makeMinimalSchema(), ExposureTable.makeMinimalSchema()) detector = DetectorWrapper().detector record = coaddInputs.ccds.addNew() record.setWcs(wcs) record.setPhotoCalib(calib) record.setPsf(psf) record.setValidPolygon(polygon) record.setApCorrMap(apCorrMap) record.setVisitInfo(visitInfo) record.setTransmissionCurve(transmissionCurve) record.setDetector(detector) for n, dtypeIn in enumerate(self.dtypes): with self.subTest(dtypeIn=dtypeIn): exposureIn = Exposure(self.bbox, dtype=dtypeIn) shape = exposureIn.image.array.shape exposureIn.image.array[:, :] = np.random.randint(low=1, high=5, size=shape) exposureIn.mask.array[:, :] = np.random.randint(low=1, high=5, size=shape) exposureIn.variance.array[:, :] = np.random.randint(low=1, high=5, size=shape) exposureIn.setMetadata(metadata) exposureIn.setWcs(wcs) exposureIn.setFilter(Filter("test_readers_filter")) exposureIn.setFilterLabel( FilterLabel(physical="test_readers_filter")) exposureIn.setPhotoCalib(calib) exposureIn.setPsf(psf) exposureIn.getInfo().setValidPolygon(polygon) exposureIn.getInfo().setApCorrMap(apCorrMap) exposureIn.getInfo().setVisitInfo(visitInfo) exposureIn.getInfo().setTransmissionCurve(transmissionCurve) exposureIn.getInfo().setCoaddInputs(coaddInputs) exposureIn.setDetector(detector) with lsst.utils.tests.getTempFilePath(".fits") as fileName: exposureIn.writeFits(fileName) self.checkMaskedImageFitsReader(exposureIn, fileName, self.dtypes[n:]) self.checkExposureFitsReader(exposureIn, fileName, self.dtypes[n:])
def testBasics(self): """Check basic formatting and skipping bad values """ metadata = PropertyList() dataList = [ ("ABOOL", True), ("AFLOAT", 1.2e25), ("AFLOAT2", 1.0e30), ("ANINT", -5), ("AFLOATZ", 0.0), # ensure a float stays a float ("INTFLOAT", -5.0), ("LONGFLT", 0.0089626337538440005), ("ANUNDEF", None), ("LONGNAME1", 1), # name is longer than 8 characters; skip it ("LONGSTR", "skip this item because the formatted value " "is too long: longer than 80 characters "), ("ASTRING1", "value for string"), ] for name, value in dataList: metadata.set(name, value) header = makeLimitedFitsHeader(metadata) expectedLines = [ # without padding to 80 chars "ABOOL = T", "AFLOAT = 1.2E+25", "AFLOAT2 = 1E+30", "ANINT = -5", "AFLOATZ = 0.0", "INTFLOAT= -5.0", "LONGFLT = 0.0089626337538440005", "ANUNDEF =", "ASTRING1= 'value for string'", ] expectedHeader = "".join("%-80s" % val for val in expectedLines) self.assertHeadersEqual(header, expectedHeader) self.checkExcludeNames(metadata, expectedLines)
def testSimpleIO(self): """Check that a simple header can be written and read back.""" expected = { "ASTRING": "Test String", "ANUNDEF": None, "AFLOAT": 3.1415, "ANINT": 42, } header = PropertyList() for k, v in expected.items(): header[k] = v output = self.writeAndRead(header) # Remove keys added by cfitsio for k in self.single: if k in output: del output[k] if "COMMENT" in output: del output["COMMENT"] self.assertEqual(output.toDict(), header.toDict())
def testNextMemIdAndCensus(self): memId0 = Citizen.getNextMemId() self.assertEqual(Citizen.census(0, memId0), 0) a = PropertyList() self.assertEqual(Citizen.census(0, memId0), 1) self.assertEqual(a.census(0, memId0), 1) memId1 = a.getNextMemId() b = PropertyList() self.assertEqual(Citizen.census(0, memId0), 2) self.assertEqual(a.census(0, memId0), 2) self.assertEqual(Citizen.census(0, memId1), 1) self.assertEqual(a.census(0, memId1), 1) del b self.assertEqual(Citizen.census(0, memId0), 1) self.assertEqual(a.census(0, memId0), 1) self.assertEqual(Citizen.census(0, memId1), 0) self.assertEqual(a.census(0, memId1), 0) del a self.assertEqual(Citizen.census(0, memId0), 0)
def makePropertyListFromDict(md): result = PropertyList() for k, v in md.items(): result.add(k, v) return result
def createMatchMetadata(exposure): """Create metadata required for unpersisting a match list @param[in] exposure exposure for which to create metadata @return metadata about the field (a daf_base PropertyList) """ matchMeta = PropertyList() bboxd = Box2D(exposure.getBBox()) ctrPos = bboxd.getCenter() wcs = getDistortedWcs(exposure.getInfo()) ctrCoord = wcs.pixelToSky(ctrPos).toIcrs() llCoord = wcs.pixelToSky(bboxd.getMin()) approxRadius = ctrCoord.angularSeparation(llCoord) matchMeta.add('RA', ctrCoord.getRa().asDegrees(), 'field center in degrees') matchMeta.add('DEC', ctrCoord.getDec().asDegrees(), 'field center in degrees') matchMeta.add('RADIUS', approxRadius.asDegrees(), 'field radius in degrees, approximate') matchMeta.add('SMATCHV', 1, 'SourceMatchVector version number') filterName = exposure.getFilter().getName() or None if filterName is not None and filterName not in ("_unknmown_", ""): matchMeta.add('FILTER', filterName, 'filter name for tagalong data') return matchMeta
def setUp(self): """Constructs a CCD with two amplifiers and prepares for ISR""" np.random.seed(12345) baseValue = 100.0 gain = 1.0 readNoise = 123456789.0 saturation = 987654321.0 height = 234 imageSize = Extent2I(123, height) overscanSize = Extent2I(16, height) self.sigma = 1.234 # Set up the various regions overscan1 = Box2I(Point2I(0, 0), overscanSize) image1 = Box2I(Point2I(overscanSize[0], 0), imageSize) image2 = Box2I(Point2I(overscanSize[0] + imageSize[0], 0), imageSize) overscan2 = Box2I(Point2I(overscanSize[0] + 2*imageSize[0], 0), overscanSize) leftBox = Box2I(overscan1.getMin(), Extent2I(overscan1.getWidth() + image1.getWidth(), height)) rightBox = Box2I(image2.getMin(), Extent2I(image2.getWidth() + overscan2.getWidth(), height)) target1 = Box2I(Point2I(0, 0), imageSize) target2 = Box2I(Point2I(image1.getWidth(), 0), imageSize) # Set the pixels exposure = ExposureF(Box2I(Point2I(0, 0), Extent2I(imageSize[0]*2 + overscanSize[0]*2, height))) yy = np.arange(0, height, 1, dtype=np.float32) leftImage = ExposureF(exposure, leftBox) leftImage.image.array[:] = baseValue + yy[:, np.newaxis] rightImage = ExposureF(exposure, rightBox) rightImage.image.array[:] = baseValue - yy[:, np.newaxis] leftOverscan = ExposureF(exposure, overscan1) leftOverscan.image.array += np.random.normal(0.0, self.sigma, leftOverscan.image.array.shape) rightOverscan = ExposureF(exposure, overscan2) rightOverscan.image.array += np.random.normal(0.0, self.sigma, leftOverscan.image.array.shape) exposure.mask.array[:] = 0.0 exposure.variance.array[:] = np.nan # Construct the detectors amps = AmpInfoCatalog(AmpInfoTable.makeMinimalSchema()) makeAmplifier(amps, "left", target1, image1, overscan1, gain, readNoise, saturation) makeAmplifier(amps, "right", target2, image2, overscan2, gain, readNoise, saturation) ccdBox = Box2I(Point2I(0, 0), Extent2I(image1.getWidth() + image2.getWidth(), height)) ccd = Detector("detector", 1, SCIENCE, "det1", ccdBox, amps, Orientation(), Extent2D(1.0, 1.0), {}) exposure.setDetector(ccd) header = PropertyList() header.add("EXPTIME", 0.0) exposure.getInfo().setVisitInfo(VisitInfo(header)) self.exposure = exposure self.config = IsrTask.ConfigClass() # Disable everything we don't care about self.config.doBias = False self.config.doDark = False self.config.doFlat = False self.config.doFringe = False self.config.doDefect = False self.config.doAddDistortionModel = False self.config.doWrite = False self.config.expectWcs = False self.config.doLinearize = False self.config.doCrosstalk = False self.config.doBrighterFatter = False self.config.doAttachTransmissionCurve = False # Set the things that match our test setup self.config.overscanFitType = "CHEB" self.config.overscanOrder = 1 self.config.doEmpiricalReadNoise = True self.task = IsrTask(config=self.config)
def testId(self): a = PropertyList() b = PropertyList() self.assertEqual(b.getId(), a.getId() + 1)
def testReplaceDuplicates(self): """Test that names in `second` override those in `first`, regardless of type """ # names that start with "item" appear in both sets of metadata md1 = PropertyList() md1.set("int1", 5) md1.set("itema", [1, 2]) md1.set("float1", 3.1) md1.set("itemb", 1.23) md1.set("string1", "md1 string1 value") md1.set("itemc", "md1 string value") md1Copy = md1.deepCopy() md2 = PropertyList() md2.set("itemc", 2) md2.set("int2", 2) md2.set("itemb", ["some data", "more data"]) md2.set("float2", 2.34) md2.set("itema", 5.27) md2.set("string2", "md2 string value") md2Names = md2.getOrderedNames() md2Copy = md2.deepCopy() result = combineMetadata(md1, md2) expectedNames = ["int1", "float1", "string1"] + list(md2Names) self.assertEqual(result.getOrderedNames(), expectedNames) md2NameSet = set(md2Names) for name in result.getOrderedNames(): if name in md2NameSet: self.assertEqual(result.getScalar(name), md2.getArray(name)[-1]) else: self.assertEqual(result.getScalar(name), md1.getArray(name)[-1]) # input should be unchanged self.assertMetadataEqual(md1, md1Copy) self.assertMetadataEqual(md2, md2Copy)
def testNoConflicts(self): """Test combination with valid values and no overlap, except COMMENT and HISTORY, which are combined """ md1 = PropertyList() md1.set("int1", [1, 2]) md1.set("float1", 1.23) md1.set("string1", "md1 string1 value") md1.set("COMMENT", "md1 comment") md1.set("HISTORY", "md1 history") md1Copy = md1.deepCopy() md2 = PropertyList() md2.set("int2", 2) md2.set("float2", [2.34, -3.45]) md2.set("string2", "md2 string2 value") md2.set("COMMENT", "md2 comment") md2.set("HISTORY", "md2 history") md2Copy = md2.deepCopy() result = combineMetadata(md1, md2) self.assertEqual(result.getOrderedNames(), ["int1", "float1", "string1", "COMMENT", "HISTORY", "int2", "float2", "string2"]) self.assertEqual(result.getArray("COMMENT"), ["md1 comment", "md2 comment"]) self.assertEqual(result.getArray("HISTORY"), ["md1 history", "md2 history"]) for name in md1.getOrderedNames(): if name in ("COMMENT", "HISTORY"): continue self.assertEqual(result.getScalar(name), md1.getArray(name)[-1]) for name in md2.getOrderedNames(): if name in ("COMMENT", "HISTORY"): continue self.assertEqual(result.getScalar(name), md2.getArray(name)[-1]) # input should be unchanged self.assertMetadataEqual(md1, md1Copy) self.assertMetadataEqual(md2, md2Copy)
def setUp(self): # Actual WCS from processing Suprime-Cam self.width = 2048 self.height = 4177 metadata = PropertyList() for name, value in ( ('NAXIS', 2), ('EQUINOX', 2000.0000000000), ('RADESYS', "ICRS"), ('CRPIX1', -3232.7544925483), ('CRPIX2', 4184.4881091129), ('CD1_1', -5.6123808607273e-05), ('CD1_2', 2.8951544956703e-07), ('CD2_1', 2.7343044348306e-07), ('CD2_2', 5.6100888336445e-05), ('CRVAL1', 5.6066137655191), ('CRVAL2', -0.60804032498548), ('CUNIT1', "deg"), ('CUNIT2', "deg"), ('A_ORDER', 5), ('A_0_2', 1.9749832126246e-08), ('A_0_3', 9.3734869173527e-12), ('A_0_4', 1.8812994578840e-17), ('A_0_5', -2.3524013652433e-19), ('A_1_1', -9.8443908806559e-10), ('A_1_2', -4.9278297504858e-10), ('A_1_3', -2.8491604610001e-16), ('A_1_4', 2.3185723720750e-18), ('A_2_0', 4.9546089730708e-08), ('A_2_1', -8.8592221672777e-12), ('A_2_2', 3.3560100338765e-16), ('A_2_3', 3.0469486185035e-21), ('A_3_0', -4.9332471706700e-10), ('A_3_1', -5.3126029725748e-16), ('A_3_2', 4.7795824885726e-18), ('A_4_0', 1.3128844828963e-16), ('A_4_1', 4.4014452170715e-19), ('A_5_0', 2.1781986904162e-18), ('B_ORDER', 5), ('B_0_2', -1.0607653075899e-08), ('B_0_3', -4.8693887937365e-10), ('B_0_4', -1.0363305097301e-15), ('B_0_5', 1.9621640066919e-18), ('B_1_1', 3.0340657679481e-08), ('B_1_2', -5.0763819284853e-12), ('B_1_3', 2.8987281654754e-16), ('B_1_4', 1.8253389678593e-19), ('B_2_0', -2.4772849184248e-08), ('B_2_1', -4.9775588352207e-10), ('B_2_2', -3.6806326254887e-16), ('B_2_3', 4.4136985315418e-18), ('B_3_0', -1.7807191001742e-11), ('B_3_1', -2.4136396882531e-16), ('B_3_2', 2.9165413645768e-19), ('B_4_0', 4.1029951148438e-16), ('B_4_1', 2.3711874424169e-18), ('B_5_0', 4.9333635889310e-19), ('AP_ORDER', 5), ('AP_0_1', -5.9740855298291e-06), ('AP_0_2', -2.0433429597268e-08), ('AP_0_3', -8.6810071023434e-12), ('AP_0_4', -2.4974690826778e-17), ('AP_0_5', 1.9819631102516e-19), ('AP_1_0', -4.5896648256716e-05), ('AP_1_1', -1.5248993348644e-09), ('AP_1_2', 5.0283116166943e-10), ('AP_1_3', 4.3796281513144e-16), ('AP_1_4', -2.1447889127908e-18), ('AP_2_0', -4.7550300344365e-08), ('AP_2_1', 1.0924172283232e-11), ('AP_2_2', -4.9862026098260e-16), ('AP_2_3', -5.4470851768869e-20), ('AP_3_0', 5.0130654116966e-10), ('AP_3_1', 6.8649554020012e-16), ('AP_3_2', -4.2759588436342e-18), ('AP_4_0', -3.6306802581471e-16), ('AP_4_1', -5.3885285875084e-19), ('AP_5_0', -1.8802693525108e-18), ('BP_ORDER', 5), ('BP_0_1', -2.6627855995942e-05), ('BP_0_2', 1.1143451873584e-08), ('BP_0_3', 4.9323396530135e-10), ('BP_0_4', 1.1785185735421e-15), ('BP_0_5', -1.6169957016415e-18), ('BP_1_0', -5.7914490267576e-06), ('BP_1_1', -3.0565765766244e-08), ('BP_1_2', 5.7727475030971e-12), ('BP_1_3', -4.0586821113726e-16), ('BP_1_4', -2.0662723654322e-19), ('BP_2_0', 2.3705520015164e-08), ('BP_2_1', 5.0530823594352e-10), ('BP_2_2', 3.8904979943489e-16), ('BP_2_3', -3.8346209540986e-18), ('BP_3_0', 1.9505421473262e-11), ('BP_3_1', 1.7583146713289e-16), ('BP_3_2', -3.4876779564534e-19), ('BP_4_0', -3.3690937119054e-16), ('BP_4_1', -2.0853007589561e-18), ('BP_5_0', -5.5344298912288e-19), ('CTYPE1', "RA---TAN-SIP"), ('CTYPE2', "DEC--TAN-SIP"), ): metadata.set(name, value) self.metadata = metadata
def testIgnoreInvalid(self): """Test that invalid items in the either argument are ignored """ md1 = PropertyList() # Set COMMENT and HISTORY to invalid values -- anything other than string # (regardless if it is a scalar or an array); # for md1 use arrays and md2 use scalars, just to try both md1.set("COMMENT", [5, 6]) md1.set("HISTORY", [3.5, 6.1]) md1Copy = md1.deepCopy() md2 = PropertyList() # Set COMMENT and HISTORY to invalid values; see comment above md1.set("COMMENT", ...) md2.set("COMMENT", 7) md2.set("HISTORY", 1.06) md2Copy = md2.deepCopy() result = combineMetadata(md1, md2) resultNames = result.getOrderedNames() self.assertEqual(resultNames, []) # input should be unchanged self.assertMetadataEqual(md1, md1Copy) self.assertMetadataEqual(md2, md2Copy)