def readTransmissionCurveFromFile(filename, unit="angstrom", atMin=None, atMax=None):
    """Load a spatial TransmissionCurve from a text file with wavelengths and
    throughputs in columns.

    Parameters
    ----------
    filename : `str`
        Name of the file to read.
    unit : `str`
        Wavelength unit; one of "nm" or "angstrom".
    atMin : `float`
        Throughput to use at wavelengths below the tabulated minimum.  If
        ``None``, the tabulated throughput at the mininum will be used.
    atMax : `float`
        Throughput to use at wavelengths above the tabulated maximum.  If
        ``None``, the tabulated throughput at the maximum will be used.
    """
    wavelengths, throughput = np.loadtxt(os.path.join(DATA_DIR, filename), usecols=[0, 1], unpack=True)
    i = np.argsort(wavelengths)
    wavelengths = wavelengths[i]
    throughput = throughput[i]
    if unit == "nm":
        wavelengths *= 10
    elif unit != "angstrom":
        raise ValueError("Invalid wavelength unit")
    if atMin is None:
        atMin = throughput[0]
    if atMax is None:
        atMax = throughput[-1]
    return TransmissionCurve.makeSpatiallyConstant(throughput=throughput, wavelengths=wavelengths,
                                                   throughputAtMin=atMin, throughputAtMax=atMax)
Exemplo n.º 2
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.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 getFilterTransmission():
    """Return a nested dictionary of TransmissionCurves describing the
    throughput of each HSC filter.

    Outer directionary keys are string dates (YYYY-MM-DD), with values
    a dictionary mapping filter name to TransmissionCurve.  If the curve
    is spatially varying, it will be defined in pixel coordinates.

    Filter curve names are in the long form used as data ID values (e.g.
    'HSC-I').

    Outer dictionary values may be None to indicate that no TransmissionCurve
    is valid after the date provided in the key.
    """
    module = {}
    filename = os.path.join(DATA_DIR, "filterTraces.py")
    with open(filename) as file:
        exec(compile(file.read(), filename, mode='exec'), module)
    result = {}
    for band, data in module["FILTER_DATA"].items():
        result[getLongFilterName(band)] = TransmissionCurve.makeRadial(
            throughput=data["T"], wavelengths=data["lam"]*10,
            radii=data['radius']/module["PIXEL_SIZE"],
            throughputAtMin=0.0, throughputAtMax=0.0
        )
    for filename in glob.glob(os.path.join(DATA_DIR, "wHSC-*.txt")):
        band = getLongFilterName(os.path.split(filename)[1][len("wHSC-"): -len(".txt")])
        if band not in result:
            result[band] = readTransmissionCurveFromFile(filename, atMin=0.0, atMax=0.0)
    return {HSC_BEGIN: result}
 def testPersistence(self):
     wavelengths = np.linspace(4000, 7000, 200)
     with lsst.utils.tests.getTempFilePath(".fits") as filename:
         self.curveCoadd.writeFits(filename)
         roundtripped = TransmissionCurve.readFits(filename)
     for i in range(10):
         point = self.makeRandomPoint(self.bboxCoadd)
         try:
             throughput1 = self.curveCoadd.sampleAt(point, wavelengths)
         except InvalidParameterError:
             self.assertRaises(InvalidParameterError, roundtripped.sampleAt, point, wavelengths)
         else:
             throughput2 = roundtripped.sampleAt(point, wavelengths)
             self.assertFloatsAlmostEqual(throughput1, throughput2, atol=1e-10)
Exemplo n.º 5
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:])
Exemplo n.º 6
0
 def testPersistence(self):
     wavelengths = np.linspace(4000, 7000, 200)
     with lsst.utils.tests.getTempFilePath(".fits") as filename:
         self.curveCoadd.writeFits(filename)
         roundtripped = TransmissionCurve.readFits(filename)
     for i in range(10):
         point = self.makeRandomPoint(self.bboxCoadd)
         try:
             throughput1 = self.curveCoadd.sampleAt(point, wavelengths)
         except InvalidParameterError:
             self.assertRaises(InvalidParameterError, roundtripped.sampleAt,
                               point, wavelengths)
         else:
             throughput2 = roundtripped.sampleAt(point, wavelengths)
             self.assertFloatsAlmostEqual(throughput1,
                                          throughput2,
                                          atol=1e-10)
Exemplo n.º 7
0
    def _outputAtmospheres(self, handleDict, atmCat):
        """
        Output the atmospheres.

        Parameters
        ----------
        handleDict : `dict`
            All data handles are `lsst.daf.butler.DeferredDatasetHandle`
            The handleDict has the follownig keys:

            ``"fgcmLookUpTable"``
                handle for the FGCM look-up table.
        atmCat : `lsst.afw.table.BaseCatalog`
            FGCM atmosphere parameter catalog from fgcmFitCycleTask.

        Returns
        -------
        atmospheres : `generator` [(`int`, `lsst.afw.image.TransmissionCurve`)]
            Generator that returns (visit, transmissionCurve) tuples.
        """
        # First, we need to grab the look-up table and key info
        lutCat = handleDict['fgcmLookUpTable'].get()

        atmosphereTableName = lutCat[0]['tablename']
        elevation = lutCat[0]['elevation']
        atmLambda = lutCat[0]['atmLambda']
        lutCat = None

        # Make the atmosphere table if possible
        try:
            atmTable = fgcm.FgcmAtmosphereTable.initWithTableName(
                atmosphereTableName)
            atmTable.loadTable()
        except IOError:
            atmTable = None

        if atmTable is None:
            # Try to use MODTRAN instead
            try:
                modGen = fgcm.ModtranGenerator(elevation)
                lambdaRange = np.array([atmLambda[0], atmLambda[-1]]) / 10.
                lambdaStep = (atmLambda[1] - atmLambda[0]) / 10.
            except (ValueError, IOError) as e:
                raise RuntimeError(
                    "FGCM look-up-table generated with modtran, "
                    "but modtran not configured to run.") from e

        zenith = np.degrees(np.arccos(1. / atmCat['secZenith']))

        for i, visit in enumerate(atmCat['visit']):
            if atmTable is not None:
                # Interpolate the atmosphere table
                atmVals = atmTable.interpolateAtmosphere(
                    pmb=atmCat[i]['pmb'],
                    pwv=atmCat[i]['pwv'],
                    o3=atmCat[i]['o3'],
                    tau=atmCat[i]['tau'],
                    alpha=atmCat[i]['alpha'],
                    zenith=zenith[i],
                    ctranslamstd=[atmCat[i]['cTrans'], atmCat[i]['lamStd']])
            else:
                # Run modtran
                modAtm = modGen(
                    pmb=atmCat[i]['pmb'],
                    pwv=atmCat[i]['pwv'],
                    o3=atmCat[i]['o3'],
                    tau=atmCat[i]['tau'],
                    alpha=atmCat[i]['alpha'],
                    zenith=zenith[i],
                    lambdaRange=lambdaRange,
                    lambdaStep=lambdaStep,
                    ctranslamstd=[atmCat[i]['cTrans'], atmCat[i]['lamStd']])
                atmVals = modAtm['COMBINED']

            # Now need to create something to persist...
            curve = TransmissionCurve.makeSpatiallyConstant(
                throughput=atmVals,
                wavelengths=atmLambda,
                throughputAtMin=atmVals[0],
                throughputAtMax=atmVals[-1])

            yield (int(visit), curve)
    def _outputAtmospheres(self, butler):
        """
        Output the atmospheres.

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

        self.log.info("Outputting atmosphere transmissions")

        # First, we need to grab the look-up table and key info
        lutCat = butler.get('fgcmLookUpTable')

        atmosphereTableName = lutCat[0]['tablename']
        elevation = lutCat[0]['elevation']
        atmLambda = lutCat[0]['atmLambda']
        lutCat = None

        # Make the atmosphere table if possible
        try:
            atmTable = fgcm.FgcmAtmosphereTable.initWithTableName(
                atmosphereTableName)
            atmTable.loadTable()
        except IOError:
            atmTable = None

        if atmTable is None:
            # Try to use MODTRAN instead
            try:
                modGen = fgcm.ModtranGenerator(elevation)
                lambdaRange = np.array([atmLambda[0], atmLambda[-1]]) / 10.
                lambdaStep = (atmLambda[1] - atmLambda[0]) / 10.
            except (ValueError, IOError) as e:
                raise RuntimeError(
                    "FGCM look-up-table generated with modtran, "
                    "but modtran not configured to run.") from e

        # Next, we need to grab the atmosphere parameters
        atmCat = butler.get('fgcmAtmosphereParameters',
                            fgcmcycle=self.config.cycleNumber)

        zenith = np.degrees(np.arccos(1. / atmCat['secZenith']))

        for i, visit in enumerate(atmCat['visit']):
            if atmTable is not None:
                # Interpolate the atmosphere table
                atmVals = atmTable.interpolateAtmosphere(
                    pmb=atmCat[i]['pmb'],
                    pwv=atmCat[i]['pwv'],
                    o3=atmCat[i]['o3'],
                    tau=atmCat[i]['tau'],
                    alpha=atmCat[i]['alpha'],
                    zenith=zenith[i],
                    ctranslamstd=[atmCat[i]['cTrans'], atmCat[i]['lamStd']])
            else:
                # Run modtran
                modAtm = modGen(
                    pmb=atmCat[i]['pmb'],
                    pwv=atmCat[i]['pwv'],
                    o3=atmCat[i]['o3'],
                    tau=atmCat[i]['tau'],
                    alpha=atmCat[i]['alpha'],
                    zenith=zenith[i],
                    lambdaRange=lambdaRange,
                    lambdaStep=lambdaStep,
                    ctranslamstd=[atmCat[i]['cTrans'], atmCat[i]['lamStd']])
                atmVals = modAtm['COMBINED']

            # Now need to create something to persist...
            curve = TransmissionCurve.makeSpatiallyConstant(
                throughput=atmVals,
                wavelengths=atmLambda,
                throughputAtMin=atmVals[0],
                throughputAtMax=atmVals[-1])

            butler.put(curve,
                       "transmission_atmosphere_fgcm",
                       dataId={self.visitDataRefName: visit})

        self.log.info("Done outputting atmosphere transmissions")