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 builtins
import map
33 from builtins
import range
34 from builtins
import object
44 from future.utils
import with_metaclass
46 __all__ = (
"SimpleMapper",
"makeSimpleCamera",
"makeDataRepo")
50 """Base class of a hierarchy used by SimpleMapper to defined different kinds of types of objects
53 PersistenceType objects are never instantiated; only the type objects are used (we needed a
54 simple singleton struct that could be inherited, which is exactly what a Python type is).
64 """Method called by SimpleMapping to implement a map_ method."""
65 return lsst.daf.persistence.ButlerLocation(cls.python, cls.cpp, cls.storage, [path], dataId,
73 """Persistence type for things that don't actually use daf_persistence.
76 python =
"lsst.daf.base.PropertySet"
80 """Method called by SimpleMapping to implement a map_ method; overridden to not use the path."""
81 return lsst.daf.persistence.ButlerLocation(cls.python, cls.cpp, cls.storage, [], dataId,
86 """Persistence type of Exposure images.
89 python =
"lsst.afw.image.ExposureF"
91 storage =
"FitsStorage"
97 """Method called by SimpleMapping to implement a map_ method; overridden to support subimages."""
99 loc = super(ExposurePersistenceType, cls).
makeButlerLocation(path, dataId, mapper, suffix=
None)
100 elif suffix ==
"_sub":
101 subId = dataId.copy()
102 bbox = subId.pop(
'bbox')
103 loc = super(ExposurePersistenceType, cls).
makeButlerLocation(path, subId, mapper, suffix=
None)
104 loc.additionalData.set(
'llcX', bbox.getMinX())
105 loc.additionalData.set(
'llcY', bbox.getMinY())
106 loc.additionalData.set(
'width', bbox.getWidth())
107 loc.additionalData.set(
'height', bbox.getHeight())
108 if 'imageOrigin' in dataId:
109 loc.additionalData.set(
'imageOrigin',
110 dataId[
'imageOrigin'])
115 python =
"lsst.skymap.BaseSkyMap"
116 storage =
"PickleStorage"
121 python =
"lsst.afw.table.BaseCatalog"
123 storage =
"FitsCatalogStorage"
128 python =
"lsst.afw.table.SimpleCatalog"
129 cpp =
"SimpleCatalog"
133 python =
"lsst.afw.table.SourceCatalog"
134 cpp =
"SourceCatalog"
138 python =
"lsst.afw.table.ExposureCatalog"
139 cpp =
"ExposureCatalog"
143 python =
"lsst.afw.detection.PeakCatalog"
148 """Mapping object used to implement SimpleMapper, similar in intent to lsst.daf.peristence.Mapping.
154 def __init__(self, persistence, template=None, keys=None):
156 if template
is not None:
161 def map(self, dataset, root, dataId, mapper, suffix=None):
163 path = os.path.join(root, self.template.format(dataset=dataset, ext=self.persistence.ext,
167 return self.persistence.makeButlerLocation(path, dataId, suffix=suffix, mapper=mapper)
171 """Mapping for dataset types that are organized the same way as raw data (i.e. by CCD)."""
173 template =
"{dataset}-{visit:04d}-{ccd:01d}{ext}"
174 keys = dict(visit=int, ccd=int)
176 def query(self, dataset, index, level, format, dataId):
177 dictList = index[dataset][level]
178 results = [list(d.values())
for d
in dictList[dataId.get(level,
None)]]
183 """Mapping for dataset types that are organized according to a SkyMap subdivision of the sky."""
185 template =
"{dataset}-{filter}-{tract:02d}-{patch}{ext}"
186 keys = dict(filter=str, tract=int, patch=str)
190 """Mapping for CoaddTempExp datasets."""
192 template =
"{dataset}-{tract:02d}-{patch}-{visit:04d}{ext}"
193 keys = dict(tract=int, patch=str, visit=int)
197 """Mapping for forced_src datasets."""
199 template =
"{dataset}-{tract:02d}-{visit:04d}-{ccd:01d}{ext}"
200 keys = dict(tract=int, ccd=int, visit=int)
204 """Metaclass for SimpleMapper that creates map_ and query_ methods for everything found in the
205 'mappings' class variable.
210 def mapClosure(self, dataId, write=False):
211 return mapping.map(dataset, self.root, dataId, self, suffix=suffix)
216 def queryClosure(self, level, format, dataId):
217 return mapping.query(dataset, self.index, level, format, dataId)
221 type.__init__(cls, name, bases, dict_)
223 for dataset, mapping
in cls.mappings.items():
224 setattr(cls,
"map_" + dataset, MapperMeta._makeMapClosure(dataset, mapping, suffix=
None))
225 for suffix
in mapping.persistence.suffixes:
226 setattr(cls,
"map_" + dataset + suffix,
227 MapperMeta._makeMapClosure(dataset, mapping, suffix=suffix))
228 if hasattr(mapping,
"query"):
229 setattr(cls,
"query_" + dataset, MapperMeta._makeQueryClosure(dataset, mapping))
230 cls.keyDict.update(mapping.keys)
235 An extremely simple mapper for an imaginary camera for use in integration tests.
237 As SimpleMapper does not inherit from obs.base.CameraMapper, it does not
238 use a policy file to set mappings or a registry; all the information is here
239 (in the map_* and query_* methods).
241 The imaginary camera's raw data format has only 'visit' and 'ccd' keys, with
242 two CCDs per visit (by default).
248 forced_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
249 template=
"{dataset}{ext}", keys={}),
250 truth=
SimpleMapping(SimpleCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
251 keys={
"tract": int}),
252 simsrc=
RawMapping(SimpleCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
253 keys={
"tract": int}),
254 observations=
SimpleMapping(ExposureCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
255 keys={
"tract": int}),
256 ccdExposureId=
RawMapping(BypassPersistenceType),
258 deepCoaddId=
SkyMapping(BypassPersistenceType),
260 deepMergedCoaddId=
SkyMapping(BypassPersistenceType),
262 deepCoadd_skyMap=
SimpleMapping(SkyMapPersistenceType, template=
"{dataset}{ext}", keys={}),
263 deepCoadd=
SkyMapping(ExposurePersistenceType),
264 deepCoadd_calexp=
SkyMapping(ExposurePersistenceType),
265 deepCoadd_calexp_background=
SkyMapping(CatalogPersistenceType),
266 deepCoadd_icSrc=
SkyMapping(SourceCatalogPersistenceType),
267 deepCoadd_icSrc_schema=
SimpleMapping(SourceCatalogPersistenceType,
268 template=
"{dataset}{ext}", keys={}),
269 deepCoadd_src=
SkyMapping(SourceCatalogPersistenceType),
270 deepCoadd_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
271 template=
"{dataset}{ext}", keys={}),
272 deepCoadd_peak_schema=
SimpleMapping(PeakCatalogPersistenceType,
273 template=
"{dataset}{ext}", keys={}),
274 deepCoadd_ref=
SkyMapping(SourceCatalogPersistenceType),
275 deepCoadd_ref_schema=
SimpleMapping(SourceCatalogPersistenceType,
276 template=
"{dataset}{ext}", keys={}),
277 deepCoadd_det=
SkyMapping(SourceCatalogPersistenceType),
278 deepCoadd_det_schema=
SimpleMapping(SourceCatalogPersistenceType,
279 template=
"{dataset}{ext}", keys={}),
280 deepCoadd_mergeDet=
SkyMapping(SourceCatalogPersistenceType),
281 deepCoadd_mergeDet_schema=
SimpleMapping(SourceCatalogPersistenceType,
282 template=
"{dataset}{ext}", keys={}),
283 deepCoadd_meas=
SkyMapping(SourceCatalogPersistenceType),
284 deepCoadd_meas_schema=
SimpleMapping(SourceCatalogPersistenceType,
285 template=
"{dataset}{ext}", keys={}),
286 deepCoadd_forced_src=
SkyMapping(SourceCatalogPersistenceType),
287 deepCoadd_forced_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
288 template=
"{dataset}{ext}", keys={}),
289 deepCoadd_mock=
SkyMapping(ExposurePersistenceType),
300 super(SimpleMapper, self).
__init__()
303 afwImageUtils.defineFilter(
'r', 619.42)
308 def getKeys(self, datasetType, level):
309 if datasetType
is None:
310 keyDict = self.keyDict
312 keyDict = self.
mappings[datasetType].keys
313 if level
is not None and level
in self.
levels:
314 keyDict = dict(keyDict)
315 for l
in self.
levels[level]:
321 filenames = os.listdir(self.
root)
322 rawRegex = re.compile(
r"(?P<dataset>\w+)-(?P<visit>\d+)-(?P<ccd>\d).*")
324 for filename
in filenames:
325 m = rawRegex.match(filename)
328 index = self.index.setdefault(m.group(
'dataset'), dict(ccd={
None: []}, visit={
None: []}))
329 visit = int(m.group(
'visit'))
330 ccd = int(m.group(
'ccd'))
331 d1 = dict(visit=visit, ccd=ccd)
332 d2 = dict(visit=visit)
333 index[
'ccd'].setdefault(visit, []).append(d1)
334 index[
'ccd'][
None].append(d1)
335 index[
'visit'][visit] = [d2]
336 index[
'visit'][
None].append(d1)
345 return lsst.daf.persistence.ButlerLocation(
346 "lsst.afw.cameraGeom.Camera",
"Camera",
None, [], dataId, mapper=self
350 detectorId = dataId[
"ccd"]
351 detector = self.
camera[detectorId]
352 item.setDetector(detector)
356 return int(dataId[
"visit"]) * 10 + int(dataId[
"ccd"])
361 tract = int(dataId[
'tract'])
362 if tract < 0
or tract >= 128:
363 raise RuntimeError(
'tract not in range [0,128)')
364 patchX, patchY = (int(c)
for c
in dataId[
'patch'].split(
','))
365 for p
in (patchX, patchY):
366 if p < 0
or p >= 2**13:
367 raise RuntimeError(
'patch component not in range [0, 8192)')
368 return (tract * 2**13 + patchX) * 2**13 + patchY
371 return dict(visit=(int(ccdExposureId) // 10), ccd=(int(ccdExposureId) % 10))
383 return 1 + 7 + 13*2 + 3
389 return 1 + 7 + 13*2 + 3
398 radialDistortion=0.925,
402 @param[in] nx: number of detectors in x
403 @param[in] ny: number of detectors in y
404 @param[in] sizeX: detector size in x (pixels)
405 @param[in] sizeY: detector size in y (pixels)
406 @param[in] gapX: gap between detectors in x (mm)
407 @param[in] gapY: gap between detectors in y (mm)
408 @param[in] pixelSize: pixel size (mm) (a float)
409 @param[in] plateScale: plate scale in arcsec/mm; 20.0 is for LSST
410 @param[in] radialDistortion: radial distortion, in mm/rad^2
411 (the r^3 coefficient of the radial distortion polynomial
412 that converts PUPIL in radians to FOCAL_PLANE in mm);
413 0.925 is the value Dave Monet measured for lsstSim data
415 Each detector will have one amplifier (with no raw information).
418 radialDistortCoeffs = [0.0, 1.0/pScaleRad, 0.0, radialDistortion/pScaleRad]
420 nativeSys = lsst.afw.cameraGeom.FOCAL_PLANE
422 lsst.afw.cameraGeom.PUPIL: focalPlaneToPupil,
429 cY = (iY - 0.5 * (nY - 1)) * (pixelSize * sizeY + gapY)
431 cX = (iX - 0.5 * (nX - 1)) * (pixelSize * sizeY + gapX)
433 detectorName =
"detector %d,%d" % (iX, iY)
434 detectorId = len(detectorList) + 1
438 serial=detectorName +
" serial",
440 ampExtent=ccdBBox.getDimensions(),
444 plateScale=plateScale,
445 radialDistortion=radialDistortion,
448 return lsst.afw.cameraGeom.Camera(
449 name=
"Simple Camera",
450 detectorList=detectorList,
451 transformMap=transformMap,
457 Create a data repository for SimpleMapper and return a butler for it.
459 Clobbers anything already in the given path.
461 if os.path.exists(root):
464 with open(os.path.join(root,
"_mapper"),
"w")
as f:
465 f.write(
"lsst.pipe.tasks.mocks.SimpleMapper\n")
466 return lsst.daf.persistence.Butler(root=root)
A Detector and the data used to construct it.
def bypass_ccdExposureId_bits
def bypass_deepMergedCoaddId
An integer coordinate rectangle.
Describe a detector's orientation in the focal plane.
double arcsecToRad(double x)
def bypass_deepMergedCoaddId_bits
def bypass_deepCoaddId_bits
def _computeCcdExposureId