Ejemplo n.º 1
0
    def __init__(self, algoDir):
        """Initialize the Algorithm class.

        Algorithm used to solve the transport of intensity equation to get
        normal/ annular Zernike polynomials.

        Parameters
        ----------
        algoDir : str
            Algorithm configuration directory.
        """

        self.algoDir = algoDir
        self.algoParamFile = ParamReader()

        self._inst = Instrument("")

        # Show the calculation message based on this value
        # 0 means no message will be showed
        self.debugLevel = 0

        # Image has the problem or not from the over-compensation
        self.caustic = False

        # Record the Zk coefficients in each outer-loop iteration
        # The actual total outer-loop iteration time is Num_of_outer_itr + 1
        self.converge = np.array([])

        # Current number of outer-loop iteration
        self.currentItr = 0

        # Record the coefficients of normal/ annular Zernike polynomials after
        # z4 in unit of nm
        self.zer4UpNm = np.array([])

        # Converged wavefront.
        self.wcomp = np.array([])

        # Calculated wavefront in previous outer-loop iteration.
        self.West = np.array([])

        # Converged Zk coefficients
        self.zcomp = np.array([])

        # Calculated Zk coefficients in previous outer-loop iteration
        self.zc = np.array([])

        # Padded mask for use at the offset planes
        self.pMask = None

        # Non-padded mask corresponding to aperture
        self.cMask = None

        # Change the dimension of mask for fft to use
        self.pMaskPad = None
        self.cMaskPad = None
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
    def __init__(self, instDir, algoDir):

        self.inst = Instrument(instDir)
        self.algo = Algorithm(algoDir)

        self.imgIntra = CompensableImage()
        self.imgExtra = CompensableImage()

        self.opticalModel = ""
        self.sizeInPix = 0
Ejemplo n.º 4
0
    def __init__(self, algoDir):

        self.algoDir = algoDir
        self.algoParamFile = ParamReader()

        self._inst = Instrument("")

        # Show the calculation message based on this value
        # 0 means no message will be showed
        self.debugLevel = 0

        # Image has the problem or not from the over-compensation
        self.caustic = False

        # Record the Zk coefficients in each outer-loop iteration
        # The actual total outer-loop iteration time is Num_of_outer_itr + 1
        self.converge = np.array([])

        # Current number of outer-loop iteration
        self.currentItr = 0

        # Record the coefficients of normal/ annular Zernike polynomials after
        # z4 in unit of nm
        self.zer4UpNm = np.array([])

        # Converged wavefront.
        self.wcomp = np.array([])

        # Calculated wavefront in previous outer-loop iteration.
        self.West = np.array([])

        # Converged Zk coefficients
        self.zcomp = np.array([])

        # Calculated Zk coefficients in previous outer-loop iteration
        self.zc = np.array([])

        # Padded mask for use at the offset planes
        self.mask_comp = None

        # Non-padded mask corresponding to aperture
        self.mask_pupil = None

        # Change the dimension of mask for fft to use
        self.mask_comp_pad = None
        self.mask_pupil_pad = None

        # Cache annular Zernike evaluations
        self._zk = None

        # Cache evaluations of X and Y annular Zernike gradients
        self._dzkdx = None
        self._dzkdy = None
Ejemplo n.º 5
0
    def testDataAuxTelZWO(self):

        inst = Instrument(self.instDir)
        inst.config(CamType.AuxTelZWO, 160, announcedDefocalDisInMm=0.5)

        self.assertEqual(inst.getObscuration(), 0.3525)
        self.assertEqual(inst.getFocalLength(), 21.6)
        self.assertEqual(inst.getApertureDiameter(), 1.2)
        self.assertEqual(inst.getDefocalDisOffset(), 0.0205)
        self.assertEqual(inst.getCamPixelSize(), 15.2e-6)
        self.assertAlmostEqual(inst.calcSizeOfDonutExpected(),
                               74.92690058,
                               places=7)
Ejemplo n.º 6
0
    def setUp(self):

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

        # Define the instrument folder
        instruFolder = os.path.join(self.modulePath, "configData", "cwfs",
                                    "instruData")

        # Define the algorithm folder
        algoFolderPath = os.path.join(self.modulePath, "configData", "cwfs",
                                      "algo")

        # Define the instrument name
        instruName = "lsst"

        # Define the algorithm being used: "exp" or "fft"
        useAlgorithm = "fft"

        # 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 = Image.Image()
        # self.I2 = Image.Image()

        self.I1 = CompensationImageDecorator()
        self.I2 = CompensationImageDecorator()

        self.I1.setImg(fieldXY, imageFile=intra_image_file, atype="intra")
        self.I2.setImg(fieldXY, imageFile=extra_image_file, atype="extra")

        self.inst = Instrument(instruFolder)
        self.inst.config(instruName, self.I1.sizeinPix)
Ejemplo n.º 7
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()
Ejemplo n.º 8
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)
Ejemplo n.º 9
0
    def __init__(self, instruFolderPath, algoFolderPath):
        """

        Initialize the wavefront estimator class.

        Arguments:
            instruFolderPath {[str]} -- Path to instrument directory.
            algoFolderPath {[str]} -- Path to algorithm directory.
        """

        self.algo = Algorithm(algoFolderPath)
        self.inst = Instrument(instruFolderPath)
        self.ImgIntra = CompensationImageDecorator()
        self.ImgExtra = CompensationImageDecorator()
        self.opticalModel = ""

        self.sizeInPix = 0
Ejemplo n.º 10
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])
Ejemplo n.º 11
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()
Ejemplo n.º 12
0
    def __init__(self, instDir, algoDir):
        """Initialize the wavefront estimator class.

        Parameters
        ----------
        instDir : str
            Path to instrument directory.
        algoDir : str
            Path to algorithm directory.
        """

        self.inst = Instrument(instDir)
        self.algo = Algorithm(algoDir)

        self.imgIntra = CompensableImage()
        self.imgExtra = CompensableImage()

        self.opticalModel = ""
        self.sizeInPix = 0
    def setUp(self):

        # Get the path of module
        modulePath = getModulePath()
        
        # Define the instrument folder
        instruFolder = os.path.join(modulePath, "configData", "cwfs",
                                    "instruData")

        # Define the instrument name
        instruName = "lsst"
        sensorSamples = 120

        self.inst = Instrument(instruFolder)
        self.inst.config(instruName, sensorSamples)

        # 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)

        # Define fieldXY: [1.185, 1.185] or [0, 0]
        # 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",
                                     "LSST_NE_SN25_z11_0.25_exp.txt")
        self.zcCol = np.loadtxt(zcAnsFilePath)
Ejemplo n.º 14
0
    def _runWEP(
        self,
        instDir,
        algoFolderPath,
        useAlgorithm,
        imageFolderPath,
        intra_image_name,
        extra_image_name,
        fieldXY,
        opticalModel,
        showFig=False,
    ):

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

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

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

        # Set the instrument
        inst = Instrument(instDir)
        inst.config(CamType.LsstCam,
                    I1.getImgSizeInPix(),
                    announcedDefocalDisInMm=1.0)

        # Define the algorithm to be used.
        algo = Algorithm(algoFolderPath)
        algo.config(useAlgorithm, inst, debugLevel=0)

        # Plot the original wavefront images
        if showFig:
            plotImage(I1.image, title="intra image")
            plotImage(I2.image, title="extra image")

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

        # Show the Zernikes Zn (n>=4)
        algo.outZer4Up(showPlot=False)

        # Plot the final conservated images and wavefront
        if showFig:
            plotImage(I1.image, title="Compensated intra image")
            plotImage(I2.image, title="Compensated extra image")

            # Plot the Wavefront
            plotImage(algo.wcomp, title="Final wavefront")
            plotImage(
                algo.wcomp,
                title="Final wavefront with pupil mask applied",
                mask=algo.pMask,
            )

        # Return the Zernikes Zn (n>=4)
        return algo.getZer4UpInNm()
Ejemplo n.º 15
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()
Ejemplo n.º 16
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()
Ejemplo n.º 17
0
 def testInstrument(self):
     inst = Instrument(self.instruFolder)
     inst.config(self.instruName, 120)
     self.assertEqual(inst.parameter["sensorSamples"], 120)
Ejemplo n.º 18
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()