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}
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}
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)
def makeDetectorConfigs(detectorLayoutFile): """ Create the detector configs to use in building the Camera @param detectorLayoutFile -- String describing where the focalplanelayout.txt file is located. """ detectorConfigs = [] xsize = 2048 ysize = 4096 #Only do Science detectors right now. #There is an overall 0.05 deg rotation to the entire focal plane that I'm ignoring here. with open(detectorLayoutFile) 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 detConfig = DetectorConfig() detConfig.name = detectorName detConfig.id = int(els[0]) detConfig.bbox_x0 = 0 detConfig.bbox_y0 = 0 detConfig.bbox_x1 = xsize - 1 detConfig.bbox_y1 = ysize - 1 detConfig.detectorType = 0 detConfig.serial = els[0] # Convert from microns to mm. detConfig.offset_x = (float(els[2]) + float(els[3]))/2. detConfig.offset_y = (float(els[4]) + float(els[5]))/2. detConfig.refpos_x = (xsize - 1.)/2. detConfig.refpos_y = (ysize - 1.)/2. # TODO translate between John's angles and Orientation angles. # It's not an issue now because there is no rotation except about z in John's model. detConfig.yawDeg = float(els[6]) detConfig.pitchDeg = 0. detConfig.rollDeg = 0. detConfig.pixelSize_x = 0.015 detConfig.pixelSize_y = 0.015 detConfig.transposeDetector = False detConfig.transformDict.nativeSys = PIXELS.getSysName() # The FOCAL_PLANE and TAN_PIXEL transforms are generated by the Camera maker, # based on orientaiton and other data. # Any additional transforms (such as ACTUAL_PIXELS) should be inserted here. detectorConfigs.append(detConfig) return detectorConfigs
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)
def makeDetectorConfigs(detectorLayoutFile): """ Create the detector configs to use in building the Camera @param detectorLayoutFile -- String describing where the focalplanelayout.txt file is located. """ detectorConfigs = [] xsize = 2048 ysize = 4096 # Only do Science detectors right now. # There is an overall 0.05 deg rotation to the entire focal plane that I'm ignoring here. with open(detectorLayoutFile) 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 detConfig = DetectorConfig() detConfig.name = detectorName detConfig.id = int(els[0]) detConfig.bbox_x0 = 0 detConfig.bbox_y0 = 0 detConfig.bbox_x1 = xsize - 1 detConfig.bbox_y1 = ysize - 1 detConfig.detectorType = 0 detConfig.serial = els[0] # Convert from microns to mm. detConfig.offset_x = (float(els[2]) + float(els[3]))/2. detConfig.offset_y = (float(els[4]) + float(els[5]))/2. detConfig.refpos_x = (xsize - 1.)/2. detConfig.refpos_y = (ysize - 1.)/2. # TODO translate between John's angles and Orientation angles. # It's not an issue now because there is no rotation except about z in John's model. detConfig.yawDeg = float(els[6]) detConfig.pitchDeg = 0. detConfig.rollDeg = 0. detConfig.pixelSize_x = 0.015 detConfig.pixelSize_y = 0.015 detConfig.transposeDetector = False detConfig.transformDict.nativeSys = PIXELS.getSysName() # The FOCAL_PLANE and TAN_PIXEL transforms are generated by the Camera maker, # based on orientaiton and other data. # Any additional transforms (such as ACTUAL_PIXELS) should be inserted here. detectorConfigs.append(detConfig) return detectorConfigs
def _makeDetectorConfig(self, id, fpPos): """Make a detector config for one detector. Parameters ---------- id : `int` Detector ID. fpPos : pair of `float` Focal plane position of detector, in units of detector width/height. For example: - (0, 0) is a detector centered on the focal plane - (1, 0) is adjacent to a centered detector, in the direction of increasing focal plane x Returns ------- detectorConfig : `lsst.afw.cameraGeom.DetectorConfig` Detector configuration for one detector. """ bbox = lsst.geom.Box2I( lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(self.detectorWidthPix, self.detectorHeightPix)) ctr = lsst.geom.Box2D(bbox).getCenter() pixelSizeMm = 0.01 config = DetectorConfig() config.name = "D{}".format(id) config.id = id # detector serial number is not used by the CBP code, # but some value is required to construct a Detector config.serial = '0000011' config.detectorType = 0 config.bbox_x0 = bbox.getMinX() config.bbox_x1 = bbox.getMaxX() config.bbox_y0 = bbox.getMinY() config.bbox_y1 = bbox.getMaxY() config.pixelSize_x = pixelSizeMm config.pixelSize_y = pixelSizeMm config.transformDict.nativeSys = 'Pixels' config.transformDict.transforms = None config.refpos_x = ctr[0] config.refpos_y = ctr[1] config.offset_x = fpPos[0] * pixelSizeMm * self.detectorWidthPix config.offset_y = fpPos[1] * pixelSizeMm * self.detectorHeightPix config.transposeDetector = False config.pitchDeg = 0.0 config.yawDeg = 0.0 config.rollDeg = 0.0 return config
def makeDetectorConfigs(detectorLayoutFile, phosimVersion): """ Create the detector configs to use in building the Camera @param detectorLayoutFile -- String describing where the focalplanelayout.txt file is located. @todo: * set serial to something other than name (e.g. include git sha) * deal with the extra orientation angles (not that they really matter) """ detectorConfigs = [] detType = int(SCIENCE) #We know we need to rotate 3 times and also apply the yaw perturbation nQuarter = 1 with open(detectorLayoutFile) as fh: for l in fh: if l.startswith("#"): continue detConfig = DetectorConfig() els = l.rstrip().split() detConfig.name = expandDetectorName(els[0]) detConfig.id = detectorIdFromAbbrevName(els[0]) detConfig.bbox_x0 = 0 detConfig.bbox_y0 = 0 detConfig.bbox_x1 = int(els[5]) - 1 detConfig.bbox_y1 = int(els[4]) - 1 detConfig.detectorType = detType detConfig.serial = els[0]+"_"+phosimVersion # Convert from microns to mm. detConfig.offset_x = float(els[1])/1000. + float(els[12]) detConfig.offset_y = float(els[2])/1000. + float(els[13]) detConfig.refpos_x = (int(els[5]) - 1.)/2. detConfig.refpos_y = (int(els[4]) - 1.)/2. # TODO translate between John's angles and Orientation angles. # It's not an issue now because there is no rotation except about z in John's model. detConfig.yawDeg = 90.*nQuarter + float(els[9]) detConfig.pitchDeg = float(els[10]) detConfig.rollDeg = float(els[11]) detConfig.pixelSize_x = float(els[3])/1000. detConfig.pixelSize_y = float(els[3])/1000. detConfig.transposeDetector = False detConfig.transformDict.nativeSys = PIXELS.getSysName() # The FOCAL_PLANE and TAN_PIXEL transforms are generated by the Camera maker, # based on orientaiton and other data. # Any additional transforms (such as ACTUAL_PIXELS) should be inserted here. detectorConfigs.append(detConfig) return detectorConfigs
def makeDetectorConfigs(detectorLayoutFile, phosimVersion): """ Create the detector configs to use in building the Camera @param detectorLayoutFile -- String describing where the focalplanelayout.txt file is located. @todo: * set serial to something other than name (e.g. include git sha) * deal with the extra orientation angles (not that they really matter) """ detectorConfigs = [] detTypeMap = {"Group2":2, "Group1":3, "Group0":0} #We know we need to rotate 3 times and also apply the yaw perturbation nQuarter = 1 with open(detectorLayoutFile) as fh: for l in fh: if l.startswith("#"): continue detConfig = DetectorConfig() els = l.rstrip().split() detConfig.name = expandDetectorName(els[0]) detConfig.id = detectorIdFromAbbrevName(els[0]) detConfig.bbox_x0 = 0 detConfig.bbox_y0 = 0 detConfig.bbox_x1 = int(els[5]) - 1 detConfig.bbox_y1 = int(els[4]) - 1 detConfig.detectorType = detTypeMap[els[8]] detConfig.serial = els[0]+"_"+phosimVersion # Convert from microns to mm. detConfig.offset_x = float(els[1])/1000. + float(els[12]) detConfig.offset_y = float(els[2])/1000. + float(els[13]) detConfig.refpos_x = (int(els[5]) - 1.)/2. detConfig.refpos_y = (int(els[4]) - 1.)/2. # TODO translate between John's angles and Orientation angles. # It's not an issue now because there is no rotation except about z in John's model. detConfig.yawDeg = 90.*nQuarter + float(els[9]) detConfig.pitchDeg = float(els[10]) detConfig.rollDeg = float(els[11]) detConfig.pixelSize_x = float(els[3])/1000. detConfig.pixelSize_y = float(els[3])/1000. detConfig.transposeDetector = False detConfig.transformDict.nativeSys = PIXELS.getSysName() # The FOCAL_PLANE and TAN_PIXEL transforms are generated by the Camera maker, # based on orientaiton and other data. # Any additional transforms (such as ACTUAL_PIXELS) should be inserted here. detectorConfigs.append(detConfig) return detectorConfigs
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 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 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}
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}