Esempio n. 1
0
def parseCcds(policy, ccdParams, ccdToUse=None):
    """
    Make DetectorConfigs for each CCD in the mosaic
    @param policy: Poicy object to parse
    @param ccdParams: CCD level parameters returned by makeCcdParams
    @param ccdToUse: Type of CCD to use to construct the config, use Policy value if None
    @return a dictionary containing a list of DetectorConfigs and a dictionary of AmpInfoTable objects
    keyed on CCD name
    """
    specialChipMap = {}
    eParams = makeEparams(policy)
    ampInfoDict = {}
    ccdInfoList = []
    rafts = policy.getArray('Raft')
    if len(rafts) > 1:
        raise ValueError("Expecting only one raft")
    for ccd in rafts[0].getArray('Ccd'):
        detConfig = DetectorConfig()
        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        ampCatalog = afwTable.AmpInfoCatalog(schema)
        if ccdToUse is not None:
            ccdParam = ccdParams[ccdToUse]
        else:
            ccdParam = ccdParams[ccd.get('ptype')]
        detConfig.name = ccd.get('name')
        detConfig.serial = str(ccd.get('serial'))
        detConfig.id = int(ccd.get('name')[-2:])
        offset = ccd.getArray('offset')
        if ccdParam['offsetUnit'] == 'pixels':
            offset[0] *= ccdParam['pixelSize']
            offset[1] *= ccdParam['pixelSize']
        detConfig.offset_x = offset[0]
        detConfig.offset_y = offset[1]
        if detConfig.name in specialChipMap:
            detConfig.detectorType = specialChipMap[detConfig.name]
        else:
            detConfig.detectorType = SCIENCE
        detConfig.pixelSize_x = ccdParam['pixelSize']
        detConfig.pixelSize_y = ccdParam['pixelSize']
        detConfig.refpos_x = (ccdParam['xsize'] - 1) / 2.
        detConfig.refpos_y = (ccdParam['ysize'] - 1) / 2.
        detConfig.bbox_x0 = 0
        detConfig.bbox_y0 = 0
        detConfig.bbox_x1 = ccdParam['xsize'] - 1
        detConfig.bbox_y1 = ccdParam['ysize'] - 1
        detConfig.rollDeg = 0.
        detConfig.pitchDeg = 0.
        detConfig.yawDeg = 90. * ccd.get('nQuarter') + ccd.getArray(
            'orientation')[2]
        for amp in ccdParam['ampArr']:
            eparms = None
            for ep in eParams[ccd.get('name')]:
                if amp['id'] == ep['index'][0]:
                    eparms = ep
            if eparms is None:
                raise ValueError("Could not find electronic params.")
            addAmp(ampCatalog, amp, eparms)
        ampInfoDict[ccd.get('name')] = ampCatalog
        ccdInfoList.append(detConfig)
    return {"ccdInfo": ccdInfoList, "ampInfo": ampInfoDict}
Esempio n. 2
0
    def buildDetector(self):
        """Take all the information and build a Detector object.
        The Detector object is necessary for doing things like assembly.

        Returns
        -------
        detector : `lsst.afw.cameraGeom.Detector`
             The detector.
        """
        if self.detector is not None:
            return self.detector

        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        ampInfo = afwTable.AmpInfoCatalog(schema)
        for ampMetadata in self.ampMetadataList:
            record = ampInfo.addNew()
            self.defaultAmpMap.setAttributes(record, ampMetadata, self.doRaise)
            record.setHasRawInfo(True)

        detConfig = afwCameraGeom.DetectorConfig()
        self.defaultDetectorMap.setAttributes(detConfig, self.detectorMetadata,
                                              self.doRaise)
        self.detector = afwCameraGeom.makeDetector(detConfig, ampInfo,
                                                   self.focalPlaneToField)
        return self.detector
def makeCcd(ccdId):
    schema = afwTable.AmpInfoTable.makeMinimalSchema()
    ampCatalog = afwTable.AmpInfoCatalog(schema)
    ccdName = ccdId + 1
    for i in range(1):
        addAmp(ampCatalog, i, readout[ccdId - 1][i], gain_all[ccdId - 1][i])
    return ampCatalog.writeFits("n%s_necam.fits" % ccdName)
Esempio n. 4
0
def makeCcd():
    schema = afwTable.AmpInfoTable.makeMinimalSchema()
    ampCatalog = afwTable.AmpInfoCatalog(schema)

    addAmp(ampCatalog)

    return ampCatalog.writeFits('g2_goto.fits')
Esempio n. 5
0
 def setUp(self):
     ampInfoShema = afwTable.AmpInfoTable.makeMinimalSchema()
     ampInfoCat = afwTable.AmpInfoCatalog(ampInfoShema)
     ampInfo = ampInfoCat.addNew()
     ampInfo.setRawBBox(
         afwGeom.Box2I(afwGeom.Point2I(-5, 7), afwGeom.Extent2I(53, 104)))
     ampInfo.setSuspectLevel(25000)
     self.ampInfo = ampInfo
     self.isrTask = ipIsr.IsrTask()
    def makeDetector(self,
                     bbox=None,
                     numAmps=None,
                     rowInds=None,
                     colIndOffsets=None,
                     detName="det_a",
                     detSerial="123",
                     linearityType="LookupTable"):
        """!Make a detector

        @param[in] bbox  bounding box for image
        @param[n] numAmps  x,y number of amplifiers (pair of int)
        @param[in] rowInds  index of lookup table for each amplifier (array of shape numAmps)
        @param[in] colIndOffsets  column index offset for each amplifier (array of shape numAmps)
        @param[in] detName  detector name (a str)
        @param[in] detSerial  detector serial numbe (a str)
        @param[in] linearityType  name of linearity type (a str)

        @return a detector (an lsst.afw.cameraGeom.Detector)
        """
        bbox = bbox if bbox is not None else self.bbox
        numAmps = numAmps if numAmps is not None else self.numAmps
        rowInds = rowInds if rowInds is not None else self.rowInds
        colIndOffsets = colIndOffsets if colIndOffsets is not None else self.colIndOffsets

        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        ampInfoCat = afwTable.AmpInfoCatalog(schema)
        boxArr = BoxGrid(box=bbox, numColRow=numAmps)
        for i in range(numAmps[0]):
            for j in range(numAmps[1]):
                ampInfo = ampInfoCat.addNew()
                ampInfo.setName("amp %d_%d" % (i + 1, j + 1))
                ampInfo.setBBox(boxArr[i, j])
                ampInfo.setLinearityType(linearityType)
                # setLinearityCoeffs is picky about getting a mixed int/float list.
                ampInfo.setLinearityCoeffs(
                    np.array([rowInds[i, j], colIndOffsets[i, j], 0, 0],
                             dtype=float))
        detId = 1
        orientation = cameraGeom.Orientation()
        pixelSize = afwGeom.Extent2D(1, 1)
        transMap = {}
        return cameraGeom.Detector(
            detName,
            detId,
            cameraGeom.SCIENCE,
            detSerial,
            bbox,
            ampInfoCat,
            orientation,
            pixelSize,
            transMap,
        )
Esempio n. 7
0
def createDetector(nAmpX, nAmpY, nPixX, nPixY, pre, hOscan, vOscan, ext,
                   isPerAmp):
    '''!Fill ampInfo tables
    \param[in] nAmpX -- Number of amps in the x direction
    \param[in] nAmpY -- Number of amps in the y direction
    \param[in] nPixX -- Number of pixels in the amp in the x direction
    \param[in] nPixY -- Number of pixels in the amp in the y direction
    \param[in] pre -- Number of prescan rows
    \param[in] hOscan -- Number of horizontal overscan columns
    \param[in] vOscan -- Number of vertical overscan rows
    \param[in] ext -- Number of pixels in the extended register
    \param[in] isPerAmp -- Are the raw amp data in separate images?
    \return an lsst.afw.cameraGeom.Detector object
    '''
    schema = afwTable.AmpInfoTable.makeMinimalSchema()
    ampCatalog = afwTable.AmpInfoCatalog(schema)
    flipy = True
    for iy in range(nAmpY):
        flipy = not flipy
        flipx = True
        for ix in range(nAmpX):
            flipx = not flipx
            record = ampCatalog.addNew()
            populateAmpBoxes(nPixX, nPixY, pre, hOscan, vOscan, ext, flipx,
                             flipy, ix, iy, isPerAmp, record)
            record.setGain(ix + iy * nAmpX + 1.)

    detConfig = DetectorConfig()
    detConfig.name = 'TestDetector'
    detConfig.id = 0
    detConfig.bbox_x0 = 0
    detConfig.bbox_y0 = 0
    detConfig.bbox_x1 = nAmpX * nPixX - 1
    detConfig.bbox_y1 = nAmpY * nPixY - 1
    detConfig.detectorType = 0  #Science type
    detConfig.serial = 'THX1138'
    detConfig.offset_x = 0.
    detConfig.offset_y = 0.
    detConfig.refpos_x = nAmpX * nPixX * 0.5 - 0.5
    detConfig.refpos_y = nAmpY * nPixY * 0.5 - 0.5
    detConfig.yawDeg = 0.
    detConfig.pitchDeg = 0.
    detConfig.rollDeg = 0.
    detConfig.pixelSize_x = 10. / 1000.  #in mm
    detConfig.pixelSize_y = 10. / 1000.  #in mm
    detConfig.transposeDetector = False
    detConfig.transformDict.nativeSys = PIXELS.getSysName()

    fpTransform = afwGeom.xyTransformRegistry['identity']()
    plateScale = 1.
    return makeDetector(detConfig, ampCatalog, fpTransform, plateScale)
Esempio n. 8
0
    def makeDetector(self,
                     bbox=None,
                     numAmps=None,
                     sqCoeffs=None,
                     linearityType="Squared"):
        """!Make a detector

        @param[in] bbox  bounding box for image
        @param[n] numAmps  x,y number of amplifiers (pair of int)
        @param[in] sqCoeffs  square coefficient for each amplifier (2D array of float)
        @param[in] detName  detector name (a str)
        @param[in] detID  detector ID (an int)
        @param[in] detSerial  detector serial numbe (a str)
        @param[in] linearityType  name of linearity type (a str)

        @return a detector (an lsst.afw.cameraGeom.Detector)
        """
        bbox = bbox if bbox is not None else self.bbox
        numAmps = numAmps if numAmps is not None else self.numAmps
        sqCoeffs = sqCoeffs if sqCoeffs is not None else self.sqCoeffs
        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        ampInfoCat = afwTable.AmpInfoCatalog(schema)
        boxArr = BoxGrid(box=bbox, numColRow=numAmps)
        for i in range(numAmps[0]):
            for j in range(numAmps[1]):
                ampInfo = ampInfoCat.addNew()
                ampInfo.setName("amp %d_%d" % (i + 1, j + 1))
                ampInfo.setBBox(boxArr[i, j])
                ampInfo.setLinearityType(linearityType)
                ampInfo.setLinearityCoeffs([sqCoeffs[i, j]])
        detName = "det_a"
        detId = 1
        detSerial = "123"
        orientation = cameraGeom.Orientation()
        pixelSize = afwGeom.Extent2D(1, 1)
        transMap = {}
        return cameraGeom.Detector(
            detName,
            detId,
            cameraGeom.SCIENCE,
            detSerial,
            bbox,
            ampInfoCat,
            orientation,
            pixelSize,
            transMap,
        )
Esempio n. 9
0
def makeCcd(ccdId):
    '''
        Make a CCD out of a set of amps
        Remove the for loop if you only have one amp
        per CCD.

        note that the name used to be set to 'ccd0_superbit.fits' in
        ampCatalog.writeFits('ccd%s_superbit.fits' %ccdId) (ccdId=0)
        That causes problems since 'ccd0_superbit' never 
        appears in header of calib/data files, so not useful as identifier 

        Changed writeFits to 'superbitccd', which \does\ appear in header
        '''
    schema = afwTable.AmpInfoTable.makeMinimalSchema()
    ampCatalog = afwTable.AmpInfoCatalog(schema)
    for i in range(1):
        addAmp(ampCatalog,i,readout[ccdId][i],gain_all[ccdId][i])

    return ampCatalog.writeFits('superbitccd.fits')
Esempio n. 10
0
def makeCcd(ccdName, ccdId, offsetPoint):
    """make the information necessary to build a set detector
    @param ccdName: string name of the ccd
    @param ccdId: Integer id of the ccd
    @param offsetPoint: Point2D position of the center of the ccd in mm
    @return a dict of a DetectorConfig and an AmpInfoCatalog
    """
    obsSdssDir = lsst.utils.getPackageDir('obs_sdss')
    opDir = os.path.join(obsSdssDir, "etc")
    sc = SdssCameraState(opDir, "opConfig-50000.par", "opECalib-50000.par")
    eparams = sc.getEParams(ccdName)
    width = 1024 * 2
    height = 1361

    pixelSize = 24e-3  # pixel size in mm
    schema = afwTable.AmpInfoTable.makeMinimalSchema()
    ampCatalog = afwTable.AmpInfoCatalog(schema)
    for i in range(2):
        addAmp(ampCatalog, i, eparams[i][1])
    detConfig = DetectorConfig()
    detConfig.name = ccdName
    detConfig.id = ccdId
    detConfig.bbox_x0 = 0
    detConfig.bbox_y0 = 0
    detConfig.bbox_x1 = width - 1
    detConfig.bbox_y1 = height - 1
    detConfig.serial = ccdName
    detConfig.detectorType = SCIENCE
    detConfig.offset_x = offsetPoint.getX()
    detConfig.offset_y = offsetPoint.getY()
    detConfig.refpos_x = (width - 1) / 2.
    detConfig.refpos_y = (height - 1) / 2.
    detConfig.yawDeg = 0.
    detConfig.pitchDeg = 0.
    detConfig.rollDeg = 0.
    detConfig.pixelSize_x = pixelSize
    detConfig.pixelSize_y = pixelSize
    detConfig.transposeDetector = False
    detConfig.transformDict.nativeSys = PIXELS.getSysName()
    return {'ccdConfig': detConfig, 'ampInfo': ampCatalog}
def makeAmpTables(segmentsFile):
    """
    Read the segments file from a PhoSim release and produce the appropriate AmpInfo
    @param segmentsFile -- String indicating where the file is located
    """
    returnDict = {}
    readoutMap = {'LL': afwTable.LL, 'LR': afwTable.LR, 'UR': afwTable.UR, 'UL': afwTable.UL}
    detectorName = []  # set to a value that is an invalid dict key, to catch bugs
    with open(segmentsFile) as fh:
        fh.readline()
        for l in fh:
            els = l.rstrip().split()
            detectorName = els[1]
            # skip focus and guiding for now:
            if detectorName[0] in ('F', 'G'):
                continue
            if detectorName not in returnDict:
                schema = afwTable.AmpInfoTable.makeMinimalSchema()
                returnDict[detectorName] = afwTable.AmpInfoCatalog(schema)
            record = returnDict[detectorName].addNew()
            name = els[2]
            gain = float(els[7])
            saturation = int(els[8])
            readnoise = float(els[9])
            xoff = int(els[5])
            yoff = int(els[6])
            ndatax = int(els[3])
            ndatay = int(els[4])

            flipx = False
            flipy = False

            if detectorName.startswith("S") and name == "A":
                readCorner = readoutMap['UR']
            elif detectorName.startswith("S") and name == "B":
                readCorner = readoutMap['UL']
            elif detectorName.startswith("N") and name == "A":
                readCorner = readoutMap['LL']
            elif detectorName.startswith("N") and name == "B":
                readCorner = readoutMap['LR']
            else:
                raise RuntimeError("Did not recognize detector name or amp name")

            prescan = 6
            hoverscan = 50
            voverscan = 50
            rawBBox = afwGeom.Box2I(afwGeom.Point2I(xoff, yoff),
                                    afwGeom.Extent2I(ndatax + prescan + hoverscan, ndatay + voverscan))
            # Note: I'm not particularry happy with how the data origin is derived (it neglects [xy]off),
            # but I don't see a better way.
            if readCorner is afwTable.LL:
                originRawData = afwGeom.Point2I(xoff + prescan + hoverscan, yoff)
                originData = afwGeom.Point2I(0, 0)
                originHOverscan = afwGeom.Point2I(xoff + prescan, yoff)
                originVOverscan = afwGeom.Point2I(xoff + prescan + hoverscan, yoff + ndatay)
            elif readCorner is afwTable.LR:
                originRawData = afwGeom.Point2I(xoff, yoff)
                originData = afwGeom.Point2I(ndatax, 0)
                originHOverscan = afwGeom.Point2I(xoff + ndatax, yoff)
                originVOverscan = afwGeom.Point2I(xoff, yoff + ndatay)
            elif readCorner is afwTable.UL:
                originRawData = afwGeom.Point2I(xoff + prescan + hoverscan, yoff + voverscan)
                originData = afwGeom.Point2I(0, 0)
                originHOverscan = afwGeom.Point2I(xoff + prescan, yoff + voverscan)
                originVOverscan = afwGeom.Point2I(xoff + prescan + hoverscan, yoff)
            elif readCorner is afwTable.UR:
                originRawData = afwGeom.Point2I(xoff, yoff + voverscan)
                originData = afwGeom.Point2I(ndatax, 0)
                originHOverscan = afwGeom.Point2I(xoff + ndatax, yoff + voverscan)
                originVOverscan = afwGeom.Point2I(xoff, yoff)
            else:
                raise RuntimeError("Expected readout corner to be LL, LR, UL, or UR")

            rawDataBBox = afwGeom.Box2I(originRawData, afwGeom.Extent2I(ndatax, ndatay))
            dataBBox = afwGeom.Box2I(originData, afwGeom.Extent2I(ndatax, ndatay))
            rawHorizontalOverscanBBox = afwGeom.Box2I(originHOverscan, afwGeom.Extent2I(hoverscan, ndatay))
            rawVerticalOverscanBBox = afwGeom.Box2I(originVOverscan, afwGeom.Extent2I(ndatax, voverscan))

            print("\nDetector=%s; Amp=%s" % (detectorName, name))
            print(rawHorizontalOverscanBBox)
            print(rawVerticalOverscanBBox)
            print(dataBBox)
            print(rawBBox)
            # Set the elements of the record for this amp
            record.setBBox(dataBBox)  # This is the box for the amp in the assembled frame
            record.setName(name)
            record.setReadoutCorner(readCorner)
            record.setGain(gain)
            record.setSaturation(saturation)
            record.setSuspectLevel(float("nan"))
            record.setReadNoise(readnoise)
            ampIndex = dict(A=0, B=1)[name]
            record.setLinearityCoeffs([ampIndex, 0, 0, 0])
            record.setLinearityType(LinearizeLookupTable.LinearityType)
            print("Linearity type=%r; coeffs=%s" % (record.getLinearityType(), record.getLinearityCoeffs()))
            record.setHasRawInfo(True)
            record.setRawFlipX(flipx)
            record.setRawFlipY(flipy)
            record.setRawBBox(rawBBox)
            # I believe that xy offset is not needed if the raw data are pre-assembled
            record.setRawXYOffset(afwGeom.Extent2I(0, 0))
            """
            if readCorner is afwTable.LL:
                record.setRawXYOffset(afwGeom.Extent2I(xoff + prescan + hoverscan, yoff))
            elif readCorner is afwTable.LR:
                record.setRawXYOffset(afwGeom.Extent2I(xoff, yoff))
            elif readCorner is afwTable.UL:
                record.setRawXYOffset(afwGeom.Extent2I(xoff + prescan + hoverscan, yoff + voverscan))
            elif readCorner is afwTable.UR:
                record.setRawXYOffset(afwGeom.Extent2I(xoff, yoff + voverscan))
            """
            record.setRawDataBBox(rawDataBBox)
            record.setRawHorizontalOverscanBBox(rawHorizontalOverscanBBox)
            record.setRawVerticalOverscanBBox(rawVerticalOverscanBBox)
            # I think of prescan as being along the bottom of the raw data.  I actually
            # don't know how you would do a prescan in the serial direction.
            record.setRawPrescanBBox(afwGeom.Box2I())
    return returnDict
Esempio n. 12
0
 def setUp(self):
     self.schema = afwTable.AmpInfoTable.makeMinimalSchema()
     self.catalog = afwTable.AmpInfoCatalog(self.schema)
Esempio n. 13
0
def makeCcd(utId):
    schema = afwTable.AmpInfoTable.makeMinimalSchema()
    ampCatalog = afwTable.AmpInfoCatalog(schema)
    for i in range(2):
        addAmp(ampCatalog, i, readout[utId][i], gain_all[utId][i])
    return ampCatalog.writeFits('g%s_goto.fits' % utId[-1])
Esempio n. 14
0
    def __init__(self,
        name="detector 1",
        id=1,
        detType=SCIENCE,
        serial="xkcd722",
        bbox=None,    # do not use mutable objects as defaults
        numAmps=3,
        pixelSize=(0.02, 0.02),
        ampExtent=(5, 6),
        orientation=Orientation(),
        plateScale=20.0,
        radialDistortion=0.925,
        modFunc=None,
    ):
        """!Construct a DetectorWrapper

        @param[in] name  detector name
        @param[in] id  detector ID (int)
        @param[in] detType  detector type (an lsst.afw.cameraGeom.DetectorType)
        @param[in] serial  serial "number" (a string)
        @param[in] bbox  bounding box; defaults to (0, 0), (1024x1024) (an lsst.afw.geom.Box2I)
        @param[in] numAmps  number of amplifiers (int)
        @param[in] pixelSize  pixel size (mm) (an lsst.afw.geom.Point2D)
        @param[in] ampExtent  dimensions of amplifier image bbox (an lsst.afw.geom.Extent2I)
        @param[in] orientation  orientation of CCC in focal plane (lsst.afw.cameraGeom.Orientation)
        @param[in] plateScale  plate scale in arcsec/mm; 20.0 is for LSST
        @param[in] radialDistortion  radial distortion, in mm/rad^2
            (the r^3 coefficient of the radial distortion polynomial
            that converts PUPIL in radians to FOCAL_PLANE in mm);
            0.925 is the value Dave Monet measured for lsstSim data
        @param[in] modFunc  a function that can modify attributes just before constructing the detector;
            modFunc receives one argument: a DetectorWrapper with all attributes except detector set.
        """
        # note that (0., 0.) for the reference position is the center of the first pixel
        self.name = name
        self.id = int(id)
        self.type = detType
        self.serial = serial
        if bbox is None:
            bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1024, 1048))
        self.bbox = bbox
        self.pixelSize = afwGeom.Extent2D(*pixelSize)
        self.ampExtent = afwGeom.Extent2I(*ampExtent)
        self.plateScale = float(plateScale)
        self.radialDistortion = float(radialDistortion)
        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        self.ampInfo = afwTable.AmpInfoCatalog(schema)
        for i in range(numAmps):
            record = self.ampInfo.addNew()
            ampName = "amp %d" % (i + 1,)
            record.setName(ampName)
            record.setBBox(afwGeom.Box2I(afwGeom.Point2I(-1, 1), self.ampExtent))
            record.setGain(1.71234e3)
            record.setReadNoise(0.521237e2)
            record.setReadoutCorner(afwTable.LL)
            record.setHasRawInfo(False)
        self.orientation = orientation

        # compute TAN_PIXELS transform
        pScaleRad = afwGeom.arcsecToRad(self.plateScale)
        radialDistortCoeffs = [0.0, 1.0/pScaleRad, 0.0, self.radialDistortion/pScaleRad]
        focalPlaneToPupil = afwGeom.RadialXYTransform(radialDistortCoeffs)
        pixelToTanPixel = makePixelToTanPixel(
            bbox = self.bbox,
            orientation = self.orientation,
            focalPlaneToPupil = focalPlaneToPupil,
            pixelSizeMm = self.pixelSize,
            plateScale = self.plateScale,
        )

        self.transMap = {
            FOCAL_PLANE: self.orientation.makePixelFpTransform(self.pixelSize),
            CameraSys(TAN_PIXELS, self.name): pixelToTanPixel,
            CameraSys(ACTUAL_PIXELS, self.name): afwGeom.RadialXYTransform([0, 0.95, 0.01]),
        }
        if modFunc:
            modFunc(self)
        self.detector = Detector(
            self.name,
            self.id,
            self.type,
            self.serial,
            self.bbox,
            self.ampInfo,
            self.orientation,
            self.pixelSize,
            self.transMap,
        )
def makeAmpTables(segmentsFile, gainFile):
    """
    Read the segments file from a PhoSim release and produce the appropriate AmpInfo
    @param segmentsFile -- String indicating where the file is located
    """
    gainDict = {}
    """
    with open(gainFile) as fh:
        for l in fh:
            els = l.rstrip().split()
            gainDict[els[0]] = {'gain':float(els[1]), 'saturation':int(els[2])}
    """
    returnDict = {}
    #TODO currently there is no linearity provided, but we should identify
    #how to get this information.
    linearityCoeffs = (0.,1.,0.,0.)
    linearityType = "Polynomial"
    readoutMap = {'LL':afwTable.LL, 'LR':afwTable.LR, 'UR':afwTable.UR, 'UL':afwTable.UL}
    ampCatalog = None
    detectorName = [] # set to a value that is an invalid dict key, to catch bugs
    correctY0 = False
    with open(segmentsFile) as fh:
        for l in fh:
            if l.startswith("#"):
                continue

            els = l.rstrip().split()
            if len(els) == 4:
                if ampCatalog is not None:
                    returnDict[detectorName] = ampCatalog
                detectorName = expandDetectorName(els[0])
                numy = int(els[2])
                schema = afwTable.AmpInfoTable.makeMinimalSchema()
                ampCatalog = afwTable.AmpInfoCatalog(schema)
                if len(els[0].split('_')) == 3:   #wavefront sensor
                    correctY0 = True
                else:
                    correctY0 = False
                continue
            record = ampCatalog.addNew()
            name = els[0].split("_")[-1]
            name = '%s,%s'%(name[1], name[2])
            #Because of the camera coordinate system, we choose an
            #image coordinate system that requires a -90 rotation to get
            #the correct pixel positions from the
            #phosim segments file
            y0 = numy - 1 - int(els[2])
            y1 = numy - 1 - int(els[1])
            #Another quirk of the phosim file is that one of the wavefront sensor
            #chips has an offset of 2000 pix in y.  It's always the 'C1' chip.
            if correctY0:
                if y0 > 0:
                    y1 -= y0
                    y0 = 0
            x0 = int(els[3])
            x1 = int(els[4])
            try:
                saturation = gainDict[els[0]]['saturation']
                gain = gainDict[els[0]]['gain']
            except KeyError:
                # Set default if no gain exists
                saturation = 65535
                gain = float(els[7])
            readnoise = float(els[11])
            bbox = afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Point2I(x1, y1))

            if int(els[5]) == -1:
                flipx = False
            else:
                flipx = True
            if int(els[6]) == 1:
                flipy = False
            else:
                flipy = True

            #Since the amps are stored in amp coordinates, the readout is the same
            #for all amps
            readCorner = readoutMap['LL']

            ndatax = x1 - x0 + 1
            ndatay = y1 - y0 + 1
            #Because in versions v3.3.2 and earlier there was no overscan, we use the extended register as the overscan region
            prescan = 1
            hoverscan = 0
            extended = 4
            voverscan = 0
            rawBBox = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(extended+ndatax+hoverscan, prescan+ndatay+voverscan))
            rawDataBBox = afwGeom.Box2I(afwGeom.Point2I(extended, prescan), afwGeom.Extent2I(ndatax, ndatay))
            rawHorizontalOverscanBBox = afwGeom.Box2I(afwGeom.Point2I(0, prescan), afwGeom.Extent2I(extended, ndatay))
            rawVerticalOverscanBBox = afwGeom.Box2I(afwGeom.Point2I(extended, prescan+ndatay), afwGeom.Extent2I(ndatax, voverscan))
            rawPrescanBBox = afwGeom.Box2I(afwGeom.Point2I(extended, 0), afwGeom.Extent2I(ndatax, prescan))

            extraRawX = extended + hoverscan
            extraRawY = prescan + voverscan
            rawx0 = x0 + extraRawX*(x0//ndatax)
            rawy0 = y0 + extraRawY*(y0//ndatay)
            #Set the elements of the record for this amp
            record.setBBox(bbox)
            record.setName(name)
            record.setReadoutCorner(readCorner)
            record.setGain(gain)
            record.setSaturation(saturation)
            record.setReadNoise(readnoise)
            record.setLinearityCoeffs(linearityCoeffs)
            record.setLinearityType(linearityType)
            record.setHasRawInfo(True)
            record.setRawFlipX(flipx)
            record.setRawFlipY(flipy)
            record.setRawBBox(rawBBox)
            record.setRawXYOffset(afwGeom.Extent2I(rawx0, rawy0))
            record.setRawDataBBox(rawDataBBox)
            record.setRawHorizontalOverscanBBox(rawHorizontalOverscanBBox)
            record.setRawVerticalOverscanBBox(rawVerticalOverscanBBox)
            record.setRawPrescanBBox(rawPrescanBBox)
    returnDict[detectorName] = ampCatalog
    return returnDict
Esempio n. 16
0
    def __init__(
        self,
        name="detector 1",
        id=1,
        detType=SCIENCE,
        serial="xkcd722",
        bbox=None,  # do not use mutable objects as defaults
        numAmps=3,
        pixelSize=(0.02, 0.02),
        ampExtent=(5, 6),
        orientation=Orientation(),
        plateScale=20.0,
        radialDistortion=0.925,
        crosstalk=None,
        modFunc=None,
        physicalType="CCD",
    ):
        # note that (0., 0.) for the reference position is the center of the
        # first pixel
        self.name = name
        self.id = int(id)
        self.type = detType
        self.serial = serial
        if bbox is None:
            bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                                   lsst.geom.Extent2I(1024, 1048))
        self.bbox = bbox
        self.pixelSize = lsst.geom.Extent2D(*pixelSize)
        self.ampExtent = lsst.geom.Extent2I(*ampExtent)
        self.plateScale = float(plateScale)
        self.radialDistortion = float(radialDistortion)
        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        self.ampInfo = afwTable.AmpInfoCatalog(schema)
        for i in range(numAmps):
            record = self.ampInfo.addNew()
            ampName = "amp %d" % (i + 1, )
            record.setName(ampName)
            record.setBBox(
                lsst.geom.Box2I(lsst.geom.Point2I(-1, 1), self.ampExtent))
            record.setGain(1.71234e3)
            record.setReadNoise(0.521237e2)
            record.setReadoutCorner(afwTable.LL)
            record.setHasRawInfo(False)
        self.orientation = orientation

        # compute TAN_PIXELS transform
        pScaleRad = lsst.geom.arcsecToRad(self.plateScale)
        radialDistortCoeffs = [
            0.0, 1.0 / pScaleRad, 0.0, self.radialDistortion / pScaleRad
        ]
        focalPlaneToField = afwGeom.makeRadialTransform(radialDistortCoeffs)
        pixelToTanPixel = makePixelToTanPixel(
            bbox=self.bbox,
            orientation=self.orientation,
            focalPlaneToField=focalPlaneToField,
            pixelSizeMm=self.pixelSize,
        )

        self.transMap = {
            FOCAL_PLANE:
            self.orientation.makePixelFpTransform(self.pixelSize),
            CameraSys(TAN_PIXELS, self.name):
            pixelToTanPixel,
            CameraSys(ACTUAL_PIXELS, self.name):
            afwGeom.makeRadialTransform([0, 0.95, 0.01]),
        }
        if crosstalk is None:
            crosstalk = [[0.0 for _ in range(numAmps)] for _ in range(numAmps)]
        self.crosstalk = crosstalk
        self.physicalType = physicalType
        if modFunc:
            modFunc(self)
        self.detector = Detector(
            self.name,
            self.id,
            self.type,
            self.serial,
            self.bbox,
            self.ampInfo,
            self.orientation,
            self.pixelSize,
            self.transMap,
            np.array(self.crosstalk, dtype=np.float32),
            self.physicalType,
        )
Esempio n. 17
0
    def makeAmpCatalogs(self, ampFile, isLsstLike=False):
        """Construct a dict of AmpInfoCatalog, one per detector.

        Parameters
        ----------
        ampFile : `str`
            Path to amplifier data file.
        isLsstLike : `bool`
            If True then there is one raw image per amplifier;
            if False then there is one raw image per detector.
        """
        readoutMap = {
            'LL': afwTable.ReadoutCorner.LL,
            'LR': afwTable.ReadoutCorner.LR,
            'UR': afwTable.ReadoutCorner.UR,
            'UL': afwTable.ReadoutCorner.UL,
        }
        amps = []
        with open(ampFile) as fh:
            names = fh.readline().rstrip().lstrip("#").split("|")
            for l in fh:
                els = l.rstrip().split("|")
                ampProps = dict([(name, el) for name, el in zip(names, els)])
                amps.append(ampProps)
        ampTablesDict = {}
        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        linThreshKey = schema.addField('linearityThreshold', type=np.float64)
        linMaxKey = schema.addField('linearityMaximum', type=np.float64)
        linUnitsKey = schema.addField('linearityUnits', type=str, size=9)
        self.ampInfoDict = {}
        for amp in amps:
            if amp['ccd_name'] in ampTablesDict:
                ampCatalog = ampTablesDict[amp['ccd_name']]
                self.ampInfoDict[amp['ccd_name']]['namps'] += 1
            else:
                ampCatalog = afwTable.AmpInfoCatalog(schema)
                ampTablesDict[amp['ccd_name']] = ampCatalog
                self.ampInfoDict[amp['ccd_name']] = {'namps': 1, 'linInfo': {}}
            record = ampCatalog.addNew()
            bbox = lsst.geom.Box2I(
                lsst.geom.Point2I(int(amp['trimmed_xmin']),
                                  int(amp['trimmed_ymin'])),
                lsst.geom.Point2I(int(amp['trimmed_xmax']),
                                  int(amp['trimmed_ymax'])))
            rawBbox = lsst.geom.Box2I(
                lsst.geom.Point2I(int(amp['raw_xmin']), int(amp['raw_ymin'])),
                lsst.geom.Point2I(int(amp['raw_xmax']), int(amp['raw_ymax'])))
            rawDataBbox = lsst.geom.Box2I(
                lsst.geom.Point2I(int(amp['raw_data_xmin']),
                                  int(amp['raw_data_ymin'])),
                lsst.geom.Point2I(int(amp['raw_data_xmax']),
                                  int(amp['raw_data_ymax'])))
            rawHOverscanBbox = lsst.geom.Box2I(
                lsst.geom.Point2I(int(amp['hoscan_xmin']),
                                  int(amp['hoscan_ymin'])),
                lsst.geom.Point2I(int(amp['hoscan_xmax']),
                                  int(amp['hoscan_ymax'])))
            rawVOverscanBbox = lsst.geom.Box2I(
                lsst.geom.Point2I(int(amp['voscan_xmin']),
                                  int(amp['voscan_ymin'])),
                lsst.geom.Point2I(int(amp['voscan_xmax']),
                                  int(amp['voscan_ymax'])))
            rawPrescanBbox = lsst.geom.Box2I(
                lsst.geom.Point2I(int(amp['pscan_xmin']),
                                  int(amp['pscan_ymin'])),
                lsst.geom.Point2I(int(amp['pscan_xmax']),
                                  int(amp['pscan_ymax'])))
            xoffset = int(amp['x_offset'])
            yoffset = int(amp['y_offset'])
            flipx = bool(int(amp['flipx']))
            flipy = bool(int(amp['flipy']))
            readcorner = 'LL'
            if not isLsstLike:
                offext = lsst.geom.Extent2I(xoffset, yoffset)
                if flipx:
                    xExt = rawBbox.getDimensions().getX()
                    rawBbox.flipLR(xExt)
                    rawDataBbox.flipLR(xExt)
                    rawHOverscanBbox.flipLR(xExt)
                    rawVOverscanBbox.flipLR(xExt)
                    rawPrescanBbox.flipLR(xExt)
                if flipy:
                    yExt = rawBbox.getDimensions().getY()
                    rawBbox.flipTB(yExt)
                    rawDataBbox.flipTB(yExt)
                    rawHOverscanBbox.flipTB(yExt)
                    rawVOverscanBbox.flipTB(yExt)
                    rawPrescanBbox.flipTB(yExt)
                if not flipx and not flipy:
                    readcorner = 'LL'
                elif flipx and not flipy:
                    readcorner = 'LR'
                elif flipx and flipy:
                    readcorner = 'UR'
                elif not flipx and flipy:
                    readcorner = 'UL'
                else:
                    raise RuntimeError("Couldn't find read corner")

                flipx = False
                flipy = False
                rawBbox.shift(offext)
                rawDataBbox.shift(offext)
                rawHOverscanBbox.shift(offext)
                rawVOverscanBbox.shift(offext)
                rawPrescanBbox.shift(offext)
                xoffset = 0
                yoffset = 0
            offset = lsst.geom.Extent2I(xoffset, yoffset)
            record.setBBox(bbox)
            record.setRawXYOffset(offset)
            record.setName(str(amp['name']))
            record.setReadoutCorner(readoutMap[readcorner])
            record.setGain(float(amp['gain']))
            record.setReadNoise(float(amp['readnoise']))
            record.setLinearityCoeffs([
                float(amp['lin_coeffs']),
            ])
            record.setLinearityType(str(amp['lin_type']))
            record.setHasRawInfo(True)
            record.setRawFlipX(flipx)
            record.setRawFlipY(flipy)
            record.setRawBBox(rawBbox)
            record.setRawDataBBox(rawDataBbox)
            record.setRawHorizontalOverscanBBox(rawHOverscanBbox)
            record.setRawVerticalOverscanBBox(rawVOverscanBbox)
            record.setRawPrescanBBox(rawPrescanBbox)
            record.set(linThreshKey, float(amp['lin_thresh']))
            record.set(linMaxKey, float(amp['lin_max']))
            record.set(linUnitsKey, str(amp['lin_units']))
            # The current schema assumes third order coefficients
            saveCoeffs = (float(amp['lin_coeffs']), )
            saveCoeffs += (np.nan, np.nan, np.nan)
            self.ampInfoDict[amp['ccd_name']]['linInfo'][amp['name']] = \
                {'lincoeffs': saveCoeffs, 'lintype': str(amp['lin_type']),
                 'linthresh': float(amp['lin_thresh']), 'linmax': float(amp['lin_max']),
                 'linunits': str(amp['lin_units'])}
        return ampTablesDict
Esempio n. 18
0
import lsst.afw.table as afwTable
import lsst.afw.geom as afwGeom
import numpy as np

# This is copying from afw/tests/testAmpInfoTable.py:
schema = afwTable.AmpInfoTable.makeMinimalSchema()
catalog = afwTable.AmpInfoCatalog(schema)
record = catalog.addNew()

name = 'Amp1'
bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(8176, 6132))
gain = 0.7
saturation = 57571
readNoise = 12.5
readoutCorner = afwTable.LL  #I think this means Lower Left.
linearityCoeffs = (1.0, np.nan, np.nan, np.nan)
linearityType = "None"
rawBBox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(8176, 6132))
rawXYOffset = afwGeom.Extent2I(0, 0)
rawDataBBox = afwGeom.Box2I(afwGeom.Point2I(0, 0),
                            afwGeom.Extent2I(8176, 6132))
#rawHorizontalOverscanBBox = afwGeom.Box2I(afwGeom.Point2I(8176, 0), afwGeom.Extent2I(0, 8176))
#rawVerticalOverscanBBox = afwGeom.Box2I(afwGeom.Point2I(6132, 0), afwGeom.Extent2I(0, 6132))
rawPrescanBBox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(0, 0))

record.setHasRawInfo(True)  #Sets the first Flag=True
record.setRawFlipX(False)  #Sets the second Flag=False
record.setRawFlipY(False)  #Sets the third Flag=False
record.setBBox(bbox)
record.setName(name)
record.setGain(gain)
Esempio n. 19
0
def parseCcds(policy, ccdParams, ccdToUse=None):
    """ parse a policy into a set of ampInfo and detectorConfig objects
    @param[in] policy  Policy to parse
    @param[in] ccdParams  dictionary of dictionaries describing the ccds in the camera
    @param[in] ccdToUse  Override the type of ccd to use given in the policy
    @return a dictionary of lists with detectorConfigs with the 'ccdInfo' key and AmpInfoCatalogs
    with the 'ampInfo' key
    """
    # The pafs I have now in the hsc dir include the focus sensors (but not the guiders)
    specialChipMap = {
        '108': cameraGeom.FOCUS,
        '110': cameraGeom.FOCUS,
        '111': cameraGeom.FOCUS,
        '107': cameraGeom.FOCUS,
        '105': cameraGeom.FOCUS,
        '104': cameraGeom.FOCUS,
        '109': cameraGeom.FOCUS,
        '106': cameraGeom.FOCUS
    }
    eParams = makeEparams(policy)
    lParams = makeLparams(policy)
    ampInfoDict = {}
    ccdInfoList = []
    rafts = policy.getArray('Raft')
    if len(rafts) > 1:
        raise ValueError("Expecting only one raft")
    for ccd in rafts[0].getArray('Ccd'):
        detConfig = DetectorConfig()
        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        ampCatalog = afwTable.AmpInfoCatalog(schema)
        if ccdToUse is not None:
            ccdParam = ccdParams[ccdToUse]
        else:
            ccdParam = ccdParams[ccd.get('ptype')]
        detConfig.name = ccd.get('name')
        #This should be the serial number on the device, but for now is an integer id
        detConfig.serial = str(ccd.get('serial'))
        detConfig.id = ccd.get('serial')
        offset = ccd.getArray('offset')
        if ccdParam['offsetUnit'] == 'pixels':
            offset[0] *= ccdParam['pixelSize']
            offset[1] *= ccdParam['pixelSize']
        detConfig.offset_x = offset[0]
        detConfig.offset_y = offset[1]
        if detConfig.serial in specialChipMap:
            detConfig.detectorType = specialChipMap[detConfig.serial]
        else:
            detConfig.detectorType = SCIENCE
        detConfig.pixelSize_x = ccdParam['pixelSize']
        detConfig.pixelSize_y = ccdParam['pixelSize']
        detConfig.refpos_x = (ccdParam['xsize'] - 1) / 2.
        detConfig.refpos_y = (ccdParam['ysize'] - 1) / 2.
        detConfig.bbox_x0 = 0
        detConfig.bbox_y0 = 0
        detConfig.bbox_x1 = ccdParam['xsize'] - 1
        detConfig.bbox_y1 = ccdParam['ysize'] - 1
        detConfig.rollDeg = 0.
        detConfig.pitchDeg = 0.
        detConfig.yawDeg = 90. * ccd.get('nQuarter') + ccd.getArray(
            'orientation')[2]
        for amp in ccdParam['ampArr']:
            eparms = None
            for ep in eParams[ccd.get('name')]:
                if amp['id'] - 1 == ep['index'][0]:
                    eparms = ep
            if eparms is None:
                raise ValueError("Could not find electronic params.")

            lparms = None
            # Only science ccds (serial 0 through 103) have linearity params defined in hsc_geom.paf
            if detConfig.detectorType is SCIENCE:
                if lParams.has_key(ccd.get('serial')):
                    for ep in lParams[ccd.get('serial')]:
                        if amp['id'] == ep['index']:
                            lparms = ep
                if lparms is None:
                    if lParams.has_key(
                            -1
                    ):  # defaults in suprimecam/Full_Suprimecam*_geom.paf
                        for ep in lParams[-1]:
                            if amp['id'] == ep['index']:
                                lparms = ep
                if lparms is None:
                    raise ValueError("Could not find linearity params.")
            if lparms is None:
                lparms = {}
                lparms['index'] = amp['id']
                lparms['coefficient'] = 0.0
                lparms['type'] = 'NONE'
                lparms['threshold'] = 0.0
                lparms['maxCorrectable'] = 0.0
                lparms['intensityUnits'] = 'UNKNOWN'
            addAmp(ampCatalog, amp, eparms, lparms)
        ampInfoDict[ccd.get('name')] = ampCatalog
        ccdInfoList.append(detConfig)
    return {"ccdInfo": ccdInfoList, "ampInfo": ampInfoDict}