Exemplo n.º 1
0
    def writeFcr(self, dataRefList):
        self.log.info("Write Fcr ...")
        M_LN10 = math.log(10)
        dmag = list()
        for m in self.matchVec:
            if (m.good == True and m.mag != -9999 and m.jstar != -1 and
                m.mag0 != -9999 and m.mag_cat != -9999):
                mag = m.mag
                mag_cat = m.mag_cat
                exp_cor = -2.5*math.log10(self.fexp[m.iexp])
                chip_cor = -2.5*math.log10(self.fchip[m.ichip])
                gain_cor = self.ffpSet[m.iexp].eval(m.u, m.v)
                mag_cor = mag + exp_cor + chip_cor + gain_cor
                dmag.append(mag_cor - mag_cat)
        std, mean, n  = mosaicUtils.clippedStd(numpy.array(dmag), 2.1)
        for dataRef in dataRefList:
            iexp = dataRef.dataId["visit"]
            ichip = dataRef.dataId["ccd"]
            try:
                x0 = self.coeffSet[iexp].x0
                y0 = self.coeffSet[iexp].y0
            except:
                x0 = 0.0
                y0 = 0.0
            newP = measMosaic.convertFluxFitParams(measMosaic.FluxFitParams(self.ffpSet[iexp]),
                                                   self.ccdSet[ichip], x0, y0)
            metadata = measMosaic.metadataFromFluxFitParams(newP)
            exp = afwImage.ExposureI(0,0)
            exp.getMetadata().combine(metadata)
            scale = self.fexp[iexp]*self.fchip[ichip]
            constantPhotoCalib = afwImage.makePhotoCalibFromCalibZeroPoint(1.0/scale, 1.0/scale*std*M_LN10*0.4)
            exp.setPhotoCalib(constantPhotoCalib)
            try:
                dataRef.put(exp, "fcr")
            except Exception as e:
                print("failed to write fcr: %s" % (e))

            # Write the flux fit (including Jacobian) as a PhotoCalib for
            # future compatibility with jointcal.  This is redundant with
            # the above, and should eventually supercede it.
            detector = dataRef.get("camera")[dataRef.dataId["ccd"]]
            nQuarter = detector.getOrientation().getNQuarter()
            bbox = detector.getBBox()
            try:
                # Reading the Wcs we just wrote obviously isn't efficient, but
                # it should be in the noise of the overall runtime and it
                # saves us from doing a bunch of refactoring in a fragile
                # package with no tests.
                wcs = dataRef.get("jointcal_wcs")
            except Exception as e:
                print("failed to read Wcs for PhotoCalib: %s" % (e))
                continue
            bf = measMosaic.FluxFitBoundedField(bbox, newP, wcs,
                                                zeroPoint=constantPhotoCalib.getInstFluxAtZeroMagnitude(),
                                                nQuarter=nQuarter)
            varyingPhotoCalib = afwImage.PhotoCalib(constantPhotoCalib.getCalibrationMean(),
                                                    constantPhotoCalib.getCalibrationErr(),
                                                    bf,
                                                    isConstant=False)
            dataRef.put(varyingPhotoCalib, "jointcal_photoCalib")
    def _getConstantPhotoCalib(self, zeropoint, err, offset, scaling):
        """
        Get the PhotoCalib object from a constant zeropoint.

        Parameters
        ----------
        zeropoint: `float`
           Zeropoint value (mag)
        err: `float`
           Error on zeropoint
        offset: `float`
           Absolute calibration offset
        scaling: `float`
           Flat scaling value from fgcmBuildStars

        Returns
        -------
        photoCalib: `afwImage.PhotoCalib`
        """

        # Take the zeropoint, apply the absolute relative calibration offset,
        # and whatever flat-field scaling was applied

        calibMean = (
            (zeropoint + offset) * units.ABmag).to_value(units.nJy) * scaling
        calibErr = (np.log(10.) / 2.5) * calibMean * err
        photoCalib = afwImage.PhotoCalib(calibMean, calibErr)

        return photoCalib
Exemplo n.º 3
0
    def setUp(self):
        super().setUp()

        afwImage.Filter.reset()
        afwImage.FilterProperty.reset()
        defineFilter("g", 470.0)

        self.wcs = afwGeom.makeSkyWcs(
            lsst.geom.Point2D(0.0, 0.0),
            lsst.geom.SpherePoint(2.0, 34.0, lsst.geom.degrees),
            np.identity(2),
        )
        self.photoCalib = afwImage.PhotoCalib(1.5)
        self.psf = DummyPsf(2.0)
        self.detector = DetectorWrapper().detector
        self.summaryStats = afwImage.ExposureSummaryStats(ra=100.0)
        self.polygon = afwGeom.Polygon(
            lsst.geom.Box2D(lsst.geom.Point2D(0.0, 0.0),
                            lsst.geom.Point2D(25.0, 20.0)))
        self.coaddInputs = afwImage.CoaddInputs()
        self.apCorrMap = afwImage.ApCorrMap()
        self.transmissionCurve = afwImage.TransmissionCurve.makeIdentity()

        self.exposureInfo = afwImage.ExposureInfo()
        gFilter = afwImage.Filter("g")
        gFilterLabel = afwImage.FilterLabel(band="g")
        self.exposureInfo.setFilter(gFilter)
        self.exposureInfo.setFilterLabel(gFilterLabel)
Exemplo n.º 4
0
 def testVisitInfoFitsPersistence(self):
     """Test saving an exposure to FITS and reading it back in preserves (some) VisitInfo fields"""
     exposureId = 5
     exposureTime = 12.3
     boresightRotAngle = 45.6 * lsst.geom.degrees
     weather = Weather(1.1, 2.2, 0.3)
     visitInfo = afwImage.VisitInfo(
         exposureId=exposureId,
         exposureTime=exposureTime,
         boresightRotAngle=boresightRotAngle,
         weather=weather,
     )
     photoCalib = afwImage.PhotoCalib(3.4, 5.6)
     exposureInfo = afwImage.ExposureInfo()
     exposureInfo.setVisitInfo(visitInfo)
     exposureInfo.setPhotoCalib(photoCalib)
     exposureInfo.setDetector(self.detector)
     gFilter = afwImage.Filter("g")
     exposureInfo.setFilter(gFilter)
     maskedImage = afwImage.MaskedImageF(inFilePathSmall)
     exposure = afwImage.ExposureF(maskedImage, exposureInfo)
     with lsst.utils.tests.getTempFilePath(".fits") as tmpFile:
         exposure.writeFits(tmpFile)
         rtExposure = afwImage.ExposureF(tmpFile)
     rtVisitInfo = rtExposure.getInfo().getVisitInfo()
     self.assertEqual(rtVisitInfo.getWeather(), weather)
     self.assertEqual(rtExposure.getPhotoCalib(), photoCalib)
     self.assertEqual(rtExposure.getFilter(), gFilter)
Exemplo n.º 5
0
    def testReadWriteFits(self):
        """Test readFits and writeFits.
        """
        # This should pass without an exception
        mainExposure = afwImage.ExposureF(inFilePathSmall)
        mainExposure.setDetector(self.detector)

        subBBox = lsst.geom.Box2I(lsst.geom.Point2I(10, 10),
                                  lsst.geom.Extent2I(40, 50))
        subExposure = mainExposure.Factory(mainExposure, subBBox,
                                           afwImage.LOCAL)
        self.checkWcs(mainExposure, subExposure)
        det = subExposure.getDetector()
        self.assertTrue(det)

        subExposure = afwImage.ExposureF(inFilePathSmall, subBBox,
                                         afwImage.LOCAL)

        self.checkWcs(mainExposure, subExposure)

        # This should throw an exception
        def getExposure():
            afwImage.ExposureF(inFilePathSmallImage)

        self.assertRaises(FitsError, getExposure)

        mainExposure.setPsf(self.psf)

        # Make sure we can write without an exception
        photoCalib = afwImage.PhotoCalib(1e-10, 1e-12)
        mainExposure.setPhotoCalib(photoCalib)

        mainInfo = mainExposure.getInfo()
        for key, value in self.extras.items():
            mainInfo.setComponent(key, value)

        with lsst.utils.tests.getTempFilePath(".fits") as tmpFile:
            mainExposure.writeFits(tmpFile)

            readExposure = type(mainExposure)(tmpFile)

            #
            # Check the round-tripping
            #
            self.assertEqual(mainExposure.getFilter().getName(),
                             readExposure.getFilter().getName())
            self.assertIsNotNone(mainExposure.getFilterLabel())
            self.assertEqual(mainExposure.getFilterLabel(),
                             readExposure.getFilterLabel())

            self.assertEqual(photoCalib, readExposure.getPhotoCalib())

            readInfo = readExposure.getInfo()
            for key, value in self.extras.items():
                self.assertEqual(value, readInfo.getComponent(key))

            psf = readExposure.getPsf()
            self.assertIsNotNone(psf)
            self.assertEqual(psf, self.psf)
Exemplo n.º 6
0
    def getCalibratedExposure(self, dataRef, bgSubtracted):
        """Return one calibrated Exposure, possibly with an updated SkyWcs.

        @param[in] dataRef        a sensor-level data reference
        @param[in] bgSubtracted   return calexp with background subtracted? If False get the
                                  calexp's background background model and add it to the calexp.
        @return calibrated exposure

        @raises MissingExposureError If data for the exposure is not available.

        If config.doApplyUberCal, the exposure will be photometrically
        calibrated via the `jointcal_photoCalib` dataset and have its SkyWcs
        updated to the `jointcal_wcs`, otherwise it will be calibrated via the
        Exposure's own PhotoCalib and have the original SkyWcs.
        """
        try:
            exposure = dataRef.get(self.calexpType, immediate=True)
        except dafPersist.NoResults as e:
            raise MissingExposureError('Exposure not found: %s ' %
                                       str(e)) from e

        if not bgSubtracted:
            background = dataRef.get("calexpBackground", immediate=True)
            mi = exposure.getMaskedImage()
            mi += background.getImage()
            del mi

        if self.config.doApplyUberCal:
            if self.config.useMeasMosaic:
                from lsst.meas.mosaic import applyMosaicResultsExposure
                # NOTE: this changes exposure in-place, updating its Calib and Wcs.
                # Save the calibration error, as it gets overwritten with zero.
                calibrationErr = exposure.getPhotoCalib().getCalibrationErr()
                try:
                    applyMosaicResultsExposure(dataRef, calexp=exposure)
                except dafPersist.NoResults as e:
                    raise MissingExposureError(
                        'Mosaic calibration not found: %s ' % str(e)) from e
                photoCalib = afwImage.PhotoCalib(
                    exposure.getPhotoCalib().getCalibrationMean(),
                    calibrationErr, exposure.getBBox())
            else:
                photoCalib = dataRef.get("jointcal_photoCalib")
                skyWcs = dataRef.get("jointcal_wcs")
                exposure.setWcs(skyWcs)
        else:
            photoCalib = exposure.getPhotoCalib()

        exposure.maskedImage = photoCalib.calibrateImage(
            exposure.maskedImage,
            includeScaleUncertainty=self.config.includeCalibVar)
        exposure.maskedImage /= photoCalib.getCalibrationMean()
        exposure.setPhotoCalib(photoCalib)
        # TODO: The images will have a calibration of 1.0 everywhere once RFC-545 is implemented.
        # exposure.setCalib(afwImage.Calib(1.0))
        return exposure
Exemplo n.º 7
0
    def testNullWarpExposure(self, interpLength=10):
        """Test that warpExposure maps an image onto itself.

        Note:
        - NO_DATA and off-CCD pixels must be ignored
        - bad mask pixels get smeared out so we have to excluded all bad mask pixels
          from the output image when comparing masks.
        """
        imageUtils.defineFilter("i", 748.1)

        originalExposure = afwImage.ExposureF(originalExposurePath)
        originalExposure.getInfo().setVisitInfo(makeVisitInfo())
        originalFilter = afwImage.Filter("i")
        originalPhotoCalib = afwImage.PhotoCalib(1.0e5, 1.0e3)
        originalExposure.setFilter(originalFilter)
        originalExposure.setPhotoCalib(originalPhotoCalib)
        afwWarpedExposure = afwImage.ExposureF(originalExposure.getBBox(),
                                               originalExposure.getWcs())
        warpingControl = afwMath.WarpingControl("lanczos4", "", 0,
                                                interpLength)
        afwMath.warpExposure(afwWarpedExposure, originalExposure,
                             warpingControl)
        if SAVE_FITS_FILES:
            afwWarpedExposure.writeFits("afwWarpedExposureNull.fits")

        self.assertEqual(afwWarpedExposure.getFilter().getName(),
                         originalFilter.getName())
        self.assertEqual(afwWarpedExposure.getPhotoCalib(), originalPhotoCalib)
        self.assertEqual(afwWarpedExposure.getInfo().getVisitInfo(),
                         originalExposure.getInfo().getVisitInfo())

        afwWarpedMaskedImage = afwWarpedExposure.getMaskedImage()
        afwWarpedMask = afwWarpedMaskedImage.getMask()
        noDataBitMask = afwWarpedMask.getPlaneBitMask("NO_DATA")
        afwWarpedMaskedImageArrSet = afwWarpedMaskedImage.getArrays()
        afwWarpedMaskArr = afwWarpedMaskedImageArrSet[1]

        # compare all non-DATA pixels of image and variance, but relax specs a bit
        # because of minor noise introduced by bad pixels
        noDataMaskArr = afwWarpedMaskArr & noDataBitMask
        msg = "afw null-warped MaskedImage (all pixels, relaxed tolerance)"
        self.assertMaskedImagesAlmostEqual(afwWarpedMaskedImage,
                                           originalExposure.getMaskedImage(),
                                           doMask=False,
                                           skipMask=noDataMaskArr,
                                           atol=1e-5,
                                           msg=msg)

        # compare good pixels (mask=0) of image, mask and variance using full
        # tolerance
        msg = "afw null-warped MaskedImage (good pixels, max tolerance)"
        self.assertMaskedImagesAlmostEqual(afwWarpedMaskedImage,
                                           originalExposure.getMaskedImage(),
                                           skipMask=afwWarpedMask,
                                           msg=msg)
Exemplo n.º 8
0
    def _build_ccdImage(self, dataRef, associations, jointcalControl):
        """
        Extract the necessary things from this dataRef to add a new ccdImage.

        Parameters
        ----------
        dataRef : lsst.daf.persistence.ButlerDataRef
            dataRef to extract info from.
        associations : lsst.jointcal.Associations
            object to add the info to, to construct a new CcdImage
        jointcalControl : jointcal.JointcalControl
            control object for associations management

        Returns
        ------
        namedtuple
            wcs : lsst.afw.image.TanWcs
                the TAN WCS of this image, read from the calexp
            key : namedtuple
                a key to identify this dataRef by its visit and ccd ids
            filter : str
                this calexp's filter
        """
        visit = dataRef.dataId["visit"]
        src = dataRef.get("src",
                          flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS,
                          immediate=True)
        calexp = dataRef.get("calexp", immediate=True)
        visitInfo = calexp.getInfo().getVisitInfo()
        ccdname = calexp.getDetector().getId()

        calib = calexp.getCalib()
        tanWcs = calexp.getWcs()
        bbox = calexp.getBBox()
        filt = calexp.getInfo().getFilter().getName()
        fluxMag0 = calib.getFluxMag0()
        photoCalib = afwImage.PhotoCalib(fluxMag0[0], fluxMag0[1], bbox)

        goodSrc = self.sourceSelector.selectSources(src)

        if len(goodSrc.sourceCat) == 0:
            self.log.warn("no stars selected in ", visit, ccdname)
            return tanWcs
        self.log.info("%d stars selected in visit %d ccd %d",
                      len(goodSrc.sourceCat), visit, ccdname)
        associations.addImage(goodSrc.sourceCat, tanWcs, visitInfo, bbox, filt,
                              photoCalib, visit, ccdname, jointcalControl)

        Result = collections.namedtuple('Result_from_build_CcdImage',
                                        ('wcs', 'key', 'filter'))
        Key = collections.namedtuple('Key', ('visit', 'ccd'))
        return Result(tanWcs, Key(visit, ccdname), filt)
Exemplo n.º 9
0
 def testApplyCppTransform(self):
     """Test that we can apply a simple C++ transform.
     """
     inCat = self._generateCatalog()
     sillyControl = testLib.SillyCentroidControl()
     mapper = afwTable.SchemaMapper(inCat.schema)
     sillyTransform = testLib.SillyTransform(sillyControl, self.pluginName,
                                             mapper)
     outCat = afwTable.BaseCatalog(mapper.getOutputSchema())
     outCat.extend(inCat, mapper=mapper)
     self.assertEqual(len(inCat), len(outCat))
     sillyTransform(inCat, outCat, makeWcs(), afwImage.PhotoCalib())
     self._checkSillyOutputs(inCat, outCat)
Exemplo n.º 10
0
    def testSetMembers(self):
        """
        Test that the MaskedImage and the WCS of an Exposure can be set.
        """
        exposure = afwImage.ExposureF()

        maskedImage = afwImage.MaskedImageF(inFilePathSmall)
        exposure.setMaskedImage(maskedImage)
        exposure.setWcs(self.wcs)
        exposure.setDetector(self.detector)
        exposure.setFilter(afwImage.Filter("g"))
        exposure.setFilterLabel(afwImage.FilterLabel(band="g"))

        self.assertEqual(exposure.getDetector().getName(),
                         self.detector.getName())
        self.assertEqual(exposure.getDetector().getSerial(),
                         self.detector.getSerial())
        self.assertEqual(exposure.getFilter().getName(), "g")
        self.assertEqual(exposure.getFilterLabel().bandLabel, "g")
        self.assertEqual(exposure.getWcs(), self.wcs)

        # The PhotoCalib tests are in test_photoCalib.py;
        # here we just check that it's gettable and settable.
        self.assertIsNone(exposure.getPhotoCalib())

        photoCalib = afwImage.PhotoCalib(511.1, 44.4)
        exposure.setPhotoCalib(photoCalib)
        self.assertEqual(exposure.getPhotoCalib(), photoCalib)

        # Psfs next
        self.assertFalse(exposure.hasPsf())
        exposure.setPsf(self.psf)
        self.assertTrue(exposure.hasPsf())

        exposure.setPsf(DummyPsf(1.0))  # we can reset the Psf

        # extras next
        info = exposure.getInfo()
        for key, value in self.extras.items():
            self.assertFalse(info.hasComponent(key))
            self.assertIsNone(info.getComponent(key))
            info.setComponent(key, value)
            self.assertTrue(info.hasComponent(key))
            self.assertEqual(info.getComponent(key), value)
            info.removeComponent(key)
            self.assertFalse(info.hasComponent(key))

        # Test that we can set the MaskedImage and WCS of an Exposure
        # that already has both
        self.exposureMiWcs.setMaskedImage(maskedImage)
        exposure.setWcs(self.wcs)
    def setUp(self):
        # CFHT Filters from the camera mapper.
        afwImageUtils.resetFilters()
        afwImageUtils.defineFilter('u', lambdaEff=374, alias="u.MP9301")
        afwImageUtils.defineFilter('g', lambdaEff=487, alias="g.MP9401")
        afwImageUtils.defineFilter('r', lambdaEff=628, alias="r.MP9601")
        afwImageUtils.defineFilter('i', lambdaEff=778, alias="i.MP9701")
        afwImageUtils.defineFilter('z', lambdaEff=1170, alias="z.MP9801")

        self.metadata = dafBase.PropertySet()

        self.metadata.set("SIMPLE", "T")
        self.metadata.set("BITPIX", -32)
        self.metadata.set("NAXIS", 2)
        self.metadata.set("NAXIS1", 1024)
        self.metadata.set("NAXIS2", 1153)
        self.metadata.set("RADECSYS", 'FK5')
        self.metadata.set("EQUINOX", 2000.)

        self.metadata.setDouble("CRVAL1", 215.604025685476)
        self.metadata.setDouble("CRVAL2", 53.1595451514076)
        self.metadata.setDouble("CRPIX1", 1109.99981456774)
        self.metadata.setDouble("CRPIX2", 560.018167811613)
        self.metadata.set("CTYPE1", 'RA---SIN')
        self.metadata.set("CTYPE2", 'DEC--SIN')

        self.metadata.setDouble("CD1_1", 5.10808596133527E-05)
        self.metadata.setDouble("CD1_2", 1.85579539217196E-07)
        self.metadata.setDouble("CD2_2", -5.10281493481982E-05)
        self.metadata.setDouble("CD2_1", -8.27440751733828E-07)

        self.wcs = afwGeom.makeSkyWcs(self.metadata)
        self.exposure = afwImage.makeExposure(
            afwImage.makeMaskedImageFromArrays(np.ones((1024, 1153))),
            self.wcs)
        detector = DetectorWrapper(id=23,
                                   bbox=self.exposure.getBBox()).detector
        visit = afwImage.VisitInfo(exposureId=4321,
                                   exposureTime=200.,
                                   date=dafBase.DateTime(nsecs=1400000000 *
                                                         10**9))
        self.exposure.setDetector(detector)
        self.exposure.getInfo().setVisitInfo(visit)
        self.exposure.setFilter(afwImage.Filter('g'))
        scale = 2
        scaleErr = 1
        self.photoCalib = afwImage.PhotoCalib(scale, scaleErr)
        self.exposure.setPhotoCalib(self.photoCalib)

        self.inputCatalogNoFlags = make_input_source_catalog(10, False)
        self.inputCatalog = make_input_source_catalog(10, True)
Exemplo n.º 12
0
    def setUp(self):
        self.dataDir = os.path.join(os.path.split(__file__)[0], "data")

        # Check the values below against what was written by comparing with
        # the code in `afw/tests/data/makeTestExposure.py`
        nx = ny = 10
        image = afwImage.ImageF(np.arange(nx*ny, dtype='f').reshape(nx, ny))
        variance = afwImage.ImageF(np.ones((nx, ny), dtype='f'))
        mask = afwImage.MaskX(nx, ny)
        mask.array[5, 5] = 5
        self.maskedImage = afwImage.MaskedImageF(image, mask, variance)

        self.v0PhotoCalib = afwImage.makePhotoCalibFromCalibZeroPoint(1e6, 2e4)
        self.v1PhotoCalib = afwImage.PhotoCalib(1e6, 2e4)
Exemplo n.º 13
0
    def setUp(self):
        '''Create two calibs, one with a valid zero-point and one without. Use these to create two UnitSystem
        objects.
        '''
        self.mag2Flux = lambda m: 10.0**(m/2.5)
        self.flux2Mag = lambda f: 2.5*np.log10(f)

        photoCalibNoZero = afwImage.PhotoCalib()
        photoCalibWithZero = afwImage.makePhotoCalibFromCalibZeroPoint(self.mag2Flux(25))

        scale = 0.2 * geom.arcseconds
        wcs = afwGeom.makeSkyWcs(crpix=geom.Point2D(),
                                 crval=geom.SpherePoint(45.0, 45.0, geom.degrees),
                                 cdMatrix=afwGeom.makeCdMatrix(scale=scale))

        self.unitNoZero = measModel.UnitSystem(wcs, photoCalibNoZero)
        self.unitWithZero = measModel.UnitSystem(wcs, photoCalibWithZero)
Exemplo n.º 14
0
    def testBBox(self):
        """Test that the default bounding box includes all warped pixels
        """
        kernelName = "lanczos2"
        warper = afwMath.Warper(kernelName)
        originalExposure, swarpedImage, swarpedWcs = self.getSwarpedImage(
            kernelName=kernelName, useSubregion=True, useDeepCopy=False)

        imageUtils.defineFilter("i", 748.1)

        originalFilter = afwImage.Filter("i")
        originalPhotoCalib = afwImage.PhotoCalib(1.0e5, 1.0e3)
        originalExposure.setFilter(originalFilter)
        originalExposure.setPhotoCalib(originalPhotoCalib)

        warpedExposure1 = warper.warpExposure(destWcs=swarpedWcs,
                                              srcExposure=originalExposure)
        # the default size must include all good pixels, so growing the bbox
        # should not add any
        warpedExposure2 = warper.warpExposure(destWcs=swarpedWcs,
                                              srcExposure=originalExposure,
                                              border=1)
        # a bit of excess border is allowed, but surely not as much as 10 (in
        # fact it is approx. 5)
        warpedExposure3 = warper.warpExposure(destWcs=swarpedWcs,
                                              srcExposure=originalExposure,
                                              border=-10)
        # assert that warpedExposure and warpedExposure2 have the same number of non-no_data pixels
        # and that warpedExposure3 has fewer
        noDataBitMask = afwImage.Mask.getPlaneBitMask("NO_DATA")
        mask1Arr = warpedExposure1.getMaskedImage().getMask().getArray()
        mask2Arr = warpedExposure2.getMaskedImage().getMask().getArray()
        mask3Arr = warpedExposure3.getMaskedImage().getMask().getArray()
        nGood1 = (mask1Arr & noDataBitMask == 0).sum()
        nGood2 = (mask2Arr & noDataBitMask == 0).sum()
        nGood3 = (mask3Arr & noDataBitMask == 0).sum()
        self.assertEqual(nGood1, nGood2)
        self.assertLess(nGood3, nGood1)

        self.assertEqual(warpedExposure1.getFilter().getName(),
                         originalFilter.getName())
        self.assertEqual(warpedExposure1.getPhotoCalib(), originalPhotoCalib)
Exemplo n.º 15
0
    def _getChebyshevPhotoCalib(self, coefficients, err, xyMax, offset,
                                scaling):
        """
        Get the PhotoCalib object from a chebyshev polynomial zeropoint.

        Parameters
        ----------
        coefficients: `np.array`
           Flattened array of chebyshev coefficients
        err: `float`
           Error on zeropoint
        xyMax: `list` of length 2
           Maximum x and y of the chebyshev bounding box
        offset: `float`
           Absolute calibration offset
        scaling: `float`
           Flat scaling value from fgcmBuildStars

        Returns
        -------
        photoCalib: `afwImage.PhotoCalib`
        """

        orderPlus1 = self.chebyshevOrder + 1
        pars = np.zeros((orderPlus1, orderPlus1))

        bbox = lsst.geom.Box2I(lsst.geom.Point2I(0.0, 0.0),
                               lsst.geom.Point2I(*xyMax))
        # Take the zeropoint, apply the absolute relative calibration offset,
        # and whatever flat-field scaling was applied
        pars[:, :] = (coefficients.reshape(orderPlus1, orderPlus1) *
                      (offset * units.ABmag).to_value(units.nJy) * scaling)

        field = afwMath.ChebyshevBoundedField(bbox, pars)
        calibMean = field.mean()

        calibErr = (np.log(10.) / 2.5) * calibMean * err

        photoCalib = afwImage.PhotoCalib(field, calibErr)

        return photoCalib
    def setUp(self):
        # CFHT Filters from the camera mapper.
        self.filter_names = ["u", "g", "r", "i", "z"]
        afwImageUtils.resetFilters()
        afwImageUtils.defineFilter('u', lambdaEff=374, alias="u.MP9301")
        afwImageUtils.defineFilter('g', lambdaEff=487, alias="g.MP9401")
        afwImageUtils.defineFilter('r', lambdaEff=628, alias="r.MP9601")
        afwImageUtils.defineFilter('i', lambdaEff=778, alias="i.MP9701")
        afwImageUtils.defineFilter('z', lambdaEff=1170, alias="z.MP9801")

        # metadata taken from CFHT data
        # v695856-e0/v695856-e0-c000-a00.sci_img.fits
        self.metadata = dafBase.PropertySet()

        self.metadata.set("SIMPLE", "T")
        self.metadata.set("BITPIX", -32)
        self.metadata.set("NAXIS", 2)
        self.metadata.set("NAXIS1", 1024)
        self.metadata.set("NAXIS2", 1153)
        self.metadata.set("RADECSYS", 'FK5')
        self.metadata.set("EQUINOX", 2000.)

        self.metadata.setDouble("CRVAL1", 215.604025685476)
        self.metadata.setDouble("CRVAL2", 53.1595451514076)
        self.metadata.setDouble("CRPIX1", 1109.99981456774)
        self.metadata.setDouble("CRPIX2", 560.018167811613)
        self.metadata.set("CTYPE1", 'RA---SIN')
        self.metadata.set("CTYPE2", 'DEC--SIN')

        self.metadata.setDouble("CD1_1", 5.10808596133527E-05)
        self.metadata.setDouble("CD1_2", 1.85579539217196E-07)
        self.metadata.setDouble("CD2_2", -5.10281493481982E-05)
        self.metadata.setDouble("CD2_1", -8.27440751733828E-07)

        self.wcs = afwGeom.makeSkyWcs(self.metadata)

        self.calibration = 10000
        self.calibrationErr = 100
        self.exposureId = 1234
        self.exposureTime = 200.
        self.imageSize = [1024, 1153]
        self.dateTime = "2014-05-13T17:00:00.000000000"

        # Make images  with one source in them and distinct values and
        # variance for each image.
        # Direct Image
        source_image = afwImage.MaskedImageF(
            lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1))
        source_image.image[100, 100, afwImage.LOCAL] = 10
        source_image.getVariance().set(1)
        bbox = lsst.geom.BoxI(
            lsst.geom.PointI(1, 1),
            lsst.geom.ExtentI(self.imageSize[0],
                              self.imageSize[1]))
        masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL)
        self.exposure = afwImage.makeExposure(masked_image, self.wcs)

        detector = DetectorWrapper(
            id=23, bbox=self.exposure.getBBox()).detector
        visit = afwImage.VisitInfo(
            exposureId=self.exposureId,
            exposureTime=self.exposureTime,
            date=dafBase.DateTime(self.dateTime,
                                  dafBase.DateTime.Timescale.TAI))
        self.exposure.setDetector(detector)
        self.exposure.getInfo().setVisitInfo(visit)
        self.exposure.setFilter(afwImage.Filter('g'))
        self.exposure.setPhotoCalib(afwImage.PhotoCalib(self.calibration, self.calibrationErr))

        # Difference Image
        source_image = afwImage.MaskedImageF(
            lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1))
        source_image.image[100, 100, afwImage.LOCAL] = 20
        source_image.getVariance().set(2)
        bbox = lsst.geom.BoxI(
            lsst.geom.PointI(1, 1),
            lsst.geom.ExtentI(self.imageSize[0],
                              self.imageSize[1]))
        masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL)
        self.diffim = afwImage.makeExposure(masked_image, self.wcs)
        self.diffim.setDetector(detector)
        self.diffim.getInfo().setVisitInfo(visit)
        self.diffim.setFilter(afwImage.Filter('g'))
        self.diffim.setPhotoCalib(afwImage.PhotoCalib(self.calibration, self.calibrationErr))

        self.expIdBits = 16

        FWHM = 5
        psf = measAlg.DoubleGaussianPsf(15, 15, FWHM/(2*np.sqrt(2*np.log(2))))
        self.exposure.setPsf(psf)
        self.diffim.setPsf(psf)

        self.testDiaObjects = create_test_dia_objects(5, self.wcs)
Exemplo n.º 17
0
    def _outputZeropoints(self,
                          camera,
                          zptCat,
                          visitCat,
                          offsets,
                          bands,
                          physicalFilterMap,
                          tract=None):
        """Output the zeropoints in fgcm_photoCalib format.

        Parameters
        ----------
        camera : `lsst.afw.cameraGeom.Camera`
            Camera from the butler.
        zptCat : `lsst.afw.table.BaseCatalog`
            FGCM zeropoint catalog from `FgcmFitCycleTask`.
        visitCat : `lsst.afw.table.BaseCatalog`
            FGCM visitCat from `FgcmBuildStarsTask`.
        offsets : `numpy.array`
            Float array of absolute calibration offsets, one for each filter.
        bands : `list` [`str`]
            List of band names from FGCM output.
        physicalFilterMap : `dict`
            Dictionary of mappings from physical filter to FGCM band.
        tract: `int`, optional
            Tract number to output.  Default is None (global calibration)

        Returns
        -------
        photoCalibCatalogs : `generator` [(`int`, `lsst.afw.table.ExposureCatalog`)]
            Generator that returns (visit, exposureCatalog) tuples.
        """
        # Select visit/ccds where we have a calibration
        # This includes ccds where we were able to interpolate from neighboring
        # ccds.
        cannot_compute = fgcm.fgcmUtilities.zpFlagDict[
            'CANNOT_COMPUTE_ZEROPOINT']
        selected = (((zptCat['fgcmFlag'] & cannot_compute) == 0)
                    & (zptCat['fgcmZptVar'] > 0.0)
                    & (zptCat['fgcmZpt'] > FGCM_ILLEGAL_VALUE))

        # Log warnings for any visit which has no valid zeropoints
        badVisits = np.unique(zptCat['visit'][~selected])
        goodVisits = np.unique(zptCat['visit'][selected])
        allBadVisits = badVisits[~np.isin(badVisits, goodVisits)]
        for allBadVisit in allBadVisits:
            self.log.warning(f'No suitable photoCalib for visit {allBadVisit}')

        # Get a mapping from filtername to the offsets
        offsetMapping = {}
        for f in physicalFilterMap:
            # Not every filter in the map will necesarily have a band.
            if physicalFilterMap[f] in bands:
                offsetMapping[f] = offsets[bands.index(physicalFilterMap[f])]

        # Get a mapping from "ccd" to the ccd index used for the scaling
        ccdMapping = {}
        for ccdIndex, detector in enumerate(camera):
            ccdMapping[detector.getId()] = ccdIndex

        # And a mapping to get the flat-field scaling values
        scalingMapping = {}
        for rec in visitCat:
            scalingMapping[rec['visit']] = rec['scaling']

        if self.config.doComposeWcsJacobian:
            approxPixelAreaFields = computeApproxPixelAreaFields(camera)

        # The zptCat is sorted by visit, which is useful
        lastVisit = -1
        zptVisitCatalog = None

        metadata = dafBase.PropertyList()
        metadata.add("COMMENT", "Catalog id is detector id, sorted.")
        metadata.add("COMMENT", "Only detectors with data have entries.")

        for rec in zptCat[selected]:
            # Retrieve overall scaling
            scaling = scalingMapping[rec['visit']][ccdMapping[rec['detector']]]

            # The postCalibrationOffset describe any zeropoint offsets
            # to apply after the fgcm calibration.  The first part comes
            # from the reference catalog match (used in testing).  The
            # second part comes from the mean chromatic correction
            # (if configured).
            postCalibrationOffset = offsetMapping[rec['filtername']]
            if self.config.doApplyMeanChromaticCorrection:
                postCalibrationOffset += rec['fgcmDeltaChrom']

            fgcmSuperStarField = self._getChebyshevBoundedField(
                rec['fgcmfZptSstarCheb'], rec['fgcmfZptChebXyMax'])
            # Convert from FGCM AB to nJy
            fgcmZptField = self._getChebyshevBoundedField(
                (rec['fgcmfZptCheb'] * units.AB).to_value(units.nJy),
                rec['fgcmfZptChebXyMax'],
                offset=postCalibrationOffset,
                scaling=scaling)

            if self.config.doComposeWcsJacobian:

                fgcmField = afwMath.ProductBoundedField([
                    approxPixelAreaFields[rec['detector']], fgcmSuperStarField,
                    fgcmZptField
                ])
            else:
                # The photoCalib is just the product of the fgcmSuperStarField and the
                # fgcmZptField
                fgcmField = afwMath.ProductBoundedField(
                    [fgcmSuperStarField, fgcmZptField])

            # The "mean" calibration will be set to the center of the ccd for reference
            calibCenter = fgcmField.evaluate(fgcmField.getBBox().getCenter())
            calibErr = (np.log(10.0) / 2.5) * calibCenter * np.sqrt(
                rec['fgcmZptVar'])
            photoCalib = afwImage.PhotoCalib(calibrationMean=calibCenter,
                                             calibrationErr=calibErr,
                                             calibration=fgcmField,
                                             isConstant=False)

            # Return full per-visit exposure catalogs
            if rec['visit'] != lastVisit:
                # This is a new visit.  If the last visit was not -1, yield
                # the ExposureCatalog
                if lastVisit > -1:
                    # ensure that the detectors are in sorted order, for fast lookups
                    zptVisitCatalog.sort()
                    yield (int(lastVisit), zptVisitCatalog)
                else:
                    # We need to create a new schema
                    zptExpCatSchema = afwTable.ExposureTable.makeMinimalSchema(
                    )
                    zptExpCatSchema.addField('visit',
                                             type='L',
                                             doc='Visit number')

                # And start a new one
                zptVisitCatalog = afwTable.ExposureCatalog(zptExpCatSchema)
                zptVisitCatalog.setMetadata(metadata)

                lastVisit = int(rec['visit'])

            catRecord = zptVisitCatalog.addNew()
            catRecord['id'] = int(rec['detector'])
            catRecord['visit'] = rec['visit']
            catRecord.setPhotoCalib(photoCalib)

        # Final output of last exposure catalog
        # ensure that the detectors are in sorted order, for fast lookups
        zptVisitCatalog.sort()
        yield (int(lastVisit), zptVisitCatalog)
Exemplo n.º 18
0
def make_exps(band_data, show=False):
    """
    make lsst stack exposures for each image and noise image
    """

    from lsst.afw.cameraGeom.testUtils import DetectorWrapper

    exps = []
    psf_exps = []
    byband_exps = {}
    byband_psf_exps = {}

    for band in band_data:
        bdata = band_data[band]

        byband_exps[band] = []
        byband_psf_exps[band] = []

        for epoch_ind, se_obs in enumerate(bdata):

            wcs = se_obs.wcs
            pos = wcs.toImage(wcs.center)
            # pos = wcs.center

            image = se_obs.image.array
            bmask = se_obs.bmask.array
            weight = se_obs.weight.array

            weight = se_obs.weight.array

            psf_gsimage, psf_offset = se_obs.get_psf(
                pos.x,
                pos.y,
                center_psf=False,
                get_offset=True,
            )
            psf_image = psf_gsimage.array

            # TODO: deal with zeros
            w = np.where(weight > 0)
            assert w[0].size == weight.size
            noise_var = 1.0 / weight

            sy, sx = image.shape

            masked_image = afw_image.MaskedImageF(sx, sy)
            masked_image.image.array[:, :] = image
            masked_image.variance.array[:, :] = noise_var
            masked_image.mask.array[:, :] = bmask

            # an exp for the PSF
            # we need to put a var here that is consistent with the
            # main image to get a consistent coadd.  I'm not sure
            # what the best choice is, using median for now TODO
            pny, pnx = psf_image.shape
            pmasked_image = afw_image.MaskedImageF(pny, pnx)
            pmasked_image.image.array[:, :] = psf_image
            pmasked_image.variance.array[:, :] = np.median(noise_var)
            pmasked_image.mask.array[:, :] = 0

            exp = afw_image.ExposureF(masked_image)
            psf_exp = afw_image.ExposureF(pmasked_image)

            zperr = 0.0
            calib_mean = (ZERO_POINT * units.ABmag).to_value(units.nJy)
            calib_err = (np.log(10.) / 2.5) * calib_mean * zperr
            calib = afw_image.PhotoCalib(calib_mean, calib_err)

            exp.setPsf(make_stack_psf(psf_image))
            exp.setWcs(make_stack_wcs(wcs))
            exp.setPhotoCalib(calib)

            psf_exp.setWcs(
                make_stack_psf_wcs(
                    dims=psf_gsimage.array.shape,
                    jac=psf_gsimage.wcs,
                    offset=psf_offset,
                    world_origin=wcs.center,
                ))

            detector = DetectorWrapper().detector
            exp.setDetector(detector)
            psf_exp.setDetector(detector)

            if show:
                from espy import images
                images.view(exp.image.array)
                # show_image_and_mask(exp)
                # input('hit a key')

            exps.append(exp)
            byband_exps[band].append(exp)

            psf_exps.append(psf_exp)
            byband_psf_exps[band].append(psf_exp)

    return exps, psf_exps, byband_exps, byband_psf_exps
Exemplo n.º 19
0
    def _outputZeropoints(self, butler, zptCat, visitCat, offsets, tract=None):
        """
        Output the zeropoints in fgcm_photoCalib format.

        Parameters
        ----------
        butler: `lsst.daf.persistence.Butler`
        zptCat: `lsst.afw.table.BaseCatalog`
           FGCM zeropoint catalog from `FgcmFitCycleTask`
        visitCat: `lsst.afw.table.BaseCatalog`
           FGCM visitCat from `FgcmBuildStarsTask`
        offsets: `numpy.array`
           Float array of absolute calibration offsets, one for each filter
        tract: `int`, optional
           Tract number to output.  Default is None (global calibration)
        """

        if tract is None:
            datasetType = 'fgcm_photoCalib'
        else:
            datasetType = 'fgcm_tract_photoCalib'

        self.log.info("Outputting %s objects" % (datasetType))

        # Select visit/ccds where we have a calibration
        # This includes ccds where we were able to interpolate from neighboring
        # ccds.
        cannot_compute = fgcm.fgcmUtilities.zpFlagDict[
            'CANNOT_COMPUTE_ZEROPOINT']
        too_few_stars = fgcm.fgcmUtilities.zpFlagDict['TOO_FEW_STARS_ON_CCD']
        selected = (((zptCat['fgcmFlag'] & cannot_compute) == 0) &
                    (zptCat['fgcmZptVar'] > 0.0))

        # We also select the "best" calibrations, avoiding interpolation.  These
        # are only used for mapping filternames
        selected_best = (((zptCat['fgcmFlag'] &
                           (cannot_compute | too_few_stars)) == 0) &
                         (zptCat['fgcmZptVar'] > 0.0))

        # Log warnings for any visit which has no valid zeropoints
        badVisits = np.unique(zptCat['visit'][~selected])
        goodVisits = np.unique(zptCat['visit'][selected])
        allBadVisits = badVisits[~np.isin(badVisits, goodVisits)]
        for allBadVisit in allBadVisits:
            self.log.warn(
                f'No suitable photoCalib for {self.visitDataRefName} {allBadVisit}'
            )

        # Get the mapping from filtername to dataId filter name, empirically
        filterMapping = {}
        nFound = 0
        for rec in zptCat[selected_best]:
            if rec['filtername'] in filterMapping:
                continue
            dataId = {
                self.visitDataRefName: int(rec['visit']),
                self.ccdDataRefName: int(rec['ccd'])
            }
            dataRef = butler.dataRef('raw', dataId=dataId)
            filterMapping[rec['filtername']] = dataRef.dataId['filter']
            nFound += 1
            if nFound == len(self.filterMap):
                break

        # Get a mapping from filtername to the offsets
        offsetMapping = {}
        for f in self.filterMap:
            # Not every filter in the map will necesarily have a band.
            if self.filterMap[f] in self.bands:
                offsetMapping[f] = offsets[self.bands.index(self.filterMap[f])]

        # Get a mapping from "ccd" to the ccd index used for the scaling
        camera = butler.get('camera')
        ccdMapping = {}
        for ccdIndex, detector in enumerate(camera):
            ccdMapping[detector.getId()] = ccdIndex

        # And a mapping to get the flat-field scaling values
        scalingMapping = {}
        for rec in visitCat:
            scalingMapping[rec['visit']] = rec['scaling']

        if self.config.doComposeWcsJacobian:
            approxPixelAreaFields = computeApproxPixelAreaFields(camera)

        for rec in zptCat[selected]:

            # Retrieve overall scaling
            scaling = scalingMapping[rec['visit']][ccdMapping[rec['ccd']]]

            # The postCalibrationOffset describe any zeropoint offsets
            # to apply after the fgcm calibration.  The first part comes
            # from the reference catalog match (used in testing).  The
            # second part comes from the mean chromatic correction
            # (if configured).
            postCalibrationOffset = offsetMapping[rec['filtername']]
            if self.config.doApplyMeanChromaticCorrection:
                postCalibrationOffset += rec['fgcmDeltaChrom']

            fgcmSuperStarField = self._getChebyshevBoundedField(
                rec['fgcmfZptSstarCheb'], rec['fgcmfZptChebXyMax'])
            # Convert from FGCM AB to nJy
            fgcmZptField = self._getChebyshevBoundedField(
                (rec['fgcmfZptCheb'] * units.AB).to_value(units.nJy),
                rec['fgcmfZptChebXyMax'],
                offset=postCalibrationOffset,
                scaling=scaling)

            if self.config.doComposeWcsJacobian:

                fgcmField = afwMath.ProductBoundedField([
                    approxPixelAreaFields[rec['ccd']], fgcmSuperStarField,
                    fgcmZptField
                ])
            else:
                # The photoCalib is just the product of the fgcmSuperStarField and the
                # fgcmZptField
                fgcmField = afwMath.ProductBoundedField(
                    [fgcmSuperStarField, fgcmZptField])

            # The "mean" calibration will be set to the center of the ccd for reference
            calibCenter = fgcmField.evaluate(fgcmField.getBBox().getCenter())
            calibErr = (np.log(10.0) / 2.5) * calibCenter * np.sqrt(
                rec['fgcmZptVar'])
            photoCalib = afwImage.PhotoCalib(calibrationMean=calibCenter,
                                             calibrationErr=calibErr,
                                             calibration=fgcmField,
                                             isConstant=False)

            if tract is None:
                butler.put(photoCalib,
                           datasetType,
                           dataId={
                               self.visitDataRefName: int(rec['visit']),
                               self.ccdDataRefName: int(rec['ccd']),
                               'filter': filterMapping[rec['filtername']]
                           })
            else:
                butler.put(photoCalib,
                           datasetType,
                           dataId={
                               self.visitDataRefName: int(rec['visit']),
                               self.ccdDataRefName: int(rec['ccd']),
                               'filter': filterMapping[rec['filtername']],
                               'tract': tract
                           })

        self.log.info("Done outputting %s objects" % (datasetType))
Exemplo n.º 20
0
    def _build_ccdImage(self, dataRef, associations, jointcalControl):
        """
        Extract the necessary things from this dataRef to add a new ccdImage.

        Parameters
        ----------
        dataRef : lsst.daf.persistence.ButlerDataRef
            dataRef to extract info from.
        associations : lsst.jointcal.Associations
            object to add the info to, to construct a new CcdImage
        jointcalControl : jointcal.JointcalControl
            control object for associations management

        Returns
        ------
        namedtuple
            wcs : lsst.afw.geom.SkyWcs
                the TAN WCS of this image, read from the calexp
            key : namedtuple
                a key to identify this dataRef by its visit and ccd ids
            filter : str
                this calexp's filter
        """
        if "visit" in dataRef.dataId.keys():
            visit = dataRef.dataId["visit"]
        else:
            visit = dataRef.getButler().queryMetadata("calexp", ("visit"),
                                                      dataRef.dataId)[0]

        src = dataRef.get("src",
                          flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS,
                          immediate=True)

        visitInfo = dataRef.get('calexp_visitInfo')
        detector = dataRef.get('calexp_detector')
        ccdId = detector.getId()
        calib = dataRef.get('calexp_calib')
        tanWcs = dataRef.get('calexp_wcs')
        bbox = dataRef.get('calexp_bbox')
        filt = dataRef.get('calexp_filter')
        filterName = filt.getName()
        fluxMag0 = calib.getFluxMag0()
        photoCalib = afwImage.PhotoCalib(1.0 / fluxMag0[0],
                                         fluxMag0[1] / fluxMag0[0]**2, bbox)

        goodSrc = self.sourceSelector.run(src)

        if len(goodSrc.sourceCat) == 0:
            self.log.warn("No sources selected in visit %s ccd %s", visit,
                          ccdId)
        else:
            self.log.info("%d sources selected in visit %d ccd %d",
                          len(goodSrc.sourceCat), visit, ccdId)
        associations.createCcdImage(goodSrc.sourceCat, tanWcs, visitInfo, bbox,
                                    filterName, photoCalib, detector, visit,
                                    ccdId, jointcalControl)

        Result = collections.namedtuple('Result_from_build_CcdImage',
                                        ('wcs', 'key', 'filter'))
        Key = collections.namedtuple('Key', ('visit', 'ccd'))
        return Result(tanWcs, Key(visit, ccdId), filterName)
Exemplo n.º 21
0
    def _outputZeropoints(self, butler, offsets):
        """
        Output the zeropoints in jointcal_photoCalib format.

        Parameters
        ----------
        butler: lsst.daf.persistence.Butler
        """

        self.log.info("Outputting jointcal_photoCalib objects")

        zptCat = butler.get('fgcmZeropoints', fgcmcycle=self.useCycle)
        visitCat = butler.get('fgcmVisitCatalog')

        # Only output those that we have a calibration
        selected = (zptCat['fgcmflag'] < 16)

        # Get the mapping from filtername to dataId filter name
        filterMapping = {}
        nFound = 0
        for rec in zptCat[selected]:
            if rec['filtername'] in filterMapping:
                continue
            dataId = {
                self.visitDataRefName: int(rec['visit']),
                self.ccdDataRefName: int(rec['ccd'])
            }
            dataRef = butler.dataRef('raw', dataId=dataId)
            filterMapping[rec['filtername']] = dataRef.dataId['filter']
            nFound += 1
            if nFound == len(self.filterToBand):
                break

        # Get a mapping from filtername to the offsets
        offsetMapping = {}
        for f in self.filterToBand:
            offsetMapping[f] = offsets[self.bands.index(self.filterToBand[f])]

        # Get a mapping from "ccd" to the ccd index used for the scaling
        camera = butler.get('camera')
        ccdMapping = {}
        for ccdIndex, detector in enumerate(camera):
            ccdMapping[detector.getId()] = ccdIndex

        # And a mapping to get the flat-field scaling values
        scalingMapping = {}
        for rec in visitCat:
            scalingMapping[rec['visit']] = rec['scaling']

        # Make a fixed variable to hold the parameters to build a ChebyshevBoundedField
        orderPlus1 = self.chebyshevOrder + 1

        pars = np.zeros((orderPlus1, orderPlus1))

        for rec in zptCat[selected]:

            if self.superStarSubCcd:
                # Spatially varying zeropoint
                bbox = lsst.geom.Box2I(
                    lsst.geom.Point2I(0.0, 0.0),
                    lsst.geom.Point2I(*rec['fgcmfzptchebxymax']))

                # Take the zeropoint, apply the absolute relative calibration offset,
                # and whatever flat-field scaling was applied
                pars[:, :] = (
                    rec['fgcmfzptcheb'].reshape(orderPlus1, orderPlus1) *
                    10.**(offsetMapping[rec['filtername']] / (-2.5)) *
                    scalingMapping[rec['visit']][ccdMapping[rec['ccd']]])

                # Apply absolute relative calibration offset to 0/0 term

                field = afwMath.ChebyshevBoundedField(bbox, pars)
                calibMean = field.mean()

                calibErr = (np.log(10.) / 2.5) * calibMean * rec['fgcmzpterr']

                photoCalib = afwImage.PhotoCalib(field, calibErr)

            else:
                # Spatially constant zeropoint

                # Take the zeropoint, apply the absolute relative calibration offset,
                # and whatever flat-field scaling was applied

                calibMean = (
                    10.**(rec['fgcmzpt'] / (-2.5)) *
                    10.**(offsetMapping[rec['filtername']] / (-2.5)) *
                    scalingMapping[rec['visit']][ccdMapping[rec['ccd']]])
                calibErr = (np.log(10.) / 2.5) * calibMean * rec['fgcmzpterr']
                photoCalib = afwImage.PhotoCalib(calibMean, calibErr)

            butler.put(photoCalib,
                       'jointcal_photoCalib',
                       dataId={
                           self.visitDataRefName: int(rec['visit']),
                           self.ccdDataRefName: int(rec['ccd']),
                           'filter': filterMapping[rec['filtername']],
                           'tract': 0
                       })

        self.log.info("Done outputting jointcal_photoCalib objects")
Exemplo n.º 22
0
    def testComputeExposureSummary(self):
        """Make a fake exposure and background and compute summary.
        """
        np.random.seed(12345)

        # Make an exposure with a noise image
        exposure = afwImage.ExposureF(100, 100)
        skySigma = 10.0
        exposure.getImage().getArray()[:, :] = np.random.normal(0.0,
                                                                skySigma,
                                                                size=(100,
                                                                      100))
        exposure.getVariance().getArray()[:, :] = skySigma**2.

        # Set the visitInfo
        date = DateTime(date=59234.7083333334, system=DateTime.DateSystem.MJD)
        observatory = Observatory(-70.7366 * lsst.geom.degrees,
                                  -30.2407 * lsst.geom.degrees, 2650.)
        visitInfo = afwImage.VisitInfo(exposureTime=10.0,
                                       date=date,
                                       observatory=observatory)
        exposure.getInfo().setVisitInfo(visitInfo)

        # Install a Gaussian PSF
        psfSize = 2.0
        psf = GaussianPsf(5, 5, psfSize)
        exposure.setPsf(psf)

        # Install a simple WCS
        scale = 0.2 * lsst.geom.arcseconds
        raCenter = 300.0 * lsst.geom.degrees
        decCenter = 0.0 * lsst.geom.degrees
        cdMatrix = makeCdMatrix(scale=scale)
        skyWcs = makeSkyWcs(crpix=exposure.getBBox().getCenter(),
                            crval=lsst.geom.SpherePoint(raCenter, decCenter),
                            cdMatrix=cdMatrix)
        exposure.setWcs(skyWcs)

        # Install a simple photoCalib
        photoCalib = afwImage.PhotoCalib(calibrationMean=0.3)
        zp = 2.5 * np.log10(photoCalib.getInstFluxAtZeroMagnitude())
        exposure.setPhotoCalib(photoCalib)

        # Compute the background image
        bgGridSize = 10
        bctrl = afwMath.BackgroundControl(afwMath.Interpolate.NATURAL_SPLINE)
        bctrl.setNxSample(
            int(exposure.getMaskedImage().getWidth() / bgGridSize) + 1)
        bctrl.setNySample(
            int(exposure.getMaskedImage().getHeight() / bgGridSize) + 1)
        backobj = afwMath.makeBackground(exposure.getMaskedImage().getImage(),
                                         bctrl)
        background = afwMath.BackgroundList()
        background.append(backobj)

        # Run the task
        expSummaryTask = ComputeExposureSummaryStatsTask()
        summary = expSummaryTask.run(exposure, None, background)

        # Test the outputs
        self.assertFloatsAlmostEqual(summary.psfSigma, psfSize)
        self.assertFloatsAlmostEqual(summary.psfIxx, psfSize**2.)
        self.assertFloatsAlmostEqual(summary.psfIyy, psfSize**2.)
        self.assertFloatsAlmostEqual(summary.psfIxy, 0.0)
        self.assertFloatsAlmostEqual(summary.psfArea, 23.088975164455444)

        delta = (scale * 50).asDegrees()
        for a, b in zip(summary.raCorners, [
                raCenter.asDegrees() + delta,
                raCenter.asDegrees() - delta,
                raCenter.asDegrees() - delta,
                raCenter.asDegrees() + delta
        ]):
            self.assertFloatsAlmostEqual(a, b, atol=1e-10)
        for a, b in zip(summary.decCorners, [
                decCenter.asDegrees() - delta,
                decCenter.asDegrees() - delta,
                decCenter.asDegrees() + delta,
                decCenter.asDegrees() + delta
        ]):
            self.assertFloatsAlmostEqual(a, b, atol=1e-10)

        self.assertFloatsAlmostEqual(summary.ra,
                                     raCenter.asDegrees(),
                                     atol=1e-10)
        self.assertFloatsAlmostEqual(summary.decl,
                                     decCenter.asDegrees(),
                                     atol=1e-10)

        self.assertFloatsAlmostEqual(summary.zeroPoint, zp)

        # Need to compare background level and noise
        # These are only approximately 0+/-10 because of the small image
        self.assertFloatsAlmostEqual(summary.skyBg, -0.079, atol=1e-3)

        self.assertFloatsAlmostEqual(summary.meanVar, skySigma**2.)

        self.assertFloatsAlmostEqual(summary.zenithDistance,
                                     30.57112,
                                     atol=1e-5)
Exemplo n.º 23
0
    def setUp(self):
        # metadata taken from CFHT data
        # v695856-e0/v695856-e0-c000-a00.sci_img.fits
        self.metadata = dafBase.PropertySet()

        self.metadata.set("SIMPLE", "T")
        self.metadata.set("BITPIX", -32)
        self.metadata.set("NAXIS", 2)
        self.metadata.set("NAXIS1", 1024)
        self.metadata.set("NAXIS2", 1153)
        self.metadata.set("RADECSYS", 'FK5')
        self.metadata.set("EQUINOX", 2000.)

        self.metadata.setDouble("CRVAL1", 215.604025685476)
        self.metadata.setDouble("CRVAL2", 53.1595451514076)
        self.metadata.setDouble("CRPIX1", 1109.99981456774)
        self.metadata.setDouble("CRPIX2", 560.018167811613)
        self.metadata.set("CTYPE1", 'RA---SIN')
        self.metadata.set("CTYPE2", 'DEC--SIN')

        self.metadata.setDouble("CD1_1", 5.10808596133527E-05)
        self.metadata.setDouble("CD1_2", 1.85579539217196E-07)
        self.metadata.setDouble("CD2_2", -5.10281493481982E-05)
        self.metadata.setDouble("CD2_1", -8.27440751733828E-07)

        self.wcs = afwGeom.makeSkyWcs(self.metadata)

        self.calibration = 10000
        self.calibrationErr = 100
        self.exposureId = 1234
        self.exposureTime = 200.
        self.imageSize = [1024, 1153]
        self.dateTime = "2014-05-13T17:00:00.000000000"

        # Make images  with one source in them and distinct values and
        # variance for each image.
        # Direct Image
        source_image = afwImage.MaskedImageF(
            lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1))
        source_image.image[100, 100, afwImage.LOCAL] = 10
        source_image.getVariance().set(1)
        bbox = lsst.geom.BoxI(
            lsst.geom.PointI(1, 1),
            lsst.geom.ExtentI(self.imageSize[0],
                              self.imageSize[1]))
        masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL)
        self.exposure = afwImage.makeExposure(masked_image, self.wcs)

        detector = DetectorWrapper(
            id=23, bbox=self.exposure.getBBox()).detector
        visit = afwImage.VisitInfo(
            exposureId=self.exposureId,
            exposureTime=self.exposureTime,
            date=dafBase.DateTime(self.dateTime,
                                  dafBase.DateTime.Timescale.TAI))
        self.exposure.info.id = self.exposureId
        self.exposure.setDetector(detector)
        self.exposure.getInfo().setVisitInfo(visit)
        self.exposure.setFilter(afwImage.FilterLabel(band='g', physical='g.MP9401'))
        self.exposure.setPhotoCalib(afwImage.PhotoCalib(self.calibration, self.calibrationErr))

        # Difference Image
        source_image = afwImage.MaskedImageF(
            lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1))
        source_image.image[100, 100, afwImage.LOCAL] = 20
        source_image.getVariance().set(2)
        bbox = lsst.geom.BoxI(
            lsst.geom.PointI(1, 1),
            lsst.geom.ExtentI(self.imageSize[0],
                              self.imageSize[1]))
        masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL)
        self.diffim = afwImage.makeExposure(masked_image, self.wcs)
        self.diffim.info.id = self.exposureId
        self.diffim.setDetector(detector)
        self.diffim.getInfo().setVisitInfo(visit)
        self.diffim.setFilter(afwImage.FilterLabel(band='g', physical='g.MP9401'))
        self.diffim.setPhotoCalib(afwImage.PhotoCalib(self.calibration, self.calibrationErr))

        self.expIdBits = 16

        FWHM = 5
        psf = measAlg.DoubleGaussianPsf(15, 15, FWHM/(2*np.sqrt(2*np.log(2))))
        self.exposure.setPsf(psf)
        self.diffim.setPsf(psf)

        self.testDiaObjects = create_test_dia_objects(5, self.wcs)
        # Add additional diaObjects that are outside of the above difference
        # and calexp visit images.
        objects = [
            (10000000, self.wcs.pixelToSky(-100000, -100000)),  # xy outside
            (10000001, self.wcs.pixelToSky(100, -100000)),  # y outside
            (10000002, self.wcs.pixelToSky(-100000, 100)),  # x outside
        ]
        extra = pandas.DataFrame({
            "diaObjectId": np.array([id for id, point in objects], dtype=np.int64),
            "ra": [point.getRa().asDegrees() for id, point in objects],
            "decl": [point.getDec().asDegrees() for id, point in objects]
        })
        self.testDiaObjects = pd.concat([self.testDiaObjects, extra], ignore_index=True)
        # Ids of objects that were "updated" during "ap_association"
        # processing.
        self.updatedTestIds = np.array([1, 2, 3, 4, 10000001], dtype=np.uint64)
        # Expecdted number of sources is the number of updated ids plus
        # any that are within the CCD footprint but are not in the
        # above list of ids.
        self.expectedDiaForcedSources = 6

        self.expected_n_columns = 11
    def setUp(self):
        # CFHT Filters from the camera mapper.
        self.filter_names = ["u", "g", "r", "i", "z"]
        afwImageUtils.resetFilters()
        afwImageUtils.defineFilter('u', lambdaEff=374, alias="u.MP9301")
        afwImageUtils.defineFilter('g', lambdaEff=487, alias="g.MP9401")
        afwImageUtils.defineFilter('r', lambdaEff=628, alias="r.MP9601")
        afwImageUtils.defineFilter('i', lambdaEff=778, alias="i.MP9701")
        afwImageUtils.defineFilter('z', lambdaEff=1170, alias="z.MP9801")

        # metadata taken from CFHT data
        # v695856-e0/v695856-e0-c000-a00.sci_img.fits
        self.metadata = dafBase.PropertySet()

        self.metadata.set("SIMPLE", "T")
        self.metadata.set("BITPIX", -32)
        self.metadata.set("NAXIS", 2)
        self.metadata.set("NAXIS1", 1024)
        self.metadata.set("NAXIS2", 1153)
        self.metadata.set("RADECSYS", 'FK5')
        self.metadata.set("EQUINOX", 2000.)

        self.metadata.setDouble("CRVAL1", 215.604025685476)
        self.metadata.setDouble("CRVAL2", 53.1595451514076)
        self.metadata.setDouble("CRPIX1", 1109.99981456774)
        self.metadata.setDouble("CRPIX2", 560.018167811613)
        self.metadata.set("CTYPE1", 'RA---SIN')
        self.metadata.set("CTYPE2", 'DEC--SIN')

        self.metadata.setDouble("CD1_1", 5.10808596133527E-05)
        self.metadata.setDouble("CD1_2", 1.85579539217196E-07)
        self.metadata.setDouble("CD2_2", -5.10281493481982E-05)
        self.metadata.setDouble("CD2_1", -8.27440751733828E-07)

        self.wcs = afwGeom.makeSkyWcs(self.metadata)

        self.calibration = 10000
        self.calibrationErr = 100
        self.exposureId = 1234
        self.exposureTime = 200.
        self.imageSize = [1024, 1153]
        self.dateTime = "2014-05-13T17:00:00.000000000"

        # Make images  with one source in them and distinct values and
        # variance for each image.
        # Direct Image
        source_image = afwImage.MaskedImageF(
            lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1))
        source_image.image[100, 100, afwImage.LOCAL] = 10
        source_image.getVariance().set(1)
        bbox = lsst.geom.BoxI(
            lsst.geom.PointI(1, 1),
            lsst.geom.ExtentI(self.imageSize[0], self.imageSize[1]))
        masked_image = afwImage.MaskedImageF(source_image, bbox,
                                             afwImage.LOCAL)
        self.exposure = afwImage.makeExposure(masked_image, self.wcs)

        detector = DetectorWrapper(id=23,
                                   bbox=self.exposure.getBBox()).detector
        visit = afwImage.VisitInfo(exposureId=self.exposureId,
                                   exposureTime=self.exposureTime,
                                   date=dafBase.DateTime(
                                       self.dateTime,
                                       dafBase.DateTime.Timescale.TAI))
        self.exposure.setDetector(detector)
        self.exposure.getInfo().setVisitInfo(visit)
        self.exposure.setFilter(afwImage.Filter('g'))
        self.exposure.setPhotoCalib(
            afwImage.PhotoCalib(self.calibration, self.calibrationErr))

        # Difference Image
        source_image = afwImage.MaskedImageF(
            lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1))
        source_image.image[100, 100, afwImage.LOCAL] = 20
        source_image.getVariance().set(2)
        bbox = lsst.geom.BoxI(
            lsst.geom.PointI(1, 1),
            lsst.geom.ExtentI(self.imageSize[0], self.imageSize[1]))
        masked_image = afwImage.MaskedImageF(source_image, bbox,
                                             afwImage.LOCAL)
        self.diffim = afwImage.makeExposure(masked_image, self.wcs)
        self.diffim.setDetector(detector)
        self.diffim.getInfo().setVisitInfo(visit)
        self.diffim.setFilter(afwImage.Filter('g'))
        self.diffim.setPhotoCalib(
            afwImage.PhotoCalib(self.calibration, self.calibrationErr))

        self.expIdBits = 16

        FWHM = 5
        psf = measAlg.DoubleGaussianPsf(15, 15,
                                        FWHM / (2 * np.sqrt(2 * np.log(2))))
        self.exposure.setPsf(psf)
        self.diffim.setPsf(psf)

        self.testDiaObjects = create_test_dia_objects(5, self.wcs)
        # Add additional diaObjects that are outside of the above difference
        # and calexp visit images.
        # xy outside
        src = self.testDiaObjects.addNew()
        src['id'] = 10000000
        src.setCoord(self.wcs.pixelToSky(-100000, -100000))
        # y outside
        src = self.testDiaObjects.addNew()
        src['id'] = 10000001
        src.setCoord(self.wcs.pixelToSky(100, -100000))
        # x outside
        src = self.testDiaObjects.addNew()
        src['id'] = 10000002
        src.setCoord(self.wcs.pixelToSky(-100000, 100))
        # Ids of objects that were "updated" during "ap_association"
        # processing.
        self.updatedTestIds = np.array([1, 2, 3, 4, 10000001], dtype=np.uint64)
        # Expecdted number of sources is the number of updated ids plus
        # any that are within the CCD footprint but are not in the
        # above list of ids.
        self.expectedDiaForcedSources = 6

        self.expected_n_columns = 11