23"""Mapper and cameraGeom definition for extremely simple mock data.
25SimpleMapper inherits directly from Mapper, not CameraMapper. This means
26we can avoid any problems with paf files at the expense of reimplementing
27some parts of CameraMapper here. Jim
is not sure this was the best
28possible approach, but it gave him an opportunity to play around
with
29prototyping a future paf-free mapper
class,
and it does everything it
37import lsst.daf.persistence
38import lsst.afw.cameraGeom
40import lsst.afw.image as afwImage
42__all__ = ("SimpleMapper", "makeSimpleCamera", "makeDataRepo")
46 """Base class of a hierarchy used by SimpleMapper to defined different kinds of types of objects
49 PersistenceType objects are never instantiated; only the type objects are used (we needed a
50 simple singleton struct that could be inherited, which is exactly what a Python type
is).
60 """Method called by SimpleMapping to implement a map_ method."""
61 return lsst.daf.persistence.ButlerLocation(cls.
pythonpython, cls.
cppcpp, cls.
storagestorage, [path], dataId,
70 """Persistence type for things that don't actually use daf_persistence.
73 python = "lsst.daf.base.PropertySet"
77 """Method called by SimpleMapping to implement a map_ method; overridden to not use the path."""
78 return lsst.daf.persistence.ButlerLocation(cls.
pythonpythonpython, cls.
cppcpp, cls.
storagestorage, [], dataId,
79 mapper=mapper, storage=storage)
83 """Persistence type of Exposure images.
86 python = "lsst.afw.image.ExposureF"
88 storage =
"FitsStorage"
94 """Method called by SimpleMapping to implement a map_ method; overridden to support subimages."""
96 loc = super(ExposurePersistenceType, cls).
makeButlerLocation(path, dataId, mapper, suffix=
None,
104 "compression.algorithm":
"NONE",
105 "compression.columns": 0,
106 "compression.rows": 0,
107 "compression.quantizeLevel": 0.0,
108 "scaling.algorithm":
"NONE",
109 "scaling.bzero": 0.0,
110 "scaling.bscale": 0.0,
112 "scaling.quantizeLevel": 0.0,
113 "scaling.quantizePad": 0.0,
114 "scaling.fuzz":
False,
117 for prefix
in (
"image",
"mask",
"variance"):
118 for k, v
in options.items():
119 loc.additionalData.set(
"{}.{}".format(prefix, k), v)
120 elif suffix ==
"_sub":
121 subId = dataId.copy()
122 bbox = subId.pop(
'bbox')
123 loc = super(ExposurePersistenceType, cls).
makeButlerLocation(path, subId, mapper, suffix=
None,
125 loc.additionalData.set(
'llcX', bbox.getMinX())
126 loc.additionalData.set(
'llcY', bbox.getMinY())
127 loc.additionalData.set(
'width', bbox.getWidth())
128 loc.additionalData.set(
'height', bbox.getHeight())
129 if 'imageOrigin' in dataId:
130 loc.additionalData.set(
'imageOrigin',
131 dataId[
'imageOrigin'])
136 python =
"lsst.skymap.BaseSkyMap"
137 storage =
"PickleStorage"
142 python =
"lsst.afw.table.BaseCatalog"
144 storage =
"FitsCatalogStorage"
149 python =
"lsst.afw.table.SimpleCatalog"
150 cpp =
"SimpleCatalog"
154 python =
"lsst.afw.table.SourceCatalog"
155 cpp =
"SourceCatalog"
159 python =
"lsst.afw.table.ExposureCatalog"
160 cpp =
"ExposureCatalog"
164 python =
"lsst.afw.detection.PeakCatalog"
169 """Mapping object used to implement SimpleMapper, similar in intent to lsst.daf.peristence.Mapping.
175 def __init__(self, persistence, template=None, keys=None):
177 if template
is not None:
182 def map(self, dataset, root, dataId, mapper, suffix=None, storage=None):
183 if self.
templatetemplate
is not None:
184 path = self.
templatetemplate.format(dataset=dataset, ext=self.
persistencepersistence.ext, **dataId)
187 return self.
persistencepersistence.makeButlerLocation(path, dataId, suffix=suffix, mapper=mapper,
192 """Mapping for dataset types that are organized the same way as raw data (i.e. by CCD)."""
194 template =
"{dataset}-{visit:04d}-{ccd:01d}{ext}"
195 keys = dict(visit=int, ccd=int)
197 def query(self, dataset, index, level, format, dataId):
198 dictList = index[dataset][level]
199 results = [list(d.values())
for d
in dictList[dataId.get(level,
None)]]
204 """Mapping for dataset types that are organized according to a SkyMap subdivision of the sky."""
206 template =
"{dataset}-{filter}-{tract:02d}-{patch}{ext}"
207 keys = dict(filter=str, tract=int, patch=str)
211 """Mapping for CoaddTempExp datasets."""
213 template =
"{dataset}-{tract:02d}-{patch}-{visit:04d}{ext}"
214 keys = dict(tract=int, patch=str, visit=int)
218 """Mapping for forced_src datasets."""
220 template =
"{dataset}-{tract:02d}-{visit:04d}-{ccd:01d}{ext}"
221 keys = dict(tract=int, ccd=int, visit=int)
225 """Metaclass for SimpleMapper that creates map_ and query_ methods for everything found in the
226 'mappings' class variable.
230 def _makeMapClosure(dataset, mapping, suffix=None):
231 def mapClosure(self, dataId, write=False):
232 return mapping.map(dataset, self.root, dataId, self, suffix=suffix, storage=self.storage)
236 def _makeQueryClosure(dataset, mapping):
237 def queryClosure(self, level, format, dataId):
238 return mapping.query(dataset, self.index, level, format, dataId)
242 type.__init__(cls, name, bases, dict_)
244 for dataset, mapping
in cls.mappings.items():
245 setattr(cls,
"map_" + dataset, MapperMeta._makeMapClosure(dataset, mapping, suffix=
None))
246 for suffix
in mapping.persistence.suffixes:
247 setattr(cls,
"map_" + dataset + suffix,
248 MapperMeta._makeMapClosure(dataset, mapping, suffix=suffix))
249 if hasattr(mapping,
"query"):
250 setattr(cls,
"query_" + dataset, MapperMeta._makeQueryClosure(dataset, mapping))
251 cls.
keyDictkeyDict.update(mapping.keys)
256 An extremely simple mapper for an imaginary camera
for use
in integration tests.
258 As SimpleMapper does
not inherit
from obs.base.CameraMapper, it does
not
259 use a policy file to set mappings
or a registry; all the information
is here
260 (
in the map_*
and query_* methods).
262 The imaginary camera
's raw data format has only 'visit
' and 'ccd
' keys, with
263 two CCDs per visit (by default).
269 forced_src_schema=SimpleMapping(SourceCatalogPersistenceType,
270 template="{dataset}{ext}", keys={}),
271 truth=
SimpleMapping(SimpleCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
272 keys={
"tract": int}),
273 simsrc=
RawMapping(SimpleCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
274 keys={
"tract": int}),
275 observations=
SimpleMapping(ExposureCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
276 keys={
"tract": int}),
277 ccdExposureId=
RawMapping(BypassPersistenceType),
279 deepCoaddId=
SkyMapping(BypassPersistenceType),
282 deepMergedCoaddId=
SkyMapping(BypassPersistenceType),
284 deepCoadd_skyMap=
SimpleMapping(SkyMapPersistenceType, template=
"{dataset}{ext}", keys={}),
285 deepCoadd=
SkyMapping(ExposurePersistenceType),
286 deepCoadd_filterLabel=
SkyMapping(ExposurePersistenceType),
287 deepCoaddPsfMatched=
SkyMapping(ExposurePersistenceType),
288 deepCoadd_calexp=
SkyMapping(ExposurePersistenceType),
289 deepCoadd_calexp_background=
SkyMapping(CatalogPersistenceType),
290 deepCoadd_icSrc=
SkyMapping(SourceCatalogPersistenceType),
291 deepCoadd_icSrc_schema=
SimpleMapping(SourceCatalogPersistenceType,
292 template=
"{dataset}{ext}", keys={}),
293 deepCoadd_src=
SkyMapping(SourceCatalogPersistenceType),
294 deepCoadd_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
295 template=
"{dataset}{ext}", keys={}),
296 deepCoadd_peak_schema=
SimpleMapping(PeakCatalogPersistenceType,
297 template=
"{dataset}{ext}", keys={}),
298 deepCoadd_ref=
SkyMapping(SourceCatalogPersistenceType),
299 deepCoadd_ref_schema=
SimpleMapping(SourceCatalogPersistenceType,
300 template=
"{dataset}{ext}", keys={}),
301 deepCoadd_det=
SkyMapping(SourceCatalogPersistenceType),
302 deepCoadd_det_schema=
SimpleMapping(SourceCatalogPersistenceType,
303 template=
"{dataset}{ext}", keys={}),
304 deepCoadd_mergeDet=
SkyMapping(SourceCatalogPersistenceType),
305 deepCoadd_mergeDet_schema=
SimpleMapping(SourceCatalogPersistenceType,
306 template=
"{dataset}{ext}", keys={}),
307 deepCoadd_deblendedFlux=
SkyMapping(SourceCatalogPersistenceType),
308 deepCoadd_deblendedFlux_schema=
SimpleMapping(SourceCatalogPersistenceType,
309 template=
"{dataset}{ext}", keys={}),
310 deepCoadd_deblendedModel=
SkyMapping(SourceCatalogPersistenceType),
311 deepCoadd_deblendedModel_schema=
SimpleMapping(SourceCatalogPersistenceType,
312 template=
"{dataset}{ext}", keys={}),
313 deepCoadd_meas=
SkyMapping(SourceCatalogPersistenceType),
314 deepCoadd_meas_schema=
SimpleMapping(SourceCatalogPersistenceType,
315 template=
"{dataset}{ext}", keys={}),
316 deepCoadd_forced_src=
SkyMapping(SourceCatalogPersistenceType),
317 deepCoadd_forced_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
318 template=
"{dataset}{ext}", keys={}),
319 deepCoadd_mock=
SkyMapping(ExposurePersistenceType),
320 deepCoaddPsfMatched_mock=
SkyMapping(ExposurePersistenceType),
322 deepCoadd_directWarp_mock=
TempExpMapping(ExposurePersistenceType),
324 deepCoadd_psfMatchedWarp_mock=
TempExpMapping(ExposurePersistenceType),
333 self.
storagestorage = lsst.daf.persistence.Storage.makeFromURI(root)
334 super(SimpleMapper, self).
__init__(**kwargs)
342 self.
filterLabelfilterLabel = afwImage.FilterLabel(band=
"r", physical=
"r")
349 if datasetType
is None:
352 keyDict = self.
mappingsmappings[datasetType].keys
353 if level
is not None and level
in self.
levelslevels:
354 keyDict = dict(keyDict)
355 for lev
in self.
levelslevels[level]:
361 filenames = os.listdir(self.
rootroot)
362 rawRegex = re.compile(
r"(?P<dataset>\w+)-(?P<visit>\d+)-(?P<ccd>\d).*")
364 for filename
in filenames:
365 m = rawRegex.match(filename)
368 index = self.
indexindex.setdefault(m.group(
'dataset'), dict(ccd={
None: []}, visit={
None: []}))
369 visit = int(m.group(
'visit'))
370 ccd = int(m.group(
'ccd'))
371 d1 = dict(visit=visit, ccd=ccd)
372 d2 = dict(visit=visit)
373 index[
'ccd'].setdefault(visit, []).append(d1)
374 index[
'ccd'][
None].append(d1)
375 index[
'visit'][visit] = [d2]
376 index[
'visit'][
None].append(d1)
385 return lsst.daf.persistence.ButlerLocation(
386 "lsst.afw.cameraGeom.Camera",
"Camera",
None, [], dataId, mapper=self, storage=self.
storagestorage
390 detectorId = dataId[
"ccd"]
391 detector = self.
cameracamera[detectorId]
392 item.setDetector(detector)
396 def _computeCcdExposureId(self, dataId):
397 return int(dataId[
"visit"]) * 10 + int(dataId[
"ccd"])
399 def _computeCoaddId(self, dataId):
402 tract = int(dataId[
'tract'])
403 if tract < 0
or tract >= 128:
404 raise RuntimeError(
'tract not in range [0,128)')
405 patchX, patchY = (int(c)
for c
in dataId[
'patch'].split(
','))
406 for p
in (patchX, patchY):
407 if p < 0
or p >= 2**13:
408 raise RuntimeError(
'patch component not in range [0, 8192)')
409 return (tract * 2**13 + patchX) * 2**13 + patchY
413 return dict(visit=(int(ccdExposureId) // 10), ccd=(int(ccdExposureId) % 10))
425 return 1 + 7 + 13*2 + 3
434 return 1 + 7 + 13*2 + 3
437 """To return a useful filterLabel for MergeDetectionsTask."""
438 return afwImage.FilterLabel(band=self.
filterLabelfilterLabel.bandLabel)
447 radialDistortion=0.925,
451 @param[
in] nx: number of detectors
in x
452 @param[
in] ny: number of detectors
in y
453 @param[
in] sizeX: detector size
in x (pixels)
454 @param[
in] sizeY: detector size
in y (pixels)
455 @param[
in] gapX: gap between detectors
in x (mm)
456 @param[
in] gapY: gap between detectors
in y (mm)
457 @param[
in] pixelSize: pixel size (mm) (a float)
458 @param[
in] plateScale: plate scale
in arcsec/mm; 20.0
is for LSST
459 @param[
in] radialDistortion: radial distortion,
in mm/rad^2
460 (the r^3 coefficient of the radial distortion polynomial
461 that converts FIELD_ANGLE
in radians to FOCAL_PLANE
in mm);
462 0.925
is the value Dave Monet measured
for lsstSim data
464 Each detector will have one amplifier (
with no raw information).
467 radialDistortCoeffs = [0.0, 1.0/pScaleRad, 0.0, radialDistortion/pScaleRad]
476 cY = (iY - 0.5 * (nY - 1)) * (pixelSize * sizeY + gapY)
478 cX = (iX - 0.5 * (nX - 1)) * (pixelSize * sizeY + gapX)
480 detectorName =
"detector %d,%d" % (iX, iY)
482 detectorBuilder = cameraBuilder.add(detectorName, detectorId)
483 detectorBuilder.setSerial(detectorName +
" serial")
484 detectorBuilder.setBBox(ccdBBox)
490 ampBuilder.setName(ampName)
491 ampBuilder.setBBox(ccdBBox)
492 ampBuilder.setGain(1.0)
493 ampBuilder.setReadNoise(5.0)
495 detectorBuilder.append(ampBuilder)
499 cameraBuilder.setTransformFromFocalPlaneTo(lsst.afw.cameraGeom.FIELD_ANGLE, focalPlaneToFieldAngle)
500 return cameraBuilder.finish()
505 Create a data repository for SimpleMapper
and return a butler
for it.
507 Clobbers anything already
in the given path.
509 if os.path.exists(root):
512 with open(os.path.join(root,
"_mapper"),
"w")
as f:
513 f.write(
"lsst.pipe.tasks.mocks.SimpleMapper\n")
514 return lsst.daf.persistence.Butler(root=root)
def makeButlerLocation(cls, path, dataId, mapper, suffix=None, storage=None)
def makeButlerLocation(cls, path, dataId, mapper, suffix=None, storage=None)
def makeButlerLocation(cls, path, dataId, mapper, suffix=None, storage=None)
def canStandardize(self, datasetType)
def query(self, dataset, index, level, format, dataId)
def bypass_deepMergedCoaddId_bits(self, datasetType, pythonType, location, dataId)
def bypass_deepMergedCoaddId(self, datasetType, pythonType, location, dataId)
def getDefaultLevel(self)
def bypass_ccdExposureId(self, datasetType, pythonType, location, dataId)
def _computeCcdExposureId(self, dataId)
def bypass_deepCoadd_filterLabel(self, *args, **kwargs)
def bypass_deepCoadd_band(self, datasetType, pythonType, location, dataId)
def getKeys(self, datasetType, level)
def std_calexp(self, item, dataId)
def map_camera(self, dataId, write=False)
def __init__(self, root, **kwargs)
def bypass_camera(self, datasetType, pythonType, location, dataId)
def splitCcdExposureId(ccdExposureId)
def bypass_deepCoaddId_bits(self, datasetType, pythonType, location, dataId)
def bypass_ccdExposureId_bits(self, datasetType, pythonType, location, dataId)
def bypass_deepCoaddId(self, datasetType, pythonType, location, dataId)
def _computeCoaddId(self, dataId)
def map(self, dataset, root, dataId, mapper, suffix=None, storage=None)
def __init__(self, persistence, template=None, keys=None)
std::shared_ptr< TransformPoint2ToPoint2 > makeRadialTransform(std::vector< double > const &coeffs)
constexpr double arcsecToRad(double x) noexcept
def makeSimpleCamera(nX, nY, sizeX, sizeY, gapX, gapY, pixelSize=1.0, plateScale=20.0, radialDistortion=0.925)