Пример #1
0
    def _runWep(self, imgIntraName, imgExtraName, offset, model):

        # Cut the donut image from input files
        centroidFindType = CentroidFindType.Otsu
        imgIntra = Image(centroidFindType=centroidFindType)
        imgExtra = Image(centroidFindType=centroidFindType)

        imgIntraPath = os.path.join(self.testImgDir, imgIntraName)
        imgExtraPath = os.path.join(self.testImgDir, imgExtraName)

        imgIntra.setImg(imageFile=imgIntraPath)

        imgExtra.setImg(imageFile=imgExtraPath)

        xIntra, yIntra, _ = imgIntra.getCenterAndR()
        imgIntraArray = imgIntra.getImg()[int(yIntra) - offset:int(yIntra) +
                                          offset,
                                          int(xIntra) - offset:int(xIntra) +
                                          offset, ]

        xExtra, yExtra, _ = imgExtra.getCenterAndR()
        imgExtraArray = imgExtra.getImg()[int(yExtra) - offset:int(yExtra) +
                                          offset,
                                          int(xExtra) - offset:int(xExtra) +
                                          offset, ]

        # Set the images
        fieldXY = (0, 0)
        imgCompIntra = CompensableImage(centroidFindType=centroidFindType)
        imgCompIntra.setImg(fieldXY, DefocalType.Intra, image=imgIntraArray)

        imgCompExtra = CompensableImage(centroidFindType=centroidFindType)
        imgCompExtra.setImg(fieldXY, DefocalType.Extra, image=imgExtraArray)

        # Calculate the wavefront error

        # Set the instrument
        instDir = os.path.join(getConfigDir(), "cwfs", "instData")
        instAuxTel = Instrument(instDir)
        instAuxTel.config(CamType.AuxTel,
                          imgCompIntra.getImgSizeInPix(),
                          announcedDefocalDisInMm=0.8)

        # Set the algorithm
        algoFolderPath = os.path.join(getConfigDir(), "cwfs", "algo")
        algoAuxTel = Algorithm(algoFolderPath)
        algoAuxTel.config("exp", instAuxTel)
        algoAuxTel.runIt(imgCompIntra, imgCompExtra, model)

        return algoAuxTel.getZer4UpInNm()
Пример #2
0
    def _configWfEstimator(self, camType):
        """Configure the wavefront estimator.

        Returns
        -------
        WfEstimator
            Configured wavefront estimator.
        """

        configDir = getConfigDir()
        instDir = os.path.join(configDir, "cwfs", "instData")
        algoDir = os.path.join(configDir, "cwfs", "algo")
        wfsEsti = WfEstimator(instDir, algoDir)

        solver = self.settingFile.getSetting("poissonSolver")
        opticalModel = self.settingFile.getSetting("opticalModel")
        defocalDistInMm = self.settingFile.getSetting("defocalDistInMm")
        donutImgSizeInPixel = self.settingFile.getSetting("donutImgSizeInPixel")

        centroidFind = self.settingFile.getSetting("centroidFindAlgo")
        centroidFindType = getCentroidFindType(centroidFind)

        wfsEsti.config(
            solver=solver,
            camType=camType,
            opticalModel=opticalModel,
            defocalDisInMm=defocalDistInMm,
            sizeInPix=donutImgSizeInPixel,
            centroidFindType=centroidFindType,
        )

        return wfsEsti
Пример #3
0
    def __init__(self, settingFileName="default.yaml",
                 focalPlaneFileName="focalplanelayout.txt"):
        """Initialize the SourceProcessor class.

        Parameters
        ----------
        settingFileName : str, optional
            Setting file name. (the default is "default.yaml".)
        focalPlaneFileName : str, optional
            Focal plane file name used in the PhoSim instrument directory. (the
            default is "focalplanelayout.txt".)
        """

        self.sensorName = ""
        self.blendedImageDecorator = BlendedImageDecorator()

        configDir = getConfigDir()
        settingFilePath = os.path.join(configDir, settingFileName)
        self.settingFile = ParamReader(filePath=settingFilePath)

        self.sensorFocaPlaneInDeg = dict()
        self.sensorFocaPlaneInUm = dict()
        self.sensorDimList = dict()
        self.sensorEulerRot = dict()
        self._readFocalPlane(configDir, focalPlaneFileName)
Пример #4
0
    def __init__(self,
                 settingFileName="default.yaml",
                 focalPlaneFileName="focalplanelayout.txt"):
        """Initialize the SourceProcessor class.

        Parameters
        ----------
        settingFileName : str, optional
            Setting file name. (the default is "default.yaml".)
        focalPlaneFileName : str, optional
            Focal plane file name used in the PhoSim instrument directory. (the
            default is "focalplanelayout.txt".)
        """

        self.sensorName = ""

        configDir = getConfigDir()
        settingFilePath = os.path.join(configDir, settingFileName)
        self.settingFile = ParamReader(filePath=settingFilePath)

        self.sensorFocaPlaneInDeg = dict()
        self.sensorFocaPlaneInUm = dict()
        self.sensorDimList = dict()
        self.sensorEulerRot = dict()
        self._readFocalPlane(configDir, focalPlaneFileName)

        # Deblending donut algorithm to use
        deblendDonutType = self._getDeblendDonutTypeInSetting()
        self.deblend = DeblendDonutFactory.createDeblendDonut(deblendDonutType)
Пример #5
0
    def __init__(self, camType, bscDbType, settingFileName="default.yaml"):
        """Initialize the source selector class.

        Parameters
        ----------
        camType : enum 'CamType'
            Camera type.
        bscDbType : enum 'BscDbType'
            Bright star catalog (BSC) database type.
        settingFileName : str, optional
            Setting file name (the default is "default.yaml".)
        """

        self.camera = CamFactory.createCam(camType)
        self.db = DatabaseFactory.createDb(bscDbType)
        self.filter = Filter()

        self.maxDistance = 0.0
        self.maxNeighboringStar = 0

        settingFilePath = os.path.join(getConfigDir(), settingFileName)
        self.settingFile = ParamReader(filePath=settingFilePath)

        # Configurate the criteria of neighboring stars
        starRadiusInPixel = self.settingFile.getSetting("starRadiusInPixel")
        spacingCoefficient = self.settingFile.getSetting("spacingCoef")
        maxNeighboringStar = self.settingFile.getSetting("maxNumOfNbrStar")
        self.configNbrCriteria(starRadiusInPixel,
                               spacingCoefficient,
                               maxNeighboringStar=maxNeighboringStar)
Пример #6
0
    def __init__(self, camType, bscDbType, settingFileName="default.yaml"):
        """Initialize the source selector class.

        Parameters
        ----------
        camType : enum 'CamType'
            Camera type.
        bscDbType : enum 'BscDbType'
            Bright star catalog (BSC) database type.
        settingFileName : str, optional
            Setting file name (the default is "default.yaml".)
        """

        self.camera = CamFactory.createCam(camType)
        self.db = DatabaseFactory.createDb(bscDbType)
        self.filter = Filter()

        self.maxDistance = 0.0
        self.maxNeighboringStar = 0

        settingFilePath = os.path.join(getConfigDir(), settingFileName)
        self.settingFile = ParamReader(filePath=settingFilePath)

        # Configurate the criteria of neighboring stars
        starRadiusInPixel = self.settingFile.getSetting("starRadiusInPixel")
        spacingCoefficient = self.settingFile.getSetting("spacingCoef")
        maxNeighboringStar = self.settingFile.getSetting("maxNumOfNbrStar")
        self.configNbrCriteria(starRadiusInPixel, spacingCoefficient,
                               maxNeighboringStar=maxNeighboringStar)
Пример #7
0
    def setUp(self):

        self.instDir = os.path.join(getConfigDir(), "cwfs", "instData")

        self.inst = Instrument(self.instDir)
        self.dimOfDonutOnSensor = 120

        self.inst.config(CamType.LsstCam, self.dimOfDonutOnSensor,
                         announcedDefocalDisInMm=1.5)
Пример #8
0
    def __init__(self):
        """Initialize the filter class."""

        # Configuration file of the limit of star's magnitude
        pathMagLimitStar = os.path.join(getConfigDir(), "bsc",
                                        "magLimitStar.yaml")
        self._fileMagLimitStar = ParamReader(filePath=pathMagLimitStar)

        # Filter type in use
        self.filter = FilterType.U
Пример #9
0
    def setUp(self):

        self.instDir = os.path.join(getConfigDir(), "cwfs", "instData")

        self.inst = Instrument(self.instDir)
        self.dimOfDonutOnSensor = 120

        self.inst.config(CamType.LsstCam,
                         self.dimOfDonutOnSensor,
                         announcedDefocalDisInMm=1.5)
Пример #10
0
    def __init__(self, sensorNameToIdFileName="sensorNameToId.yaml"):
        """Construct a MapSensorNameAndId object.

        Parameters
        ----------
        sensorNameToIdFileName : str, optional
            Configuration file name to map sensor name and Id. (the default is
            "sensorNameToId.yaml".)
        """

        sensorNameToIdFilePath = os.path.join(getConfigDir(),
                                              sensorNameToIdFileName)
        self._sensorNameToIdFile = ParamReader(filePath=sensorNameToIdFilePath)
Пример #11
0
    def __init__(self, sensorNameToIdFileName="sensorNameToId.yaml"):
        """Construct a MapSensorNameAndId object.

        Parameters
        ----------
        sensorNameToIdFileName : str, optional
            Configuration file name to map sensor name and Id. (the default is
            "sensorNameToId.yaml".)
        """

        sensorNameToIdFilePath = os.path.join(getConfigDir(),
                                              sensorNameToIdFileName)
        self._sensorNameToIdFile = ParamReader(filePath=sensorNameToIdFilePath)
Пример #12
0
    def setUp(self):

        # Get the path of module
        self.modulePath = getModulePath()

        # Define the image folder and image names
        # Image data -- Don't know the final image format.
        # It is noted that image.readFile inuts is based on the txt file
        imageFolderPath = os.path.join(self.modulePath, "tests", "testData",
                                       "testImages", "LSST_NE_SN25")
        intra_image_name = "z11_0.25_intra.txt"
        extra_image_name = "z11_0.25_extra.txt"

        # Define fieldXY: [1.185, 1.185] or [0, 0]
        # This is the position of donut on the focal plane in degree
        fieldXY = [1.185, 1.185]

        # Define the optical model: "paraxial", "onAxis", "offAxis"
        self.opticalModel = "offAxis"

        # Image files Path
        intra_image_file = os.path.join(imageFolderPath, intra_image_name)
        extra_image_file = os.path.join(imageFolderPath, extra_image_name)

        # Theree is the difference between intra and extra images
        # I1: intra_focal images, I2: extra_focal Images
        self.I1 = CompensableImage()
        self.I2 = CompensableImage()

        self.I1.setImg(fieldXY, DefocalType.Intra, imageFile=intra_image_file)
        self.I2.setImg(fieldXY, DefocalType.Extra, imageFile=extra_image_file)

        # Set up the instrument
        cwfsConfigDir = os.path.join(getConfigDir(), "cwfs")

        instDir = os.path.join(cwfsConfigDir, "instData")
        self.inst = Instrument(instDir)

        self.inst.config(CamType.LsstCam,
                         self.I1.getImgSizeInPix(),
                         announcedDefocalDisInMm=1.0)

        # Set up the algorithm
        algoDir = os.path.join(cwfsConfigDir, "algo")

        self.algoExp = Algorithm(algoDir)
        self.algoExp.config("exp", self.inst)

        self.algoFft = Algorithm(algoDir)
        self.algoFft.config("fft", self.inst)
Пример #13
0
    def setUp(self):

        # Get the path of module
        self.modulePath = getModulePath()

        # Define the image folder and image names
        # Image data -- Don't know the final image format.
        # It is noted that image.readFile inuts is based on the txt file
        imageFolderPath = os.path.join(self.modulePath, "tests", "testData",
                                       "testImages", "LSST_NE_SN25")
        intra_image_name = "z11_0.25_intra.txt"
        extra_image_name = "z11_0.25_extra.txt"

        # Define fieldXY: [1.185, 1.185] or [0, 0]
        # This is the position of donut on the focal plane in degree
        fieldXY = [1.185, 1.185]

        # Define the optical model: "paraxial", "onAxis", "offAxis"
        self.opticalModel = "offAxis"

        # Image files Path
        intra_image_file = os.path.join(imageFolderPath, intra_image_name)
        extra_image_file = os.path.join(imageFolderPath, extra_image_name)

        # Theree is the difference between intra and extra images
        # I1: intra_focal images, I2: extra_focal Images
        self.I1 = CompensableImage()
        self.I2 = CompensableImage()

        self.I1.setImg(fieldXY, DefocalType.Intra, imageFile=intra_image_file)
        self.I2.setImg(fieldXY, DefocalType.Extra, imageFile=extra_image_file)

        # Set up the instrument
        cwfsConfigDir = os.path.join(getConfigDir(), "cwfs")

        instDir = os.path.join(cwfsConfigDir, "instData")
        self.inst = Instrument(instDir)

        self.inst.config(CamType.LsstCam, self.I1.getImgSizeInPix(),
                         announcedDefocalDisInMm=1.0)

        # Set up the algorithm
        algoDir = os.path.join(cwfsConfigDir, "algo")

        self.algoExp = Algorithm(algoDir)
        self.algoExp.config("exp", self.inst)

        self.algoFft = Algorithm(algoDir)
        self.algoFft.config("fft", self.inst)
Пример #14
0
    def __init__(self, astWcsSol, camType, isrDir,
                 settingFileName="default.yaml"):
        """Construct an WEP calculation object.

        Parameters
        ----------
        astWcsSol : AstWcsSol
            AST world coordinate system (WCS) solution.
        camType : enum 'CamType'
            Camera type.
        isrDir : str
            Instrument signature remocal (ISR) directory. This directory will
            have the input and output that the data butler needs.
        settingFileName : str, optional
            Setting file name. (the default is "default.yaml".)
        """

        super().__init__()

        # This attribute is just a stakeholder here since there is no detail of
        # AST WCS solution yet
        self.astWcsSol = astWcsSol

        # ISR directory that the data butler uses
        self.isrDir = isrDir

        # Number of processors for WEP to use
        # This is just a stakeholder at this moment
        self.numOfProc = 1

        # Boresight infomation
        self.raInDeg = 0.0
        self.decInDeg = 0.0

        # Sky rotation angle
        self.rotSkyPos = 0.0

        # Sky information file for the temporary use
        self.skyFile = ""

        # Default setting file
        settingFilePath = os.path.join(getConfigDir(), settingFileName)
        self.settingFile = ParamReader(filePath=settingFilePath)

        # Configure the WEP controller
        self.wepCntlr = self._configWepController(camType, settingFileName)
Пример #15
0
    def testMakeMasks(self):

        donutStamp = DonutStamp(
            self.testStamps[0],
            lsst.geom.SpherePoint(0.0, 0.0, lsst.geom.degrees),
            lsst.geom.Point2D(2047.5, 2001.5),
            DefocalType.Extra.value,
            "R22_S11",
            "LSSTCam",
        )

        # Set up instrument
        instDataPath = os.path.join(getConfigDir(), "cwfs", "instData")
        inst = Instrument(instDataPath)
        donutWidth = 126
        inst.config(CamType.LsstCam, donutWidth)

        # Check that masks are empty at start
        np.testing.assert_array_equal(np.empty(shape=(0, 0)),
                                      donutStamp.mask_comp.getArray())
        np.testing.assert_array_equal(np.empty(shape=(0, 0)),
                                      donutStamp.mask_pupil.getArray())

        # Check masks after creation
        donutStamp.makeMasks(inst, "offAxis", 0, 1)
        self.assertEqual(afwImage.MaskX, type(donutStamp.mask_comp))
        self.assertEqual(afwImage.MaskX, type(donutStamp.mask_pupil))
        self.assertDictEqual({
            "BKGRD": 0,
            "DONUT": 1
        }, donutStamp.mask_comp.getMaskPlaneDict())
        self.assertDictEqual({
            "BKGRD": 0,
            "DONUT": 1
        }, donutStamp.mask_pupil.getMaskPlaneDict())
        maskC = donutStamp.mask_comp.getArray()
        maskP = donutStamp.mask_pupil.getArray()
        # Donut should match
        self.assertEqual(np.shape(maskC), (126, 126))
        self.assertEqual(np.shape(maskP), (126, 126))
        # Make sure not just an empty array
        self.assertTrue(np.sum(maskC) > 0.0)
        self.assertTrue(np.sum(maskP) > 0.0)
        # Donut at center of focal plane should be symmetric
        np.testing.assert_array_equal(maskC[:63], maskC[-63:][::-1])
        np.testing.assert_array_equal(maskP[:63], maskP[-63:][::-1])
Пример #16
0
    def setUp(self):

        # Get the path of module
        modulePath = getModulePath()

        # Define the instrument folder
        instDir = os.path.join(getConfigDir(), "cwfs", "instData")

        # Define the instrument name
        dimOfDonutOnSensor = 120

        self.inst = Instrument(instDir)
        self.inst.config(CamType.LsstCam,
                         dimOfDonutOnSensor,
                         announcedDefocalDisInMm=1.0)

        # Define the image folder and image names
        # Image data -- Don't know the final image format.
        # It is noted that image.readFile inuts is based on the txt file
        imageFolderPath = os.path.join(modulePath, "tests", "testData",
                                       "testImages", "LSST_NE_SN25")
        intra_image_name = "z11_0.25_intra.txt"
        extra_image_name = "z11_0.25_extra.txt"
        self.imgFilePathIntra = os.path.join(imageFolderPath, intra_image_name)
        self.imgFilePathExtra = os.path.join(imageFolderPath, extra_image_name)

        # This is the position of donut on the focal plane in degree
        self.fieldXY = (1.185, 1.185)

        # Define the optical model: "paraxial", "onAxis", "offAxis"
        self.opticalModel = "offAxis"

        # Get the true Zk
        zcAnsFilePath = os.path.join(
            modulePath,
            "tests",
            "testData",
            "testImages",
            "validation",
            "simulation",
            "LSST_NE_SN25_z11_0.25_exp.txt",
        )
        self.zcCol = np.loadtxt(zcAnsFilePath)

        self.wfsImg = CompensableImage()
    def _configWfEstimator(self):

        cwfsConfigDir = os.path.join(getConfigDir(), "cwfs")
        instDir = os.path.join(cwfsConfigDir, "instData")
        algoDir = os.path.join(cwfsConfigDir, "algo")
        wfEsti = WfEstimator(instDir, algoDir)

        # Use the comcam to calculate the LSST central raft image
        # with 1.5 mm defocal distance
        wfEsti.config(
            solver="exp",
            camType=CamType.ComCam,
            opticalModel="offAxis",
            defocalDisInMm=1.5,
            sizeInPix=160,
            debugLevel=0,
        )

        return wfEsti
Пример #18
0
    def setUp(self):

        # Set the path of module and the setting directories
        modulePath = getModulePath()

        cwfsConfigDir = os.path.join(getConfigDir(), "cwfs")
        self.instFolder = os.path.join(cwfsConfigDir, "instData")
        self.algoFolderPath = os.path.join(cwfsConfigDir, "algo")
        self.imageFolderPath = os.path.join(modulePath, "tests", "testData",
                                            "testImages")

        # Set the tolerance
        self.tor = 3

        # Restart time
        self.startTime = time.time()
        self.difference = 0
        self.validationDir = os.path.join(modulePath, "tests", "testData",
                                          "testImages", "validation")
Пример #19
0
    def setUp(self):

        # Set the path of module and the setting directories
        modulePath = getModulePath()

        cwfsConfigDir = os.path.join(getConfigDir(), "cwfs")
        self.instFolder = os.path.join(cwfsConfigDir, "instData")
        self.algoFolderPath = os.path.join(cwfsConfigDir, "algo")
        self.imageFolderPath = os.path.join(modulePath, "tests", "testData",
                                            "testImages")

        # Set the tolerance
        self.tor = 4

        # Restart time
        self.startTime = time.time()
        self.difference = 0
        self.validationDir = os.path.join(modulePath, "tests", "testData",
                                          "testImages", "validation",
                                          "simulation")
Пример #20
0
    def __init__(self, astWcsSol, camType, isrDir, settingFileName="default.yaml"):
        """Construct an WEP calculation object.

        Parameters
        ----------
        astWcsSol : AstWcsSol
            AST world coordinate system (WCS) solution.
        camType : enum 'CamType'
            Camera type.
        isrDir : str
            Instrument signature remocal (ISR) directory. This directory will
            have the input and output that the data butler needs.
        settingFileName : str, optional
            Setting file name. (the default is "default.yaml".)
        """

        super().__init__()

        # This attribute is just a stakeholder here since there is no detail of
        # AST WCS solution yet
        self.astWcsSol = astWcsSol

        # ISR directory that the data butler uses
        self.isrDir = isrDir

        # Boresight infomation
        self.raInDeg = 0.0
        self.decInDeg = 0.0

        # Sky rotation angle
        self.rotSkyPos = 0.0

        # Sky information file for the temporary use
        self.skyFile = ""

        # Default setting file
        settingFilePath = os.path.join(getConfigDir(), settingFileName)
        self.settingFile = ParamReader(filePath=settingFilePath)

        # Configure the WEP controller
        self.wepCntlr = self._configWepController(camType, settingFileName)
Пример #21
0
    def setUp(self):

        cwfsConfigDir = os.path.join(getConfigDir(), "cwfs")
        instDir = os.path.join(cwfsConfigDir, "instData")
        algoDir = os.path.join(cwfsConfigDir, "algo")
        self.wfsEst = WfEstimator(instDir, algoDir)

        # Define the image folder and image names
        # It is noted that image.readFile inuts is based on the txt file.
        self.modulePath = getModulePath()
        imageFolderPath = os.path.join(self.modulePath, "tests", "testData",
                                       "testImages", "LSST_NE_SN25")
        intra_image_name = "z11_0.25_intra.txt"
        extra_image_name = "z11_0.25_extra.txt"

        # Path to image files
        self.intraImgFile = os.path.join(imageFolderPath, intra_image_name)
        self.extraImgFile = os.path.join(imageFolderPath, extra_image_name)

        # Field XY position
        self.fieldXY = (1.185, 1.185)
Пример #22
0
    def setUp(self):

        cwfsConfigDir = os.path.join(getConfigDir(), "cwfs")
        instDir = os.path.join(cwfsConfigDir, "instData")
        algoDir = os.path.join(cwfsConfigDir, "algo")
        self.wfsEst = WfEstimator(instDir, algoDir)

        # Define the image folder and image names
        # It is noted that image.readFile inuts is based on the txt file.
        self.modulePath = getModulePath()
        imageFolderPath = os.path.join(self.modulePath, "tests", "testData",
                                       "testImages", "LSST_NE_SN25")
        intra_image_name = "z11_0.25_intra.txt"
        extra_image_name = "z11_0.25_extra.txt"

        # Path to image files
        self.intraImgFile = os.path.join(imageFolderPath, intra_image_name)
        self.extraImgFile = os.path.join(imageFolderPath, extra_image_name)

        # Field XY position
        self.fieldXY = (1.185, 1.185)
Пример #23
0
    def _configWfEstimator(self, camType):
        """Configure the wavefront estimator.

        Returns
        -------
        WfEstimator
            Configured wavefront estimator.
        """

        configDir = getConfigDir()
        instDir = os.path.join(configDir, "cwfs", "instData")
        algoDir = os.path.join(configDir, "cwfs", "algo")
        wfsEsti = WfEstimator(instDir, algoDir)

        solver = self.settingFile.getSetting("poissonSolver")
        opticalModel = self.settingFile.getSetting("opticalModel")
        defocalDisInMm = self.settingFile.getSetting("dofocalDistInMm")
        donutImgSizeInPixel = self.settingFile.getSetting("donutImgSizeInPixel")
        wfsEsti.config(solver=solver, camType=camType,
                       opticalModel=opticalModel,
                       defocalDisInMm=defocalDisInMm,
                       sizeInPix=donutImgSizeInPixel)

        return wfsEsti
Пример #24
0
    def makeTemplate(self, sensorName, defocalType, imageSize):
        """
        Make the donut template image from phosim templates.
        The templates should have been created using
        code located in the `ts_phosim` repository under
        `bin.src/runCreatePhosimDonutTemplates.py`. The template
        files should then be stored here in `ts_wep`
        in `policy/cwfs/donutTemplateData/phosimTemplates`.
        See the `ts_wep` docs for more information or see
        `ts_phosim` docs for instructions on creating templates.

        Parameters
        ----------
        sensorName : str
            The camera detector for which we want to make a template. Should
            be in "Rxx_Sxx" format.
        defocalType : enum 'DefocalType'
            The defocal state of the sensor.
        imageSize : int
            Size of template in pixels. The template will be a square.

        Returns
        -------
        numpy.ndarray [int]
            The donut template as a binary image.
        """

        configDir = getConfigDir()
        phosimTemplateDir = os.path.join(configDir, "cwfs",
                                         "donutTemplateData",
                                         "phosimTemplates")

        if defocalType == DefocalType.Extra:
            templateFilename = os.path.join(
                phosimTemplateDir, "extra_template-%s.txt" % sensorName)
        else:
            templateFilename = os.path.join(
                phosimTemplateDir, "intra_template-%s.txt" % sensorName)
        templateArray = np.genfromtxt(templateFilename, dtype=int)

        # Make the template the desired square shape by trimming edges of
        # template
        # Phosim templates from file are already a square
        templateSize = np.shape(templateArray)[0]

        if templateSize >= imageSize:
            # Find the excess number of pixels in x and y direction
            templateTrim = templateSize - imageSize

            # Find the left and right edges by trimming half pixels from
            # left and right.
            # Do the same for the top and bottom.
            leftEdge = topEdge = int(templateTrim / 2)
            rightEdge = bottomEdge = int(templateSize -
                                         (templateTrim - leftEdge))

            templateFinal = templateArray[leftEdge:rightEdge,
                                          topEdge:bottomEdge]
        else:
            # If requesting a larger template than the phosim template
            # add padding of zeros to edges of template returned
            templatePad = imageSize - templateSize

            # Pad each side by equal amount of pixels
            padLeft = padTop = int(templatePad / 2)
            padRight = padBottom = int(imageSize - (templatePad - padLeft))

            templateFinal = np.zeros((imageSize, imageSize))
            templateFinal[padLeft:padRight, padTop:padBottom] = templateArray

        return templateFinal
Пример #25
0
    def estimateZernikes(self, donutStampsExtra, donutStampsIntra):
        """
        Take the donut postage stamps and estimate the Zernike coefficients.

        Parameters
        ----------
        donutStampsExtra: DonutStamps
            Extra-focal donut postage stamps.
        donutStampsIntra: DonutStamps
            Intra-focal donut postage stamps.

        Returns
        -------
        numpy.ndarray
            Zernike coefficients for the exposure. Will return one set of
            coefficients per set of stamps, not one set of coefficients
            per detector so this will be a 2-D numpy array with
            the number of rows equal to the number of donut stamps and
            the number of columns equal to the number of Zernike coefficients.
        """

        zerArray = []

        configDir = getConfigDir()
        instDir = os.path.join(configDir, "cwfs", "instData")
        algoDir = os.path.join(configDir, "cwfs", "algo")
        wfEsti = WfEstimator(instDir, algoDir)
        camType = getCamType(self.instName)
        defocalDisInMm = getDefocalDisInMm(self.instName)

        wfEsti.config(
            sizeInPix=self.donutStampSize,
            camType=camType,
            opticalModel=self.opticalModel,
            defocalDisInMm=defocalDisInMm,
        )

        for donutExtra, donutIntra in zip(donutStampsExtra, donutStampsIntra):

            # Transpose field XY because CompensableImages below are transposed
            # so this gets the correct mask orientation in Algorithm.py
            fieldXYExtra = donutExtra.calcFieldXY()[::-1]
            fieldXYIntra = donutIntra.calcFieldXY()[::-1]

            camera = donutExtra.getCamera()
            detectorExtra = camera.get(donutExtra.detector_name)
            detectorIntra = camera.get(donutIntra.detector_name)

            # Rotate any sensors that are not lined up with the focal plane.
            # Mostly just for the corner wavefront sensors. The negative sign
            # creates the correct rotation based upon closed loop tests
            # with R04 and R40 corner sensors.
            eulerZExtra = -detectorExtra.getOrientation().getYaw().asDegrees()
            eulerZIntra = -detectorIntra.getOrientation().getYaw().asDegrees()

            # NOTE: TS_WEP expects these images to be transposed
            # TODO: Look into this
            wfEsti.setImg(
                fieldXYExtra,
                DefocalType.Extra,
                image=rotate(donutExtra.stamp_im.getImage().getArray(),
                             eulerZExtra).T,
            )
            wfEsti.setImg(
                fieldXYIntra,
                DefocalType.Intra,
                image=rotate(donutIntra.stamp_im.getImage().getArray(),
                             eulerZIntra).T,
            )
            wfEsti.reset()
            zer4UpNm = wfEsti.calWfsErr()
            zer4UpMicrons = zer4UpNm * 1e-3

            zerArray.append(zer4UpMicrons)

        return np.array(zerArray)
Пример #26
0
    def makeTemplate(
        self,
        sensorName,
        defocalType,
        imageSize,
        camType=CamType.LsstCam,
        opticalModel="offAxis",
        pixelScale=0.2,
    ):
        """Make the donut template image.

        Parameters
        ----------
        sensorName : str
            The camera detector for which we want to make a template. Should
            be in "Rxx_Sxx" format.
        defocalType : enum 'DefocalType'
            The defocal state of the sensor.
        imageSize : int
            Size of template in pixels. The template will be a square.
        camType : enum 'CamType', optional
            Camera type. (Default is CamType.LsstCam)
        model : str, optional
            Optical model. It can be "paraxial", "onAxis", or "offAxis".
            (The default is "offAxis")
        pixelScale : float, optional
            The pixels to arcseconds conversion factor. (The default is 0.2)

        Returns
        -------
        numpy.ndarray [int]
            The donut template as a binary image.
        """

        configDir = getConfigDir()
        focalPlaneLayout = readPhoSimSettingData(configDir,
                                                 "focalplanelayout.txt",
                                                 "fieldCenter")

        pixelSizeInUm = float(focalPlaneLayout[sensorName][2])
        sizeXinPixel = int(focalPlaneLayout[sensorName][3])

        sensorXMicron, sensorYMicron = np.array(
            focalPlaneLayout[sensorName][:2], dtype=float)
        # Correction for wavefront sensors
        if sensorName in ("R44_S00_C0", "R00_S22_C1"):
            # Shift center to +x direction
            sensorXMicron = sensorXMicron + sizeXinPixel / 2 * pixelSizeInUm
        elif sensorName in ("R44_S00_C1", "R00_S22_C0"):
            # Shift center to -x direction
            sensorXMicron = sensorXMicron - sizeXinPixel / 2 * pixelSizeInUm
        elif sensorName in ("R04_S20_C1", "R40_S02_C0"):
            # Shift center to -y direction
            sensorYMicron = sensorYMicron - sizeXinPixel / 2 * pixelSizeInUm
        elif sensorName in ("R04_S20_C0", "R40_S02_C1"):
            # Shift center to +y direction
            sensorYMicron = sensorYMicron + sizeXinPixel / 2 * pixelSizeInUm

        # Load Instrument parameters
        instDir = os.path.join(configDir, "cwfs", "instData")
        inst = Instrument(instDir)
        inst.config(camType, imageSize)

        # Create image for mask
        img = CompensableImage()

        # Convert pixel locations to degrees
        sensorXPixel = float(sensorXMicron) / pixelSizeInUm
        sensorYPixel = float(sensorYMicron) / pixelSizeInUm

        # Multiply by pixelScale then divide by 3600 for arcsec -> deg conversion
        sensorXDeg = sensorXPixel * pixelScale / 3600
        sensorYDeg = sensorYPixel * pixelScale / 3600
        fieldXY = [sensorXDeg, sensorYDeg]

        # Define position of donut at center of current sensor in degrees
        boundaryT = 0
        maskScalingFactorLocal = 1
        img.setImg(fieldXY,
                   defocalType,
                   image=np.zeros((imageSize, imageSize)))
        img.makeMask(inst, opticalModel, boundaryT, maskScalingFactorLocal)

        return img.getNonPaddedMask()
Пример #27
0
    def calcWfErr(
        self,
        centroidFindType,
        fieldXY,
        camType,
        algoName,
        announcedDefocalDisInMm,
        opticalModel,
        imageIntra=None,
        imageExtra=None,
        imageFileIntra=None,
        imageFileExtra=None,
    ):
        """Calculate the wavefront error.

        Parameters
        ----------
        centroidFindType : enum 'CentroidFindType'
            Algorithm to find the centroid of donut.
        fieldXY : tuple or list
            Position of donut on the focal plane in degree (field x, field y).
        camType : enum 'CamType'
            Camera type.
        algoName : str
            Algorithm configuration file to solve the Poisson's equation in the
            transport of intensity equation (TIE). It can be "fft" or "exp"
            here.
        announcedDefocalDisInMm : float
            Announced defocal distance in mm. It is noted that the defocal
            distance offset used in calculation might be different from this
            value.
        opticalModel : str
            Optical model. It can be "paraxial", "onAxis", or "offAxis".
        imageIntra : numpy.ndarray, optional
            Array of intra-focal image. (the default is None.)
        imageExtra : numpy.ndarray, optional
            Array of extra-focal image. (the default is None.)
        imageFileIntra : str, optional
            Path of intra-focal image file. (the default is None.)
        imageFileExtra : str, optional
            Path of extra-focal image file. (the default is None.)

        Returns
        -------
        numpy.ndarray
            Zernike polynomials of z4-zn in nm.
        """

        # Set the defocal images
        imgIntra = CompensableImage(centroidFindType=centroidFindType)
        imgExtra = CompensableImage(centroidFindType=centroidFindType)

        imgIntra.setImg(
            fieldXY, DefocalType.Intra, image=imageIntra, imageFile=imageFileIntra
        )
        imgExtra.setImg(
            fieldXY, DefocalType.Extra, image=imageExtra, imageFile=imageFileExtra
        )

        # Set the instrument
        instDir = os.path.join(getConfigDir(), "cwfs", "instData")
        inst = Instrument(instDir)
        inst.config(
            camType,
            imgIntra.getImgSizeInPix(),
            announcedDefocalDisInMm=announcedDefocalDisInMm,
        )

        # Define the algorithm to be used.
        algoFolderPath = os.path.join(getConfigDir(), "cwfs", "algo")
        algo = Algorithm(algoFolderPath)
        algo.config(algoName, inst, debugLevel=0)

        # Run it
        algo.runIt(imgIntra, imgExtra, opticalModel, tol=1e-3)

        # Return the Zernikes Zn (n>=4)
        return algo.getZer4UpInNm()
Пример #28
0
    def testGetConfigDir(self):

        ansConfigDir = os.path.join(getModulePath(), "policy")
        self.assertEqual(getConfigDir(), ansConfigDir)
Пример #29
0
    def testGetConfigDir(self):

        ansConfigDir = os.path.join(getModulePath(), "policy")
        self.assertEqual(getConfigDir(), ansConfigDir)
Пример #30
0
    def makeTemplate(
        self,
        sensorName,
        defocalType,
        imageSize,
        camType=CamType.LsstCam,
        opticalModel="offAxis",
        pixelScale=0.2,
    ):
        """Make the donut template image.

        Parameters
        ----------
        sensorName : str
            The camera detector for which we want to make a template. Should
            be in "Rxx_Sxx" format.
        defocalType : enum 'DefocalType'
            The defocal state of the sensor.
        imageSize : int
            Size of template in pixels. The template will be a square.
        camType : enum 'CamType', optional
            Camera type. (The default is CamType.LsstCam)
        opticalModel : str, optional
            Optical model. It can be "paraxial", "onAxis", or "offAxis".
            (The default is "offAxis")
        pixelScale : float, optional
            The pixels to arcseconds conversion factor. (The default is 0.2)

        Returns
        -------
        numpy.ndarray [int]
            The donut template as a binary image.

        Raises
        ------
        ValueError
            Camera type is not supported.
        """

        configDir = getConfigDir()

        # Load Instrument parameters
        instDir = os.path.join(configDir, "cwfs", "instData")
        inst = Instrument(instDir)

        if camType in (CamType.LsstCam, CamType.LsstFamCam, CamType.ComCam):
            inst.config(camType, imageSize)
            focalPlaneLayout = readPhoSimSettingData(configDir,
                                                     "focalplanelayout.txt",
                                                     "fieldCenter")

            pixelSizeInUm = float(focalPlaneLayout[sensorName][2])

            sensorXMicron, sensorYMicron = np.array(
                focalPlaneLayout[sensorName][:2], dtype=float)

        elif camType == CamType.AuxTel:
            # AuxTel only works with onAxis sources
            if opticalModel != "onAxis":
                raise ValueError(
                    str(f"Optical Model {opticalModel} not supported with AuxTel. "
                        + "Must use 'onAxis'."))
            # Defocal distance for Latiss in mm
            # for LsstCam can use the default
            # hence only need to set here
            announcedDefocalDisInMm = getDefocalDisInMm("auxTel")
            inst.config(camType, imageSize, announcedDefocalDisInMm)
            # load the info for auxTel
            pixelSizeInMeters = inst.getCamPixelSize()  # pixel size in meters.
            pixelSizeInUm = pixelSizeInMeters * 1e6

            camera = obs_lsst.Latiss.getCamera()
            sensorName = list(
                camera.getNameIter())[0]  # only one detector in latiss
            detector = camera.get(sensorName)
            xp, yp = detector.getCenter(
                cameraGeom.FOCAL_PLANE)  # center of CCD in mm

            # multiply by 1000 to for mm --> microns conversion
            sensorXMicron = yp * 1000
            sensorYMicron = xp * 1000

        else:
            raise ValueError("Camera type (%s) is not supported." % camType)

        # Create image for mask
        img = CompensableImage()

        # Convert pixel locations to degrees
        sensorXPixel = float(sensorXMicron) / pixelSizeInUm
        sensorYPixel = float(sensorYMicron) / pixelSizeInUm

        # Multiply by pixelScale then divide by 3600 for arcsec->deg conversion
        sensorXDeg = sensorXPixel * pixelScale / 3600
        sensorYDeg = sensorYPixel * pixelScale / 3600
        fieldXY = [sensorXDeg, sensorYDeg]

        # Define position of donut at center of current sensor in degrees
        boundaryT = 0
        maskScalingFactorLocal = 1
        img.setImg(fieldXY,
                   defocalType,
                   image=np.zeros((imageSize, imageSize)))
        img.makeMask(inst, opticalModel, boundaryT, maskScalingFactorLocal)

        return img.getNonPaddedMask()