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. 
   43 __all__ = (
"SimpleMapper", 
"makeSimpleCamera", 
"makeDataRepo")
 
   47     """Base class of a hierarchy used by SimpleMapper to defined different kinds of types of objects 
   50     PersistenceType objects are never instantiated; only the type objects are used (we needed a 
   51     simple singleton struct that could be inherited, which is exactly what a Python type is). 
   61         """Method called by SimpleMapping to implement a map_ method.""" 
   71     """Persistence type for things that don't actually use daf_persistence. 
   74     python = 
"lsst.daf.base.PropertySet"   
   78         """Method called by SimpleMapping to implement a map_ method; overridden to not use the path.""" 
   80                                                    mapper=mapper, storage=storage)
 
   84     """Persistence type of Exposure images. 
   87     python = 
"lsst.afw.image.ExposureF" 
   89     storage = 
"FitsStorage" 
   95         """Method called by SimpleMapping to implement a map_ method; overridden to support subimages.""" 
   97             loc = super(ExposurePersistenceType, cls).
makeButlerLocation(path, dataId, mapper, suffix=
None,
 
  105                 "compression.algorithm": 
"NONE",
 
  106                 "compression.columns": 0,
 
  107                 "compression.rows": 0,
 
  108                 "compression.quantizeLevel": 0.0,
 
  109                 "scaling.algorithm": 
"NONE",
 
  110                 "scaling.bzero": 0.0,
 
  111                 "scaling.bscale": 0.0,
 
  113                 "scaling.quantizeLevel": 0.0,
 
  114                 "scaling.quantizePad": 0.0,
 
  115                 "scaling.fuzz": 
False,
 
  118             for prefix 
in (
"image", 
"mask", 
"variance"):
 
  119                 for k, v 
in options.items():
 
  120                     loc.additionalData.set(
"{}.{}".
format(prefix, k), v)
 
  121         elif suffix == 
"_sub":
 
  122             subId = dataId.copy()
 
  123             bbox = subId.pop(
'bbox')
 
  124             loc = super(ExposurePersistenceType, cls).
makeButlerLocation(path, subId, mapper, suffix=
None,
 
  126             loc.additionalData.set(
'llcX', bbox.getMinX())
 
  127             loc.additionalData.set(
'llcY', bbox.getMinY())
 
  128             loc.additionalData.set(
'width', bbox.getWidth())
 
  129             loc.additionalData.set(
'height', bbox.getHeight())
 
  130             if 'imageOrigin' in dataId:
 
  131                 loc.additionalData.set(
'imageOrigin',
 
  132                                        dataId[
'imageOrigin'])
 
  137     python = 
"lsst.skymap.BaseSkyMap" 
  138     storage = 
"PickleStorage" 
  143     python = 
"lsst.afw.table.BaseCatalog" 
  145     storage = 
"FitsCatalogStorage" 
  150     python = 
"lsst.afw.table.SimpleCatalog" 
  151     cpp = 
"SimpleCatalog" 
  155     python = 
"lsst.afw.table.SourceCatalog" 
  156     cpp = 
"SourceCatalog" 
  160     python = 
"lsst.afw.table.ExposureCatalog" 
  161     cpp = 
"ExposureCatalog" 
  165     python = 
"lsst.afw.detection.PeakCatalog" 
  170     """Mapping object used to implement SimpleMapper, similar in intent to lsst.daf.peristence.Mapping. 
  176     def __init__(self, persistence, template=None, keys=None):
 
  178         if template 
is not None:
 
  183     def map(self, dataset, root, dataId, mapper, suffix=None, storage=None):
 
  188         return self.
persistence.makeButlerLocation(path, dataId, suffix=suffix, mapper=mapper,
 
  193     """Mapping for dataset types that are organized the same way as raw data (i.e. by CCD).""" 
  195     template = 
"{dataset}-{visit:04d}-{ccd:01d}{ext}" 
  196     keys = dict(visit=int, ccd=int)
 
  198     def query(self, dataset, index, level, format, dataId):
 
  199         dictList = index[dataset][level]
 
  200         results = [
list(d.values()) 
for d 
in dictList[dataId.get(level, 
None)]]
 
  205     """Mapping for dataset types that are organized according to a SkyMap subdivision of the sky.""" 
  207     template = 
"{dataset}-{filter}-{tract:02d}-{patch}{ext}" 
  208     keys = dict(filter=str, tract=int, patch=str)
 
  212     """Mapping for CoaddTempExp datasets.""" 
  214     template = 
"{dataset}-{tract:02d}-{patch}-{visit:04d}{ext}" 
  215     keys = dict(tract=int, patch=str, visit=int)
 
  219     """Mapping for forced_src datasets.""" 
  221     template = 
"{dataset}-{tract:02d}-{visit:04d}-{ccd:01d}{ext}" 
  222     keys = dict(tract=int, ccd=int, visit=int)
 
  226     """Metaclass for SimpleMapper that creates map_ and query_ methods for everything found in the 
  227     'mappings' class variable. 
  231     def _makeMapClosure(dataset, mapping, suffix=None):
 
  232         def mapClosure(self, dataId, write=False):
 
  233             return mapping.map(dataset, self.root, dataId, self, suffix=suffix, storage=self.storage)
 
  237     def _makeQueryClosure(dataset, mapping):
 
  238         def queryClosure(self, level, format, dataId):
 
  239             return mapping.query(dataset, self.index, level, format, dataId)
 
  243         type.__init__(cls, name, bases, dict_)
 
  245         for dataset, mapping 
in cls.mappings.
items():
 
  246             setattr(cls, 
"map_" + dataset, MapperMeta._makeMapClosure(dataset, mapping, suffix=
None))
 
  247             for suffix 
in mapping.persistence.suffixes:
 
  248                 setattr(cls, 
"map_" + dataset + suffix,
 
  249                         MapperMeta._makeMapClosure(dataset, mapping, suffix=suffix))
 
  250             if hasattr(mapping, 
"query"):
 
  251                 setattr(cls, 
"query_" + dataset, MapperMeta._makeQueryClosure(dataset, mapping))
 
  252         cls.
keyDict.update(mapping.keys)
 
  257     An extremely simple mapper for an imaginary camera for use in integration tests. 
  259     As SimpleMapper does not inherit from obs.base.CameraMapper, it does not 
  260     use a policy file to set mappings or a registry; all the information is here 
  261     (in the map_* and query_* methods). 
  263     The imaginary camera's raw data format has only 'visit' and 'ccd' keys, with 
  264     two CCDs per visit (by default). 
  270         forced_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
 
  271                                         template=
"{dataset}{ext}", keys={}),
 
  272         truth=
SimpleMapping(SimpleCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
 
  273                             keys={
"tract": int}),
 
  274         simsrc=
RawMapping(SimpleCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
 
  275                           keys={
"tract": int}),
 
  276         observations=
SimpleMapping(ExposureCatalogPersistenceType, template=
"{dataset}-{tract:02d}{ext}",
 
  277                                    keys={
"tract": int}),
 
  278         ccdExposureId=
RawMapping(BypassPersistenceType),
 
  280         deepCoaddId=
SkyMapping(BypassPersistenceType),
 
  282         deepMergedCoaddId=
SkyMapping(BypassPersistenceType),
 
  284         deepCoadd_skyMap=
SimpleMapping(SkyMapPersistenceType, template=
"{dataset}{ext}", keys={}),
 
  285         deepCoadd=
SkyMapping(ExposurePersistenceType),
 
  286         deepCoaddPsfMatched=
SkyMapping(ExposurePersistenceType),
 
  287         deepCoadd_calexp=
SkyMapping(ExposurePersistenceType),
 
  288         deepCoadd_calexp_background=
SkyMapping(CatalogPersistenceType),
 
  289         deepCoadd_icSrc=
SkyMapping(SourceCatalogPersistenceType),
 
  290         deepCoadd_icSrc_schema=
SimpleMapping(SourceCatalogPersistenceType,
 
  291                                              template=
"{dataset}{ext}", keys={}),
 
  292         deepCoadd_src=
SkyMapping(SourceCatalogPersistenceType),
 
  293         deepCoadd_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
 
  294                                            template=
"{dataset}{ext}", keys={}),
 
  295         deepCoadd_peak_schema=
SimpleMapping(PeakCatalogPersistenceType,
 
  296                                             template=
"{dataset}{ext}", keys={}),
 
  297         deepCoadd_ref=
SkyMapping(SourceCatalogPersistenceType),
 
  298         deepCoadd_ref_schema=
SimpleMapping(SourceCatalogPersistenceType,
 
  299                                            template=
"{dataset}{ext}", keys={}),
 
  300         deepCoadd_det=
SkyMapping(SourceCatalogPersistenceType),
 
  301         deepCoadd_det_schema=
SimpleMapping(SourceCatalogPersistenceType,
 
  302                                            template=
"{dataset}{ext}", keys={}),
 
  303         deepCoadd_mergeDet=
SkyMapping(SourceCatalogPersistenceType),
 
  304         deepCoadd_mergeDet_schema=
SimpleMapping(SourceCatalogPersistenceType,
 
  305                                                 template=
"{dataset}{ext}", keys={}),
 
  306         deepCoadd_deblendedFlux=
SkyMapping(SourceCatalogPersistenceType),
 
  307         deepCoadd_deblendedFlux_schema=
SimpleMapping(SourceCatalogPersistenceType,
 
  308                                                      template=
"{dataset}{ext}", keys={}),
 
  309         deepCoadd_deblendedModel=
SkyMapping(SourceCatalogPersistenceType),
 
  310         deepCoadd_deblendedModel_schema=
SimpleMapping(SourceCatalogPersistenceType,
 
  311                                                       template=
"{dataset}{ext}", keys={}),
 
  312         deepCoadd_meas=
SkyMapping(SourceCatalogPersistenceType),
 
  313         deepCoadd_meas_schema=
SimpleMapping(SourceCatalogPersistenceType,
 
  314                                             template=
"{dataset}{ext}", keys={}),
 
  315         deepCoadd_forced_src=
SkyMapping(SourceCatalogPersistenceType),
 
  316         deepCoadd_forced_src_schema=
SimpleMapping(SourceCatalogPersistenceType,
 
  317                                                   template=
"{dataset}{ext}", keys={}),
 
  318         deepCoadd_mock=
SkyMapping(ExposurePersistenceType),
 
  319         deepCoaddPsfMatched_mock=
SkyMapping(ExposurePersistenceType),
 
  321         deepCoadd_directWarp_mock=
TempExpMapping(ExposurePersistenceType),
 
  323         deepCoadd_psfMatchedWarp_mock=
TempExpMapping(ExposurePersistenceType),
 
  332         self.
storage = lsst.daf.persistence.Storage.makeFromURI(root)
 
  333         super(SimpleMapper, self).
__init__(**kwargs)
 
  336         afwImageUtils.defineFilter(
'r', 619.42)
 
  343         if datasetType 
is None:
 
  346             keyDict = self.
mappings[datasetType].keys
 
  347         if level 
is not None and level 
in self.
levels:
 
  348             keyDict = dict(keyDict)
 
  349             for l 
in self.
levels[level]:
 
  355         filenames = os.listdir(self.
root)
 
  356         rawRegex = re.compile(
r"(?P<dataset>\w+)-(?P<visit>\d+)-(?P<ccd>\d).*")
 
  358         for filename 
in filenames:
 
  359             m = rawRegex.match(filename)
 
  362             index = self.
index.setdefault(m.group(
'dataset'), dict(ccd={
None: []}, visit={
None: []}))
 
  363             visit = int(m.group(
'visit'))
 
  364             ccd = int(m.group(
'ccd'))
 
  365             d1 = dict(visit=visit, ccd=ccd)
 
  366             d2 = dict(visit=visit)
 
  367             index[
'ccd'].setdefault(visit, []).
append(d1)
 
  368             index[
'ccd'][
None].
append(d1)
 
  369             index[
'visit'][visit] = [d2]
 
  370             index[
'visit'][
None].
append(d1)
 
  380             "lsst.afw.cameraGeom.Camera", 
"Camera", 
None, [], dataId, mapper=self, storage=self.
storage 
  384         detectorId = dataId[
"ccd"]
 
  385         detector = self.
camera[detectorId]
 
  386         item.setDetector(detector)
 
  390     def _computeCcdExposureId(self, dataId):
 
  391         return int(dataId[
"visit"]) * 10 + int(dataId[
"ccd"])
 
  393     def _computeCoaddId(self, dataId):
 
  396         tract = int(dataId[
'tract'])
 
  397         if tract < 0 
or tract >= 128:
 
  398             raise RuntimeError(
'tract not in range [0,128)')
 
  399         patchX, patchY = (int(c) 
for c 
in dataId[
'patch'].split(
','))
 
  400         for p 
in (patchX, patchY):
 
  401             if p < 0 
or p >= 2**13:
 
  402                 raise RuntimeError(
'patch component not in range [0, 8192)')
 
  403         return (tract * 2**13 + patchX) * 2**13 + patchY
 
  407         return dict(visit=(int(ccdExposureId) // 10), ccd=(int(ccdExposureId) % 10))
 
  419         return 1 + 7 + 13*2 + 3
 
  425         return 1 + 7 + 13*2 + 3
 
  434     radialDistortion=0.925,
 
  438     @param[in] nx: number of detectors in x 
  439     @param[in] ny: number of detectors in y 
  440     @param[in] sizeX: detector size in x (pixels) 
  441     @param[in] sizeY: detector size in y (pixels) 
  442     @param[in] gapX: gap between detectors in x (mm) 
  443     @param[in] gapY: gap between detectors in y (mm) 
  444     @param[in] pixelSize: pixel size (mm) (a float) 
  445     @param[in] plateScale: plate scale in arcsec/mm; 20.0 is for LSST 
  446     @param[in] radialDistortion: radial distortion, in mm/rad^2 
  447         (the r^3 coefficient of the radial distortion polynomial 
  448         that converts FIELD_ANGLE in radians to FOCAL_PLANE in mm); 
  449         0.925 is the value Dave Monet measured for lsstSim data 
  451     Each detector will have one amplifier (with no raw information). 
  454     radialDistortCoeffs = [0.0, 1.0/pScaleRad, 0.0, radialDistortion/pScaleRad]
 
  463         cY = (iY - 0.5 * (nY - 1)) * (pixelSize * sizeY + gapY)
 
  465             cX = (iX - 0.5 * (nX - 1)) * (pixelSize * sizeY + gapX)
 
  467             detectorName = 
"detector %d,%d" % (iX, iY)
 
  469             detectorBuilder = cameraBuilder.add(detectorName, detectorId)
 
  470             detectorBuilder.setSerial(detectorName + 
" serial")
 
  471             detectorBuilder.setBBox(ccdBBox)
 
  477             ampBuilder.setName(ampName)
 
  478             ampBuilder.setBBox(ccdBBox)
 
  479             ampBuilder.setGain(1.0)
 
  480             ampBuilder.setReadNoise(5.0)
 
  482             detectorBuilder.append(ampBuilder)
 
  486     cameraBuilder.setTransformFromFocalPlaneTo(lsst.afw.cameraGeom.FIELD_ANGLE, focalPlaneToFieldAngle)
 
  487     return cameraBuilder.finish()
 
  492     Create a data repository for SimpleMapper and return a butler for it. 
  494     Clobbers anything already in the given path. 
  496     if os.path.exists(root):
 
  499     with open(os.path.join(root, 
"_mapper"), 
"w") 
as f:
 
  500         f.write(
"lsst.pipe.tasks.mocks.SimpleMapper\n")