def testTransformAccess(self): """Test hasTransform and getTransform """ detector = DetectorWrapper().detector for fromSys in (cameraGeom.FOCAL_PLANE, cameraGeom.PIXELS, cameraGeom.TAN_PIXELS): fullFromSys = detector.makeCameraSys(fromSys) for toSys in (cameraGeom.FOCAL_PLANE, cameraGeom.PIXELS, cameraGeom.TAN_PIXELS): fullToSys = detector.makeCameraSys(toSys) self.assertTrue(detector.hasTransform(fromSys)) self.assertTrue(detector.hasTransform(fullFromSys)) self.assertTrue(detector.hasTransform(toSys)) self.assertTrue(detector.hasTransform(fullToSys)) detector.getTransform(fromSys, toSys) detector.getTransform(fromSys, fullToSys) detector.getTransform(fullFromSys, toSys) detector.getTransform(fullFromSys, fullToSys) for badCamSys in (cameraGeom.CameraSys("badName"), cameraGeom.CameraSys("pixels", "badDetectorName")): self.assertFalse(detector.hasTransform(badCamSys)) self.assertTrue(detector.hasTransform(cameraGeom.PIXELS)) with self.assertRaises(lsst.pex.exceptions.Exception): detector.getTransform(cameraGeom.PIXELS, badCamSys)
def testHashing(self): """Test that hashing works as expected""" cs1 = cameraGeom.CameraSys("pixels", "det1") cs1Copy = cameraGeom.CameraSys("pixels", "det1") cs2 = cameraGeom.CameraSys("pixels", "det2") cs2Copy = cameraGeom.CameraSys("pixels", "det2") # import pdb; pdb.set_trace() csSet = set((cs1, cs1Copy, cs2, cs2Copy)) self.assertEqual(len(csSet), 2)
def testBasics(self): """Test CameraSys and CameraSysPrefix """ for sysName in ("fieldAngle", "pixels"): for detectorName in ("", "det1", "det2"): cameraSys = cameraGeom.CameraSys(sysName, detectorName) self.assertEqual(cameraSys.getSysName(), sysName) self.assertEqual(cameraSys.getDetectorName(), detectorName) self.assertEqual(cameraSys.hasDetectorName(), bool(detectorName)) noDetSys = cameraGeom.CameraSys(sysName) self.assertEqual(noDetSys.getSysName(), sysName) self.assertEqual(noDetSys.getDetectorName(), "") self.assertFalse(noDetSys.hasDetectorName()) camSysPrefix = cameraGeom.CameraSysPrefix(sysName) self.assertEqual(camSysPrefix.getSysName(), sysName) cameraSys2 = cameraGeom.CameraSys(camSysPrefix, detectorName) self.assertEqual(cameraSys2.getSysName(), sysName) self.assertEqual(cameraSys2.getDetectorName(), detectorName) self.assertEqual(cameraSys2, cameraSys) if detectorName: self.assertNotEqual(cameraSys, noDetSys) else: self.assertEqual(cameraSys, noDetSys) # The following tests are checking the functionality of the # == and != operators and should not be replaced with # assertEqual or assertNotEqual self.assertTrue(cameraSys != camSysPrefix) self.assertTrue(noDetSys != camSysPrefix) self.assertFalse(cameraSys == camSysPrefix) self.assertFalse(noDetSys == camSysPrefix) for sysName2 in ("fieldAngle", "pixels"): for detectorName2 in ("", "det1", "det2"): cameraSys2 = cameraGeom.CameraSys(sysName2, detectorName2) if sysName == sysName2 and detectorName == detectorName2: self.assertEqual(cameraSys, cameraSys2) # test __eq__ and __ne__ self.assertTrue(cameraSys == cameraSys2) self.assertFalse(cameraSys != cameraSys2) else: self.assertNotEqual(cameraSys, cameraSys2) # test __eq__ and __ne__ self.assertTrue(cameraSys != cameraSys2) self.assertFalse(cameraSys == cameraSys2) camSysPrefix2 = cameraGeom.CameraSysPrefix(sysName2) if sysName2 == sysName: self.assertEqual(camSysPrefix2, camSysPrefix) else: self.assertNotEqual(camSysPrefix2, camSysPrefix)
def testHashing(self): """Test that hashing gives equal CameraSys equal hashes""" # Not sure CameraSys has diverse enough values for testing # hash uniformity to be worthwhile cs1 = cameraGeom.CameraSys("pixels", "det1") cs1Copy = cameraGeom.CameraSys("pixels", "det1") cs2 = cameraGeom.CameraSys("pixels", "det2") cs2Copy = cameraGeom.CameraSys("pixels", "det2") csSet = set((cs1, cs1Copy, cs2, cs2Copy)) self.assertEqual(len(csSet), 2)
def testRepr(self): """Test __repr__ """ cs1 = cameraGeom.CameraSys("pixels", "det1") self.assertEqual(repr(cs1), "CameraSys(pixels, det1)") cs2 = cameraGeom.CameraSys("pixels") self.assertEqual(repr(cs2), "CameraSys(pixels)") dsp = cameraGeom.CameraSysPrefix("pixels") self.assertEqual(repr(dsp), "CameraSysPrefix(pixels)")
def testMakeCameraSys(self): """Test the makeCameraSys method """ dw = DetectorWrapper() for sysName in ("csys1", "csys2"): for detectorName in ("", dw.name, "a different detector"): inCamSys = cameraGeom.CameraSys(sysName, detectorName) outCamSys = dw.detector.makeCameraSys(inCamSys) self.assertEquals(inCamSys, outCamSys) inCamSysPrefix = cameraGeom.CameraSysPrefix(sysName) outCamSys2 = dw.detector.makeCameraSys(inCamSysPrefix) self.assertEquals(outCamSys2, cameraGeom.CameraSys(sysName, dw.name))
def testGet(self): """Test the get method """ for cs in self.transformMap.getCoordSysList(): xyTrans2 = self.transformMap.get(cs) self.assertTrue(isinstance(xyTrans2, afwGeom.XYTransform)) missingCamSys = cameraGeom.CameraSys("missing") shouldBeNone = self.transformMap.get(missingCamSys) self.assertTrue(shouldBeNone is None) self.assertRaises(Exception, self.transformMap.get, "badDataType") for default in (1, "hello", cameraGeom.CameraSys("default")): res = self.transformMap.get(missingCamSys, default) self.assertEquals(res, default)
def testBasics(self): """Test CameraSys and CameraSysPrefix """ for sysName in ("pupil", "pixels"): for detectorName in ("", "det1", "det2"): cameraSys = cameraGeom.CameraSys(sysName, detectorName) self.assertEquals(cameraSys.getSysName(), sysName) self.assertEquals(cameraSys.getDetectorName(), detectorName) self.assertEquals(cameraSys.hasDetectorName(), bool(detectorName)) noDetSys = cameraGeom.CameraSys(sysName) self.assertEquals(noDetSys.getSysName(), sysName) self.assertEquals(noDetSys.getDetectorName(), "") self.assertFalse(noDetSys.hasDetectorName()) camSysPrefix = cameraGeom.CameraSysPrefix(sysName) self.assertEquals(camSysPrefix.getSysName(), sysName) if detectorName: self.assertFalse(cameraSys == noDetSys) self.assertTrue(cameraSys != noDetSys) else: self.assertTrue(cameraSys == noDetSys) self.assertFalse(cameraSys != noDetSys) self.assertTrue(cameraSys != camSysPrefix) self.assertTrue(noDetSys != camSysPrefix) self.assertFalse(cameraSys == camSysPrefix) self.assertFalse(noDetSys == camSysPrefix) for sysName2 in ("pupil", "pixels"): for detectorName2 in ("", "det1", "det2"): cameraSys2 = cameraGeom.CameraSys(sysName2, detectorName2) if sysName == sysName2 and detectorName == detectorName2: self.assertTrue(cameraSys == cameraSys2) self.assertFalse(cameraSys != cameraSys2) else: self.assertFalse(cameraSys == cameraSys2) self.assertTrue(cameraSys != cameraSys2) camSysPrefix2 = cameraGeom.CameraSysPrefix(sysName2) if sysName2 == sysName: self.assertTrue(camSysPrefix2 == camSysPrefix) self.assertFalse(camSysPrefix2 != camSysPrefix) else: self.assertFalse(camSysPrefix2 == camSysPrefix) self.assertTrue(camSysPrefix2 != camSysPrefix)
def testTransform(self): """Test the transform method """ dw = DetectorWrapper() pixOffset = dw.orientation.getReferencePoint() for xyMM in ((25.6, -31.07), (0, 0), (-1.234e5, 3.123e4)): fpPoint = afwGeom.Point2D(*xyMM) fpCamPoint = cameraGeom.CameraPoint(fpPoint, cameraGeom.FOCAL_PLANE) pixCamPoint = dw.detector.transform(fpCamPoint, cameraGeom.PIXELS) pixPoint = pixCamPoint.getPoint() for i in range(2): self.assertAlmostEquals( fpPoint[i] / dw.pixelSize[i] + pixOffset[i], pixPoint[i]) fpCamPoint2 = dw.detector.transform(pixCamPoint, cameraGeom.FOCAL_PLANE) fpPoint2 = fpCamPoint2.getPoint() for i in range(2): self.assertAlmostEquals(fpPoint[i], fpPoint2[i]) # test pix to pix pixCamPoint2 = dw.detector.transform(pixCamPoint, cameraGeom.PIXELS) for i in range(2): self.assertAlmostEquals(pixCamPoint.getPoint()[i], pixCamPoint2.getPoint()[i]) # make sure you cannot transform to a different detector pixCamPoint = dw.detector.makeCameraPoint(afwGeom.Point2D(1, 1), cameraGeom.PIXELS) otherCamSys = cameraGeom.CameraSys(cameraGeom.PIXELS, "other detector") with self.assertRaises(lsst.pex.exceptions.Exception): dw.detector.transform(pixCamPoint, otherCamSys)
def testGetItem(self): """Test that the contained transforms are the ones expected """ nativeTr = self.transformMap.getTransform(self.nativeSys, self.nativeSys) self.compare2DFunctions(nativeTr.applyForward, unityTransform) self.compare2DFunctions(nativeTr.applyInverse, unityTransform) fieldTr = self.transformMap.getTransform(self.nativeSys, cameraGeom.FIELD_ANGLE) self.compare2DFunctions(fieldTr.applyForward, self.fieldTransform.applyForward) self.compare2DFunctions(fieldTr.applyInverse, self.fieldTransform.applyInverse) fieldTrInv = self.transformMap.getTransform(cameraGeom.FIELD_ANGLE, self.nativeSys) self.compare2DFunctions(fieldTrInv.applyForward, self.fieldTransform.applyInverse) self.compare2DFunctions(fieldTrInv.applyInverse, self.fieldTransform.applyForward) missingCamSys = cameraGeom.CameraSys("missing") with self.assertRaises(lsst.pex.exceptions.Exception): self.transformMap.getTransform(missingCamSys, self.nativeSys) with self.assertRaises(lsst.pex.exceptions.Exception): self.transformMap.getTransform(self.nativeSys, missingCamSys)
def testTransform(self): """Test the transform method """ dw = DetectorWrapper() pixOffset = dw.orientation.getReferencePoint() for xyMM in ((25.6, -31.07), (0, 0), (-1.234e5, 3.123e4)): fpPoint = afwGeom.Point2D(*xyMM) pixPoint = dw.detector.transform(fpPoint, cameraGeom.FOCAL_PLANE, cameraGeom.PIXELS) for i in range(2): self.assertAlmostEqual( fpPoint[i] / dw.pixelSize[i] + pixOffset[i], pixPoint[i]) fpPoint2 = dw.detector.transform(pixPoint, cameraGeom.PIXELS, cameraGeom.FOCAL_PLANE) self.assertPairsAlmostEqual(fpPoint, fpPoint2) # test pix to pix pixPoint2 = dw.detector.transform(pixPoint, cameraGeom.PIXELS, cameraGeom.PIXELS) self.assertPairsAlmostEqual(pixPoint, pixPoint2) # make sure you cannot transform to or from a different detector otherCamSys = cameraGeom.CameraSys(cameraGeom.PIXELS, "other detector") for goodSys in (cameraGeom.PIXELS, cameraGeom.FOCAL_PLANE): with self.assertRaises(lsst.pex.exceptions.Exception): dw.detector.transform(pixPoint, goodSys, otherCamSys) with self.assertRaises(lsst.pex.exceptions.Exception): dw.detector.transform(pixPoint, otherCamSys, goodSys)
def makeCamera(cameraFile): """An imaging camera (e.g. the LSST 3Gpix camera) Parameters ---------- cameraFile : `str` Camera description YAML file. Returns ------- camera : `lsst.afw.cameraGeom.Camera` The desired Camera """ with open(cameraFile) as fd: cameraParams = yaml.load(fd, Loader=yaml.CLoader) cameraName = cameraParams["name"] # # Handle distortion models. # plateScale = geom.Angle(cameraParams["plateScale"], geom.arcseconds) nativeSys = cameraGeom.CameraSys(cameraParams["transforms"].pop("nativeSys")) transforms = makeTransformDict(nativeSys, cameraParams["transforms"], plateScale) ccdParams = cameraParams["CCDs"] detectorConfigList = makeDetectorConfigList(ccdParams) amplifierDict = {} for ccdName, ccdValues in ccdParams.items(): amplifierDict[ccdName] = makeAmplifierList(ccdValues) return makeCameraFromCatalogs(cameraName, detectorConfigList, nativeSys, transforms, amplifierDict)
def makeTransformDict(nativeSys, transformDict, plateScale): """Make a dictionary of TransformPoint2ToPoint2s from yaml, mapping from nativeSys Parameters ---------- nativeSys : `lsst.afw.cameraGeom.CameraSys` transformDict : `dict` A dict specifying parameters of transforms; keys are camera system names. plateScale : `lsst.geom.Angle` The size of a pixel in angular units/mm (e.g. 20 arcsec/mm for LSST) Returns ------- transforms : `dict` A dict of `lsst.afw.cameraGeom.CameraSys` : `lsst.afw.geom.TransformPoint2ToPoint2` The resulting dict's keys are `~lsst.afw.cameraGeom.CameraSys`, and the values are Transforms *from* NativeSys *to* CameraSys """ # As other comments note this is required, and this is one function where # it's assumed assert nativeSys == cameraGeom.FOCAL_PLANE, "Cameras with nativeSys != FOCAL_PLANE are not supported." resMap = dict() for key, transform in transformDict.items(): transformType = transform["transformType"] knownTransformTypes = ["affine", "radial"] if transformType not in knownTransformTypes: raise RuntimeError("Saw unknown transform type for %s: %s (known types are: [%s])" % ( key, transform["transformType"], ", ".join(knownTransformTypes))) if transformType == "affine": affine = geom.AffineTransform(np.array(transform["linear"]), np.array(transform["translation"])) transform = afwGeom.makeTransform(affine) elif transformType == "radial": # radial coefficients of the form [0, 1 (no units), C2 (rad), # usually 0, C3 (rad^2), ...] # Radial distortion is modeled as a radial polynomial that converts # from focal plane radius (in mm) to field angle (in radians). # The provided coefficients are divided by the plate # scale (in radians/mm) meaning that C1 is always 1. radialCoeffs = np.array(transform["coeffs"]) radialCoeffs *= plateScale.asRadians() transform = afwGeom.makeRadialTransform(radialCoeffs) else: raise RuntimeError("Impossible condition \"%s\" is not in: [%s])" % ( transform["transformType"], ", ".join(knownTransformTypes))) resMap[cameraGeom.CameraSys(key)] = transform return resMap
def testTransformAccess(self): """Test hasTransform and getTransform """ detector = DetectorWrapper().detector for camSys in (cameraGeom.FOCAL_PLANE, cameraGeom.PIXELS, cameraGeom.TAN_PIXELS): # camSys may be a CameraSys or a CameraSysPrefix fullCamSys = detector.makeCameraSys(camSys) self.assertTrue(detector.hasTransform(camSys)) self.assertTrue(detector.hasTransform(fullCamSys)) detector.getTransform(camSys) detector.getTransform(fullCamSys) for badCamSys in ( cameraGeom.CameraSys("badName"), cameraGeom.CameraSys("pixels", "badDetectorName") ): self.assertFalse(detector.hasTransform(badCamSys)) self.assertRaises(lsst.pex.exceptions.Exception, detector.getTransform, badCamSys)
def testMakeCameraPoint(self): """Test the makeCameraPoint method """ dw = DetectorWrapper() for xyMM in ((25.6, -31.07), (0, 0)): point = afwGeom.Point2D(*xyMM) for sysName in ("csys1", "csys2"): for detectorName in ("", dw.name, "a different detector"): cameraSys1 = cameraGeom.CameraSys(sysName, detectorName) cameraPoint1 = dw.detector.makeCameraPoint(point, cameraSys1) self.assertEquals(cameraPoint1.getPoint(), point) self.assertEquals(cameraPoint1.getCameraSys(), cameraSys1) cameraSysPrefix = cameraGeom.CameraSysPrefix(sysName) cameraPoint2 = dw.detector.makeCameraPoint(point, cameraSysPrefix) predCameraSys2 = cameraGeom.CameraSys(sysName, dw.name) self.assertEquals(cameraPoint2.getPoint(), point) self.assertEquals(cameraPoint2.getCameraSys(), predCameraSys2)
def testBasics(self): """Test basic attributes """ for methodName in ("begin", "end", "contains", "size"): self.assertFalse(hasattr(self.transformMap, methodName)) self.assertIn(self.nativeSys, self.transformMap) self.assertIn(cameraGeom.FIELD_ANGLE, self.transformMap) self.assertNotIn(cameraGeom.CameraSys("garbage"), self.transformMap) self.assertIn(self.nativeSys, self.transformMap) self.assertIn(cameraGeom.FIELD_ANGLE, self.transformMap)
def testBasics(self): """Test basic attributes """ for methodName in ("begin", "end", "contains", "size"): self.assertFalse(hasattr(self.transformMap, methodName)) self.assertTrue(self.nativeSys in self.transformMap) self.assertTrue(cameraGeom.PUPIL in self.transformMap) self.assertFalse(cameraGeom.CameraSys("garbage") in self.transformMap) csList = self.transformMap.getCoordSysList() self.assertTrue(len(csList) == 2) self.assertTrue(self.nativeSys in csList) self.assertTrue(cameraGeom.PUPIL in csList)
def testGetItem(self): """Test that the contained transforms are the ones expected """ nativeTr = self.transformMap[self.nativeSys] self.compare2DFunctions(nativeTr.forwardTransform, unityTransform) self.compare2DFunctions(nativeTr.reverseTransform, unityTransform) pupilTr = self.transformMap[cameraGeom.PUPIL] self.compare2DFunctions(pupilTr.forwardTransform, self.pupilTransform.forwardTransform) self.compare2DFunctions(pupilTr.reverseTransform, self.pupilTransform.reverseTransform) missingCamSys = cameraGeom.CameraSys("missing") self.assertRaises(lsst.pex.exceptions.Exception, self.transformMap.__getitem__, missingCamSys)
def testBasics(self): """Test getters and other basics """ dw = DetectorWrapper() detector = dw.detector for methodName in ("begin", "end", "size"): if hasattr(detector, methodName): self.assertFalse(hasattr(detector, methodName)) self.assertEqual(dw.name, detector.getName()) self.assertEqual(dw.id, detector.getId()) self.assertEqual(dw.type, detector.getType()) self.assertEqual(dw.serial, detector.getSerial()) bbox = detector.getBBox() for i in range(2): self.assertEqual(bbox.getMin()[i], dw.bbox.getMin()[i]) self.assertEqual(bbox.getMax()[i], dw.bbox.getMax()[i]) self.assertAlmostEqual(dw.pixelSize, detector.getPixelSize()) self.assertEqual(len(detector), len(dw.ampInfo)) orientation = detector.getOrientation() transformMap = detector.getTransformMap() # add 1 for null transform self.assertEqual(len(transformMap), len(dw.transMap) + 1) for cameraSys in dw.transMap: self.assertTrue(cameraSys in transformMap) self.assertEqual(detector.getPhysicalType(), "CCD") # the default in DetectorWrapper, not Detector # make sure some complex objects stick around after detector is deleted detectorName = detector.getName() nativeCoordSys = detector.getNativeCoordSys() offset = dw.orientation.getFpPosition() del detector del dw self.assertEqual(orientation.getFpPosition(), offset) self.assertEqual( nativeCoordSys, cameraGeom.CameraSys(cameraGeom.PIXELS.getSysName(), detectorName))
#!/usr/bin/env python import lsst.pex.policy as pexPolicy import lsst.afw.table as afwTable import lsst.afw.geom as afwGeom import lsst.afw.cameraGeom as cameraGeom from lsst.afw.cameraGeom import SCIENCE, FOCAL_PLANE, PUPIL, CameraConfig, DetectorConfig,\ makeCameraFromCatalogs import argparse import eups import os import copy import shutil FOCAL_PLANE_PIXELS = cameraGeom.CameraSys('Focal_Plane_Pixels') PIXELSIZE = 1.0 # LSST likes to use mm/pix, but Subaru works in pixels def makeDir(dirPath, doClobber=False): """Make a directory; if it exists then clobber or fail, depending on doClobber @param[in] dirPath: path of directory to create @param[in] doClobber: what to do if dirPath already exists: if True and dirPath is a dir, then delete it and recreate it, else raise an exception @throw RuntimeError if dirPath exists and doClobber False """ if os.path.exists(dirPath): if doClobber and os.path.isdir(dirPath): print "Clobbering directory %r" % (dirPath, ) shutil.rmtree(dirPath)
def addBadCameraSys(dw): """Add an invalid camera system""" dw.transMap[cameraGeom.CameraSys("foo", "wrong detector")] = \ afwGeom.makeIdentityTransform()
def makeCameraFromCatalogs(cameraName, detectorConfigList, nativeSys, transformDict, amplifierDict, pupilFactoryClass=cameraGeom.pupil.PupilFactory): """Construct a Camera instance from a dictionary of detector name : `lsst.afw.cameraGeom.amplifier` Parameters ---------- cameraName : `str` The name of the camera detectorConfigList : `list` A list of `lsst.afw.cameraGeom.cameraConfig.DetectorConfig` nativeSys : `lsst.afw.cameraGeom.CameraSys` The native transformation type; must be `lsst.afw.cameraGeom.FOCAL_PLANE` transformDict : `dict` A dict of lsst.afw.cameraGeom.CameraSys : `lsst.afw.geom.TransformPoint2ToPoint2` amplifierDict : `dict` A dictionary of detector name : `lsst.afw.cameraGeom.Amplifier.Builder` pupilFactoryClass : `type`, optional Class to attach to camera; `lsst.default afw.cameraGeom.PupilFactory` Returns ------- camera : `lsst.afw.cameraGeom.Camera` New Camera instance. Notes ------ Copied from `lsst.afw.cameraGeom.cameraFactory` with permission and encouragement from Jim Bosch """ # nativeSys=FOCAL_PLANE seems to be assumed in various places in this file # (e.g. the definition of TAN_PIXELS), despite CameraConfig providing the # illusion that it's configurable. # Note that we can't actually get rid of the nativeSys config option # without breaking lots of on-disk camera configs. assert nativeSys == cameraGeom.FOCAL_PLANE, "Cameras with nativeSys != FOCAL_PLANE are not supported." focalPlaneToField = transformDict[cameraGeom.FIELD_ANGLE] cameraBuilder = Camera.Builder(cameraName) cameraBuilder.setPupilFactoryClass(pupilFactoryClass) # Ensure all transforms in the camera transform dict are included. for toSys, transform in transformDict.items(): cameraBuilder.setTransformFromFocalPlaneTo(toSys, transform) for detectorConfig in detectorConfigList: # This should build all detector pixel -> focalPlane transforms. cameraGeom.addDetectorBuilderFromConfig(cameraBuilder, detectorConfig, amplifierDict[detectorConfig.name], focalPlaneToField) # For reasons I don't understand, some obs_ packages (e.g. HSC) set # nativeSys to None for their detectors (which doesn't seem to be # permitted by the config class!), but they really mean PIXELS. For # backwards compatibility we use that as the default... detectorNativeSys = detectorConfig.transformDict.nativeSys detectorNativeSys = (cameraGeom.PIXELS if detectorNativeSys is None else cameraGeom.CameraSysPrefix(detectorNativeSys)) # ...well, actually, it seems that we've always assumed down in C++ # that the answer is always PIXELS without ever checking that it is. # So let's assert that it is, since there are hints all over this file # (e.g. the definition of TAN_PIXELS) that other parts of the codebase # have regularly made that assumption as well. Note that we can't # actually get rid of the nativeSys config option without breaking # lots of on-disk camera configs. assert detectorNativeSys == cameraGeom.PIXELS, \ "Detectors with nativeSys != PIXELS are not supported." detectorNativeSys = cameraGeom.CameraSys(detectorNativeSys, detectorConfig.name) return cameraBuilder.finish()