Esempio n. 1
0
def summarizeVisit(butler, *, exp=None, extendedSummary=False, **kwargs):
    from astroquery.simbad import Simbad
    import astropy.units as u
    from astropy.time import Time
    from astropy.coordinates import SkyCoord, EarthLocation, AltAz

    def _airMassFromrRawMd(md):
        auxTelLocation = EarthLocation(lat=-30.244639 * u.deg,
                                       lon=-70.749417 * u.deg,
                                       height=2663 * u.m)
        time = Time(md['DATE-OBS'])
        skyLocation = SkyCoord(md['RASTART'], md['DECSTART'], unit=u.deg)
        altAz = AltAz(obstime=time, location=auxTelLocation)
        observationAltAz = skyLocation.transform_to(altAz)
        return observationAltAz.secz.value

    items = ["OBJECT", "expTime", "FILTER", "imageType"]
    obj, expTime, filterCompound, imageType = butler.queryMetadata(
        'raw', items, **kwargs)[0]
    filt, grating = filterCompound.split('~')
    rawMd = butler.get('raw_md', **kwargs)
    airmass = _airMassFromrRawMd(rawMd)

    print(f"Object name: {obj}")
    print(f"expTime:     {expTime}s")
    print(f"imageType:   {imageType}")
    print(f"Filter:      {filt}")
    print(f"Grating:     {grating}")
    print(f"Airmass:     {airmass:.3f}")

    if imageType not in ['BIAS', 'FLAT', 'DARK']:
        simbadObj = Simbad.query_object(obj)
        if simbadObj is None:
            print(f"Failed to find {obj} in Simbad.")
        else:
            assert (len(simbadObj.as_array()) == 1)
            raStr = simbadObj[0]['RA']
            decStr = simbadObj[0]['DEC']
            skyLocation = SkyCoord(raStr,
                                   decStr,
                                   unit=(u.hourangle, u.degree),
                                   frame='icrs')
            raRad, decRad = skyLocation.ra.rad, skyLocation.dec.rad
            print(f"obj RA  (str):   {raStr}")
            print(f"obj DEC (str):   {decStr}")
            print(f"obj RA  (rad):   {raRad:5f}")
            print(f"obj DEC (rad):   {decRad:5f}")
            print(f"obj RA  (deg):   {raRad*180/math.pi:5f}")
            print(f"obj DEC (deg):   {decRad*180/math.pi:5f}")

            if exp is not None:  # calc source coords from exp wcs
                ra = geom.Angle(raRad)
                dec = geom.Angle(decRad)
                targetLocation = geom.SpherePoint(ra, dec)
                pixCoord = exp.getWcs().skyToPixel(targetLocation)
                print(exp.getWcs())
                print(f"Source location: {pixCoord} using exp provided")
            else:  # try to find one, but not too hard
                datasetTypes = ['calexp', 'quickLookExp', 'postISRCCD']
                for datasetType in datasetTypes:
                    wcs = None
                    typeUsed = None
                    try:
                        wcs = butler.get(datasetType + '_wcs', **kwargs)
                        typeUsed = datasetType
                        break
                    except butlerExcept.NoResults:
                        pass
                if wcs is not None:
                    ra = geom.Angle(raRad)
                    dec = geom.Angle(decRad)
                    targetLocation = geom.SpherePoint(ra, dec)
                    pixCoord = wcs.skyToPixel(targetLocation)
                    print(wcs)
                    print(f"Source location: {pixCoord} using {typeUsed}")

    if extendedSummary:
        print('\n--- Extended Summary ---')
        ranIsr = False
        if exp is None:
            print("Running isr to compute image stats...")

            # catch all the ISR chat
            # logRedirection1 = LogRedirect(1, open(os.devnull, 'w'))
            # logRedirection2 = LogRedirect(2, open(os.devnull, 'w'))
            # import ipdb as pdb; pdb.set_trace()
            from lsst.ip.isr.isrTask import IsrTask
            isrConfig = IsrTask.ConfigClass()
            isrConfig.doLinearize = False
            isrConfig.doBias = False
            isrConfig.doFlat = False
            isrConfig.doDark = False
            isrConfig.doFringe = False
            isrConfig.doDefect = False
            isrConfig.doWrite = False
            isrTask = IsrTask(config=isrConfig)
            dataRef = butler.dataRef('raw', **kwargs)
            exp = isrTask.runDataRef(dataRef).exposure
            wcs = exp.getWcs()
            ranIsr = True
            # logRedirection1.finish()  # end re-direct
            # logRedirection2.finish()  # end re-direct

            print(wcs)
        if simbadObj and ranIsr:
            ra = geom.Angle(raRad)
            dec = geom.Angle(decRad)
            targetLocation = geom.SpherePoint(ra, dec)
            pixCoord = wcs.skyToPixel(targetLocation)
            print(
                f"Source location: {pixCoord} using postISR just-reconstructed wcs"
            )

        print(
            f'\nImage stats from {"just-constructed" if ranIsr else "provided"} exp:\n'
        )
        print(f'Image mean:   {np.mean(exp.image.array):.2f}')
        print(f'Image median: {np.median(exp.image.array):.2f}')
        print(f'Image min:    {np.min(exp.image.array):.2f}')
        print(f'Image max:    {np.max(exp.image.array):.2f}')
        # TODO: quartiles/percentiles here
        # number of masked pixels, saturated pixels

        print()
        print(f'BAD pixels:      {countPixels(exp.maskedImage, "BAD")}')
        print(f'SAT pixels:      {countPixels(exp.maskedImage, "SAT")}')
        print(f'CR pixels:       {countPixels(exp.maskedImage, "CR")}')
        print(f'INTRP pixels:    {countPixels(exp.maskedImage, "INTRP")}')
        print(f'DETECTED pixels: {countPixels(exp.maskedImage, "DETECTED")}')

        # detector = exp.getDetector()
        visitInfo = exp.getInfo().getVisitInfo()
        rotAngle = visitInfo.getBoresightRotAngle()
        boresight = visitInfo.getBoresightRaDec()
        md = butler.get('raw_md', **kwargs)

        print("\n From VisitInfo:")
        print(f"boresight: {boresight}")
        print(f"rotAngle:  {rotAngle}")
        print(f"  →        {rotAngle.asDegrees():.4f} deg")

        print("\n From raw_md:")
        print(f"ROTPA:     {md['ROTPA']} deg")
        print(f"  →        {(md['ROTPA']*math.pi/180):.6f} rad")
Esempio n. 2
0
class IsrTaskUnTrimmedTestCases(lsst.utils.tests.TestCase):
    """Test IsrTask methods using untrimmed raw data.
    """
    def setUp(self):
        self.config = IsrTaskConfig()
        self.config.qa = IsrQaConfig()
        self.task = IsrTask(config=self.config)

        self.mockConfig = isrMock.IsrMockConfig()
        self.mockConfig.isTrimmed = False
        self.doGenerateImage = True
        self.dataRef = isrMock.DataRefMock(config=self.mockConfig)
        self.camera = isrMock.IsrMock(config=self.mockConfig).getCamera()

        self.inputExp = isrMock.RawMock(config=self.mockConfig).run()
        self.amp = self.inputExp.getDetector()[0]
        self.mi = self.inputExp.getMaskedImage()

    def batchSetConfiguration(self, value):
        """Set the configuration state to a consistent value.

        Disable options we do not need as well.

        Parameters
        ----------
        value : `bool`
            Value to switch common ISR configuration options to.
        """
        self.config.qa.flatness.meshX = 20
        self.config.qa.flatness.meshY = 20
        self.config.doWrite = False
        self.config.doLinearize = False
        self.config.doCrosstalk = False

        self.config.doConvertIntToFloat = value
        self.config.doSaturation = value
        self.config.doSuspect = value
        self.config.doSetBadRegions = value
        self.config.doOverscan = value
        self.config.doBias = value
        self.config.doVariance = value
        self.config.doWidenSaturationTrails = value
        self.config.doBrighterFatter = value
        self.config.doDefect = value
        self.config.doSaturationInterpolation = value
        self.config.doDark = value
        self.config.doStrayLight = value
        self.config.doFlat = value
        self.config.doFringe = value
        self.config.doMeasureBackground = value
        self.config.doVignette = value
        self.config.doAttachTransmissionCurve = value
        self.config.doUseOpticsTransmission = value
        self.config.doUseFilterTransmission = value
        self.config.doUseSensorTransmission = value
        self.config.doUseAtmosphereTransmission = value
        self.config.qa.saveStats = value
        self.config.qa.doThumbnailOss = value
        self.config.qa.doThumbnailFlattened = value

        self.config.doApplyGains = not value
        self.config.doCameraSpecificMasking = value

    def validateIsrResults(self):
        """results should be a struct with components that are
        not None if included in the configuration file.

        Returns
        -------
        results : `pipeBase.Struct`
            Results struct generated from the current ISR configuration.
        """
        self.task = IsrTask(config=self.config)
        results = self.task.run(
            self.inputExp,
            camera=self.camera,
            bias=self.dataRef.get("bias"),
            dark=self.dataRef.get("dark"),
            flat=self.dataRef.get("flat"),
            bfKernel=self.dataRef.get("bfKernel"),
            defects=self.dataRef.get("defects"),
            fringes=Struct(fringes=self.dataRef.get("fringe"), seed=1234),
            opticsTransmission=self.dataRef.get("transmission_"),
            filterTransmission=self.dataRef.get("transmission_"),
            sensorTransmission=self.dataRef.get("transmission_"),
            atmosphereTransmission=self.dataRef.get("transmission_"))

        self.assertIsInstance(results, Struct)
        self.assertIsInstance(results.exposure, afwImage.Exposure)
        return results

    def test_overscanCorrection(self):
        """Expect that this should reduce the image variance with a full fit.
        The default fitType of MEDIAN will reduce the median value.

        This needs to operate on a RawMock() to have overscan data to use.

        The output types may be different when fitType != MEDIAN.
        """
        statBefore = computeImageMedianAndStd(
            self.inputExp.image[self.amp.getRawDataBBox()])
        oscanResults = self.task.overscanCorrection(self.inputExp, self.amp)
        self.assertIsInstance(oscanResults, Struct)
        self.assertIsInstance(oscanResults.imageFit, float)
        self.assertIsInstance(oscanResults.overscanFit, float)
        self.assertIsInstance(oscanResults.overscanImage,
                              afwImage.MaskedImageF)

        statAfter = computeImageMedianAndStd(
            self.inputExp.image[self.amp.getRawDataBBox()])
        self.assertLess(statAfter[0], statBefore[0])

    def test_overscanCorrectionMedianPerRow(self):
        """Expect that this should reduce the image variance with a full fit.
        fitType of MEDIAN_PER_ROW will reduce the median value.

        This needs to operate on a RawMock() to have overscan data to use.

        The output types may be different when fitType != MEDIAN_PER_ROW.
        """
        self.config.overscan.fitType = 'MEDIAN_PER_ROW'
        statBefore = computeImageMedianAndStd(
            self.inputExp.image[self.amp.getRawDataBBox()])
        oscanResults = self.task.overscanCorrection(self.inputExp, self.amp)
        self.assertIsInstance(oscanResults, Struct)
        self.assertIsInstance(oscanResults.imageFit, afwImage.ImageF)
        self.assertIsInstance(oscanResults.overscanFit, afwImage.ImageF)
        self.assertIsInstance(oscanResults.overscanImage,
                              afwImage.MaskedImageF)

        statAfter = computeImageMedianAndStd(
            self.inputExp.image[self.amp.getRawDataBBox()])
        self.assertLess(statAfter[0], statBefore[0])

    def test_runDataRef(self):
        """Expect a dataRef to be handled correctly.
        """
        self.config.doLinearize = False
        self.config.doWrite = False
        self.task = IsrTask(config=self.config)
        results = self.task.runDataRef(self.dataRef)

        self.assertIsInstance(results, Struct)
        self.assertIsInstance(results.exposure, afwImage.Exposure)

    def test_run_allTrue(self):
        """Expect successful run with expected outputs when all non-exclusive
        configuration options are on.

        Output results should be tested more precisely by the
        individual function tests.

        """
        self.batchSetConfiguration(True)
        self.validateIsrResults()

    def test_run_allFalse(self):
        """Expect successful run with expected outputs when all non-exclusive
        configuration options are off.

        Output results should be tested more precisely by the
        individual function tests.

        """
        self.batchSetConfiguration(False)
        self.validateIsrResults()

    def test_failCases(self):
        """Expect failure with crosstalk enabled.

        Output results should be tested more precisely by the
        individual function tests.
        """
        self.batchSetConfiguration(True)

        # This breaks it
        self.config.doCrosstalk = True

        with self.assertRaises(RuntimeError):
            self.validateIsrResults()

    def test_maskingCase_negativeVariance(self):
        """Test masking cases of configuration parameters.
        """
        self.batchSetConfiguration(True)
        self.config.overscanFitType = "POLY"
        self.config.overscanOrder = 1

        self.config.doSaturation = False
        self.config.doWidenSaturationTrails = False
        self.config.doSaturationInterpolation = False
        self.config.doSuspect = False
        self.config.doSetBadRegions = False
        self.config.doDefect = False
        self.config.doBrighterFatter = False

        self.config.maskNegativeVariance = True
        self.config.doInterpolate = False

        results = self.validateIsrResults()

        self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 40800)

    def test_maskingCase_noMasking(self):
        """Test masking cases of configuration parameters.
        """
        self.batchSetConfiguration(True)
        self.config.overscanFitType = "POLY"
        self.config.overscanOrder = 1

        self.config.doSaturation = False
        self.config.doWidenSaturationTrails = False
        self.config.doSaturationInterpolation = False
        self.config.doSuspect = False
        self.config.doSetBadRegions = False
        self.config.doDefect = False
        self.config.doBrighterFatter = False

        self.config.maskNegativeVariance = False
        self.config.doInterpolate = False

        results = self.validateIsrResults()

        self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0)

    def test_maskingCase_satMasking(self):
        """Test masking cases of configuration parameters.
        """
        self.batchSetConfiguration(True)
        self.config.overscanFitType = "POLY"
        self.config.overscanOrder = 1

        self.config.saturation = 20000.0
        self.config.doSaturation = True
        self.config.doWidenSaturationTrails = True

        self.config.doSaturationInterpolation = False
        self.config.doSuspect = False
        self.config.doSetBadRegions = False
        self.config.doDefect = False
        self.config.doBrighterFatter = False

        self.config.maskNegativeVariance = False  # These are mock images.

        results = self.validateIsrResults()

        self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0)

    def test_maskingCase_satMaskingAndInterp(self):
        """Test masking cases of configuration parameters.
        """
        self.batchSetConfiguration(True)
        self.config.overscanFitType = "POLY"
        self.config.overscanOrder = 1

        self.config.saturation = 20000.0
        self.config.doSaturation = True
        self.config.doWidenSaturationTrails = True
        self.config.doSaturationInterpolation = True

        self.config.doSuspect = False
        self.config.doSetBadRegions = False
        self.config.doDefect = False
        self.config.doBrighterFatter = False

        self.config.maskNegativeVariance = False  # These are mock images.

        results = self.validateIsrResults()

        self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0)

    def test_maskingCase_throughEdge(self):
        """Test masking cases of configuration parameters.
        """
        self.batchSetConfiguration(True)
        self.config.overscanFitType = "POLY"
        self.config.overscanOrder = 1

        self.config.saturation = 20000.0
        self.config.doSaturation = True
        self.config.doWidenSaturationTrails = True
        self.config.doSaturationInterpolation = True
        self.config.numEdgeSuspect = 5
        self.config.doSuspect = True

        self.config.doSetBadRegions = False
        self.config.doDefect = False
        self.config.doBrighterFatter = False

        self.config.maskNegativeVariance = False  # These are mock images.

        results = self.validateIsrResults()

        self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0)

    def test_maskingCase_throughDefects(self):
        """Test masking cases of configuration parameters.
        """
        self.batchSetConfiguration(True)
        self.config.overscanFitType = "POLY"
        self.config.overscanOrder = 1

        self.config.saturation = 20000.0
        self.config.doSaturation = True
        self.config.doWidenSaturationTrails = True
        self.config.doSaturationInterpolation = True
        self.config.numEdgeSuspect = 5
        self.config.doSuspect = True
        self.config.doDefect = True

        self.config.doSetBadRegions = False
        self.config.doBrighterFatter = False

        self.config.maskNegativeVariance = False  # These are mock images.

        results = self.validateIsrResults()

        self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 2000)
        self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 3940)
        self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 2000)

    def test_maskingCase_throughDefectsAmpEdges(self):
        """Test masking cases of configuration parameters.
        """
        self.batchSetConfiguration(True)
        self.config.overscanFitType = "POLY"
        self.config.overscanOrder = 1

        self.config.saturation = 20000.0
        self.config.doSaturation = True
        self.config.doWidenSaturationTrails = True
        self.config.doSaturationInterpolation = True
        self.config.numEdgeSuspect = 5
        self.config.doSuspect = True
        self.config.doDefect = True
        self.config.edgeMaskLevel = 'AMP'

        self.config.doSetBadRegions = False
        self.config.doBrighterFatter = False

        self.config.maskNegativeVariance = False  # These are mock images.

        results = self.validateIsrResults()

        self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 2000)
        self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 11280)
        self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 2000)

    def test_maskingCase_throughBad(self):
        """Test masking cases of configuration parameters.
        """
        self.batchSetConfiguration(True)
        self.config.overscanFitType = "POLY"
        self.config.overscanOrder = 1

        self.config.saturation = 20000.0
        self.config.doSaturation = True
        self.config.doWidenSaturationTrails = True
        self.config.doSaturationInterpolation = True

        self.config.doSuspect = True
        self.config.doDefect = True
        self.config.doSetBadRegions = True
        self.config.doBrighterFatter = False

        self.config.maskNegativeVariance = False  # These are mock images.

        results = self.validateIsrResults()

        self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 2000)
        self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
        self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 2000)