23 """Mapper and cameraGeom definition for extremely simple mock data. 25 SimpleMapper inherits directly from Mapper, not CameraMapper. This means 26 we can avoid any problems with paf files at the expense of reimplementing 27 some parts of CameraMapper here. Jim is not sure this was the best 28 possible approach, but it gave him an opportunity to play around with 29 prototyping a future paf-free mapper class, and it does everything it 30 needs to do right now. 32 from __future__
import absolute_import, division, print_function
33 from builtins
import map
34 from builtins
import range
35 from builtins
import object
46 from future.utils
import with_metaclass
48 __all__ = (
"SimpleMapper",
"makeSimpleCamera",
"makeDataRepo")
52 """Base class of a hierarchy used by SimpleMapper to defined different kinds of types of objects 55 PersistenceType objects are never instantiated; only the type objects are used (we needed a 56 simple singleton struct that could be inherited, which is exactly what a Python type is). 66 """Method called by SimpleMapping to implement a map_ method.""" 67 return lsst.daf.persistence.ButlerLocation(cls.
python, cls.
cpp, cls.
storage, [path], dataId,
76 """Persistence type for things that don't actually use daf_persistence. 79 python =
"lsst.daf.base.PropertySet" 83 """Method called by SimpleMapping to implement a map_ method; overridden to not use the path.""" 84 return lsst.daf.persistence.ButlerLocation(cls.
python, cls.
cpp, cls.
storage, [], dataId,
85 mapper=mapper, storage=storage)
89 """Persistence type of Exposure images. 92 python =
"lsst.afw.image.ExposureF" 94 storage =
"FitsStorage" 100 """Method called by SimpleMapping to implement a map_ method; overridden to support subimages.""" 102 loc = super(ExposurePersistenceType, cls).
makeButlerLocation(path, dataId, mapper, suffix=
None,
104 elif suffix ==
"_sub":
105 subId = dataId.copy()
106 bbox = subId.pop(
'bbox')
107 loc = super(ExposurePersistenceType, cls).
makeButlerLocation(path, subId, mapper, suffix=
None,
109 loc.additionalData.set(
'llcX', bbox.getMinX())
110 loc.additionalData.set(
'llcY', bbox.getMinY())
111 loc.additionalData.set(
'width', bbox.getWidth())
112 loc.additionalData.set(
'height', bbox.getHeight())
113 if 'imageOrigin' in dataId:
114 loc.additionalData.set(
'imageOrigin',
115 dataId[
'imageOrigin'])
120 python =
"lsst.skymap.BaseSkyMap" 121 storage =
"PickleStorage" 126 python =
"lsst.afw.table.BaseCatalog" 128 storage =
"FitsCatalogStorage" 133 python =
"lsst.afw.table.SimpleCatalog" 134 cpp =
"SimpleCatalog" 138 python =
"lsst.afw.table.SourceCatalog" 139 cpp =
"SourceCatalog" 143 python =
"lsst.afw.table.ExposureCatalog" 144 cpp =
"ExposureCatalog" 148 python =
"lsst.afw.detection.PeakCatalog" 153 """Mapping object used to implement SimpleMapper, similar in intent to lsst.daf.peristence.Mapping. 159 def __init__(self, persistence, template=None, keys=None):
161 if template
is not None:
166 def map(self, dataset, root, dataId, mapper, suffix=None, storage=None):
171 return self.
persistence.makeButlerLocation(path, dataId, suffix=suffix, mapper=mapper,
176 """Mapping for dataset types that are organized the same way as raw data (i.e. by CCD).""" 178 template =
"{dataset}-{visit:04d}-{ccd:01d}{ext}" 179 keys = dict(visit=int, ccd=int)
181 def query(self, dataset, index, level, format, dataId):
182 dictList = index[dataset][level]
183 results = [list(d.values())
for d
in dictList[dataId.get(level,
None)]]
188 """Mapping for dataset types that are organized according to a SkyMap subdivision of the sky.""" 190 template =
"{dataset}-{filter}-{tract:02d}-{patch}{ext}" 191 keys = dict(filter=str, tract=int, patch=str)
195 """Mapping for CoaddTempExp datasets.""" 197 template =
"{dataset}-{tract:02d}-{patch}-{visit:04d}{ext}" 198 keys = dict(tract=int, patch=str, visit=int)
202 """Mapping for forced_src datasets.""" 204 template =
"{dataset}-{tract:02d}-{visit:04d}-{ccd:01d}{ext}" 205 keys = dict(tract=int, ccd=int, visit=int)
209 """Metaclass for SimpleMapper that creates map_ and query_ methods for everything found in the 210 'mappings' class variable. 214 def _makeMapClosure(dataset, mapping, suffix=None):
215 def mapClosure(self, dataId, write=False):
216 return mapping.map(dataset, self.root, dataId, self, suffix=suffix, storage=self.storage)
220 def _makeQueryClosure(dataset, mapping):
221 def queryClosure(self, level, format, dataId):
222 return mapping.query(dataset, self.index, level, format, dataId)
226 type.__init__(cls, name, bases, dict_)
228 for dataset, mapping
in cls.mappings.items():
229 setattr(cls,
"map_" + dataset, MapperMeta._makeMapClosure(dataset, mapping, suffix=
None))
230 for suffix
in mapping.persistence.suffixes:
231 setattr(cls,
"map_" + dataset + suffix,
232 MapperMeta._makeMapClosure(dataset, mapping, suffix=suffix))
233 if hasattr(mapping,
"query"):
234 setattr(cls,
"query_" + dataset, MapperMeta._makeQueryClosure(dataset, mapping))
235 cls.
keyDict.update(mapping.keys)
240 An extremely simple mapper for an imaginary camera for use in integration tests. 242 As SimpleMapper does not inherit from obs.base.CameraMapper, it does not 243 use a policy file to set mappings or a registry; all the information is here 244 (in the map_* and query_* methods). 246 The imaginary camera's raw data format has only 'visit' and 'ccd' keys, with 247 two CCDs per visit (by default). 253 forced_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
254 template=
"{dataset}{ext}", keys={}),
255 truth=
SimpleMapping(SimpleCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
256 keys={
"tract": int}),
257 simsrc=
RawMapping(SimpleCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
258 keys={
"tract": int}),
259 observations=
SimpleMapping(ExposureCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
260 keys={
"tract": int}),
261 ccdExposureId=
RawMapping(BypassPersistenceType),
263 deepCoaddId=
SkyMapping(BypassPersistenceType),
265 deepMergedCoaddId=
SkyMapping(BypassPersistenceType),
267 deepCoadd_skyMap=
SimpleMapping(SkyMapPersistenceType, template=
"{dataset}{ext}", keys={}),
268 deepCoadd=
SkyMapping(ExposurePersistenceType),
269 deepCoaddPsfMatched=
SkyMapping(ExposurePersistenceType),
270 deepCoadd_calexp=
SkyMapping(ExposurePersistenceType),
271 deepCoadd_calexp_background=
SkyMapping(CatalogPersistenceType),
272 deepCoadd_icSrc=
SkyMapping(SourceCatalogPersistenceType),
273 deepCoadd_icSrc_schema=
SimpleMapping(SourceCatalogPersistenceType,
274 template=
"{dataset}{ext}", keys={}),
275 deepCoadd_src=
SkyMapping(SourceCatalogPersistenceType),
276 deepCoadd_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
277 template=
"{dataset}{ext}", keys={}),
278 deepCoadd_peak_schema=
SimpleMapping(PeakCatalogPersistenceType,
279 template=
"{dataset}{ext}", keys={}),
280 deepCoadd_ref=
SkyMapping(SourceCatalogPersistenceType),
281 deepCoadd_ref_schema=
SimpleMapping(SourceCatalogPersistenceType,
282 template=
"{dataset}{ext}", keys={}),
283 deepCoadd_det=
SkyMapping(SourceCatalogPersistenceType),
284 deepCoadd_det_schema=
SimpleMapping(SourceCatalogPersistenceType,
285 template=
"{dataset}{ext}", keys={}),
286 deepCoadd_mergeDet=
SkyMapping(SourceCatalogPersistenceType),
287 deepCoadd_mergeDet_schema=
SimpleMapping(SourceCatalogPersistenceType,
288 template=
"{dataset}{ext}", keys={}),
289 deepCoadd_meas=
SkyMapping(SourceCatalogPersistenceType),
290 deepCoadd_meas_schema=
SimpleMapping(SourceCatalogPersistenceType,
291 template=
"{dataset}{ext}", keys={}),
292 deepCoadd_forced_src=
SkyMapping(SourceCatalogPersistenceType),
293 deepCoadd_forced_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
294 template=
"{dataset}{ext}", keys={}),
295 deepCoadd_mock=
SkyMapping(ExposurePersistenceType),
296 deepCoaddPsfMatched_mock=
SkyMapping(ExposurePersistenceType),
298 deepCoadd_directWarp_mock=
TempExpMapping(ExposurePersistenceType),
300 deepCoadd_psfMatchedWarp_mock=
TempExpMapping(ExposurePersistenceType),
309 self.
storage = lsst.daf.persistence.Storage.makeFromURI(root)
310 super(SimpleMapper, self).
__init__(**kwargs)
313 afwImageUtils.defineFilter(
'r', 619.42) 318 def getKeys(self, datasetType, level):
319 if datasetType
is None:
322 keyDict = self.
mappings[datasetType].keys
323 if level
is not None and level
in self.
levels:
324 keyDict = dict(keyDict)
325 for l
in self.
levels[level]:
331 filenames = os.listdir(self.
root)
332 rawRegex = re.compile(
r"(?P<dataset>\w+)-(?P<visit>\d+)-(?P<ccd>\d).*")
334 for filename
in filenames:
335 m = rawRegex.match(filename)
338 index = self.
index.setdefault(m.group(
'dataset'), dict(ccd={
None: []}, visit={
None: []}))
339 visit = int(m.group(
'visit'))
340 ccd = int(m.group(
'ccd'))
341 d1 = dict(visit=visit, ccd=ccd)
342 d2 = dict(visit=visit)
343 index[
'ccd'].setdefault(visit, []).append(d1)
344 index[
'ccd'][
None].append(d1)
345 index[
'visit'][visit] = [d2]
346 index[
'visit'][
None].append(d1)
355 return lsst.daf.persistence.ButlerLocation(
356 "lsst.afw.cameraGeom.Camera",
"Camera",
None, [], dataId, mapper=self, storage=self.
storage 360 detectorId = dataId[
"ccd"]
361 detector = self.
camera[detectorId]
362 item.setDetector(detector)
363 item.setFilter(afwImage.Filter(
"r")) 366 def _computeCcdExposureId(self, dataId):
367 return int(dataId[
"visit"]) * 10 + int(dataId[
"ccd"])
369 def _computeCoaddId(self, dataId):
372 tract = int(dataId[
'tract'])
373 if tract < 0
or tract >= 128:
374 raise RuntimeError(
'tract not in range [0,128)')
375 patchX, patchY = (int(c)
for c
in dataId[
'patch'].split(
','))
376 for p
in (patchX, patchY):
377 if p < 0
or p >= 2**13:
378 raise RuntimeError(
'patch component not in range [0, 8192)')
379 return (tract * 2**13 + patchX) * 2**13 + patchY
382 return dict(visit=(int(ccdExposureId) // 10), ccd=(int(ccdExposureId) % 10))
394 return 1 + 7 + 13*2 + 3
400 return 1 + 7 + 13*2 + 3
409 radialDistortion=0.925,
413 @param[in] nx: number of detectors in x 414 @param[in] ny: number of detectors in y 415 @param[in] sizeX: detector size in x (pixels) 416 @param[in] sizeY: detector size in y (pixels) 417 @param[in] gapX: gap between detectors in x (mm) 418 @param[in] gapY: gap between detectors in y (mm) 419 @param[in] pixelSize: pixel size (mm) (a float) 420 @param[in] plateScale: plate scale in arcsec/mm; 20.0 is for LSST 421 @param[in] radialDistortion: radial distortion, in mm/rad^2 422 (the r^3 coefficient of the radial distortion polynomial 423 that converts FIELD_ANGLE in radians to FOCAL_PLANE in mm); 424 0.925 is the value Dave Monet measured for lsstSim data 426 Each detector will have one amplifier (with no raw information). 429 radialDistortCoeffs = [0.0, 1.0/pScaleRad, 0.0, radialDistortion/pScaleRad]
431 nativeSys = lsst.afw.cameraGeom.FOCAL_PLANE
433 lsst.afw.cameraGeom.FIELD_ANGLE: focalPlaneToFieldAngle,
440 cY = (iY - 0.5 * (nY - 1)) * (pixelSize * sizeY + gapY)
442 cX = (iX - 0.5 * (nX - 1)) * (pixelSize * sizeY + gapX)
444 detectorName =
"detector %d,%d" % (iX, iY)
445 detectorId = len(detectorList) + 1
449 serial=detectorName +
" serial",
451 ampExtent=ccdBBox.getDimensions(),
455 plateScale=plateScale,
456 radialDistortion=radialDistortion,
459 return lsst.afw.cameraGeom.Camera(
460 name=
"Simple Camera",
461 detectorList=detectorList,
462 transformMap=transformMap,
468 Create a data repository for SimpleMapper and return a butler for it. 470 Clobbers anything already in the given path. 472 if os.path.exists(root):
475 with open(os.path.join(root,
"_mapper"),
"w")
as f:
476 f.write(
"lsst.pipe.tasks.mocks.SimpleMapper\n")
477 return lsst.daf.persistence.Butler(root=root)
def canStandardize(self, datasetType)
def map_camera(self, dataId, write=False)
def splitCcdExposureId(ccdExposureId)
def bypass_camera(self, datasetType, pythonType, location, dataId)
std::shared_ptr< TransformPoint2ToPoint2 > makeRadialTransform(std::vector< double > const &forwardCoeffs, std::vector< double > const &inverseCoeffs)
def __init__(self, persistence, template=None, keys=None)
def _computeCcdExposureId(self, dataId)
def makeSimpleCamera(nX, nY, sizeX, sizeY, gapX, gapY, pixelSize=1.0, plateScale=20.0, radialDistortion=0.925)
def bypass_ccdExposureId_bits(self, datasetType, pythonType, location, dataId)
def map(self, dataset, root, dataId, mapper, suffix=None, storage=None)
def getDefaultLevel(self)
def _computeCoaddId(self, dataId)
def __init__(self, root, kwargs)
def bypass_deepMergedCoaddId(self, datasetType, pythonType, location, dataId)
def makeButlerLocation(cls, path, dataId, mapper, suffix=None, storage=None)
def bypass_deepCoaddId(self, datasetType, pythonType, location, dataId)
def std_calexp(self, item, dataId)
def bypass_ccdExposureId(self, datasetType, pythonType, location, dataId)
def bypass_deepMergedCoaddId_bits(self, datasetType, pythonType, location, dataId)
constexpr double arcsecToRad(double x) noexcept
def query(self, dataset, index, level, format, dataId)
def bypass_deepCoaddId_bits(self, datasetType, pythonType, location, dataId)
def makeButlerLocation(cls, path, dataId, mapper, suffix=None, storage=None)
def makeButlerLocation(cls, path, dataId, mapper, suffix=None, storage=None)