23 Subtasks for creating the reference catalogs used in forced measurement. 
   27 import lsst.pex.config
 
   30 __all__ = (
"BaseReferencesTask", 
"CoaddSrcReferencesTask")
 
   34     """Default configuration for reference source selection. 
   37     removePatchOverlaps = lsst.pex.config.Field(
 
   38         doc=
"Only include reference sources for each patch that lie within the patch's inner bbox",
 
   42     filter = lsst.pex.config.Field(
 
   43         doc=
"Bandpass for reference sources; None indicates chi-squared detections.",
 
   50     """Base class for forced photometry subtask that fetches reference sources. 
   54     schema : `lsst.afw.table.Schema`, optional 
   55         The schema of the reference catalog. 
   56     butler : `lsst.daf.persistence.butler.Butler`, optional 
   57         A butler that will allow the task to load its schema from disk. 
   61     At least one of the ``schema`` and ``butler`` arguments must be present; 
   62     if both are, ``schema`` takes precedence. 
   64     ``BaseReferencesTask`` defines the required API for the references task, 
   67     - ``getSchema(butler)`` 
   68     - ``fetchInPatches(butler, tract, filter, patchList)`` 
   69     - ``fetchInBox(self, butler, tract, filter, bbox, wcs)`` 
   70     - the ``removePatchOverlaps`` config option 
   72     It also provides the ``subset`` method, which may be of use to derived 
   73     classes when reimplementing ``fetchInBox``. 
   76     ConfigClass = BaseReferencesConfig
 
   77     """Configuration class associated with this task (`lsst.pex.config.Config`). 
   80     def __init__(self, butler=None, schema=None, **kwargs):
 
   81         lsst.pipe.base.Task.__init__(self, **kwargs)
 
   84         """Return the schema for the reference sources. 
   88         butler : `lsst.daf.persistence.butler.Butler` 
   89             Data butler from which the schema will be fetched. 
   93         Must be available even before any data has been processed. 
   95         raise NotImplementedError(
"BaseReferencesTask is pure abstract, and cannot be used directly.")
 
   98         """Return the WCS for reference sources. 
  102         dataRef : `lsst.daf.persistence.ButlerDataRef` 
  103             The data reference from which the WCS will be fetched. This must 
  104             include the tract in its dataId. 
  106         raise NotImplementedError(
"BaseReferencesTask is pure abstract, and cannot be used directly.")
 
  109         """Return reference sources within a given bounding box. 
  111         Reference sources are selected if they overlap a region defined by a 
  112         pixel-coordinate bounding box and corresponding WCS. 
  116         dataRef : `lsst.daf.persistence.ButlerDataRef` 
  117             Butler data reference. The implied data ID must contain the 
  119         bbox : `lsst.afw.geom.Box2I` or `lsst.afw.geom.Box2D` 
  120             Defines the selection region in pixel coordinates. 
  121         wcs : `lsst.afw.image.SkyWcs` 
  122             Maps ``bbox`` to sky coordinates. 
  126         sources : iterable of `~lsst.afw.table.SourceRecord` 
  127             Reference sources. May be any Python iterable, including a lazy 
  132         The returned set of sources should be complete and close to minimal. 
  134         raise NotImplementedError(
"BaseReferencesTask is pure abstract, and cannot be used directly.")
 
  137         """Return reference sources within one or more patches. 
  141         dataRef : `lsst.daf.persistence.ButlerDataRef` 
  142             Butler data reference. The implied data ID must contain the 
  144         patchList : `list` of `lsst.skymap.PatchInfo` 
  145             Patches for which to fetch reference sources. 
  149         sources : iterable of `~lsst.afw.table.SourceRecord` 
  150             Reference sources. May be any Python iterable, including a lazy 
  155         The returned set of sources should be complete and close to minimal. 
  157         If ``config.removePatchOverlaps`` is `True`, only sources within each 
  158         patch's "inner" bounding box should be returned. 
  160         raise NotImplementedError(
"BaseReferencesTask is pure abstract, and cannot be used directly.")
 
  163         """Filter a list of sources to only those within the bounding box. 
  167         sources : iterable of `~lsst.afw.table.SourceRecord` 
  168             Reference sources. May be any Python iterable, including a lazy 
  170         bbox : `lsst.afw.geom.Box2I` or `lsst.afw.geom.Box2D` 
  171             Defines the selection region. 
  172         wcs : `lsst.afw.image.SkyWcs` 
  173             Maps ``bbox`` to sky coordinates. 
  177         sources : iterable of `~lsst.afw.table.SourceRecord` 
  178             Filtered sources. May be any Python iterable, including a lazy 
  183         Instead of filtering sources directly via their positions, we filter 
  184         based on the positions of parent objects, then include or discard all 
  185         children based on their parent's status. This is necessary to support 
  186         replacement with noise in measurement, which requires all child 
  187         sources have their parent present. 
  189         This is not a part of the required `BaseReferencesTask` interface; 
  190         it's a convenience function used in implementing `fetchInBox` that may 
  191         be of use to subclasses. 
  197         catalog.extend(sources)
 
  202         parentSources = catalog.getChildren(0)
 
  203         skyCoordList = [source.getCoord() 
for source 
in parentSources]
 
  204         pixelPosList = wcs.skyToPixel(skyCoordList)
 
  205         for parent, pixel 
in zip(parentSources, pixelPosList):
 
  206             if boxD.contains(pixel):
 
  208                 for child 
in catalog.getChildren(parent.getId()):
 
  213     """Default configuration for coadd reference source selection. 
  216     coaddName = lsst.pex.config.Field(
 
  217         doc=
"Coadd name: typically one of deep or goodSeeing.",
 
  221     skipMissing = lsst.pex.config.Field(
 
  222         doc=
"Silently skip patches where the reference catalog does not exist.",
 
  228         if (self.
coaddName == 
"chiSquared") != (self.filter 
is None):
 
  229             raise lsst.pex.config.FieldValidationError(
 
  230                 field=CoaddSrcReferencesConfig.coaddName,
 
  232                 msg=
"filter may be None if and only if coaddName is chiSquared" 
  237     """Select reference sources by loading the “coadd source” dataset directly. 
  239     The name of the dataset to read is generated by appending the 
  240     `datasetSuffix` attribute to the string ``Coadd_``. The dataset is then 
  241     read directly from disk using the Butler. 
  245     schema : `lsst.afw.table.Schema`, optional 
  246         The schema of the detection catalogs used as input to this one. 
  247     butler : `lsst.daf.persistence.butler.Butler`, optional 
  248         A Butler used to read the input schema from disk. Required if 
  249         ``schema`` is `None`. 
  253     The task will set its own ``self.schema`` attribute to the schema of the 
  254     output merged catalog. 
  257     ConfigClass = CoaddSrcReferencesConfig
 
  258     """Configuration class associated with this task (`lsst.pex.config.Config`). 
  261     datasetSuffix = 
"src" 
  262     """Suffix to append to ``Coadd_`` to generate the dataset name (`str`). 
  265     def __init__(self, butler=None, schema=None, **kwargs):
 
  266         BaseReferencesTask.__init__(self, butler=butler, schema=schema, **kwargs)
 
  268             assert butler 
is not None, 
"No butler nor schema provided" 
  274         """Return the WCS for reference sources. 
  278         dataRef : `lsst.daf.persistence.ButlerDataRef` 
  279             Butler data reference. Must includ the trac in its dataId. 
  281         skyMap = dataRef.get(self.
config.coaddName + 
"Coadd_skyMap", immediate=
True)
 
  282         return skyMap[dataRef.dataId[
"tract"]].
getWcs()
 
  285         """Fetch the source catalog using the Butler. 
  289         dataRef : `lsst.daf.persistence.ButlerDataRef` 
  290             Butler data reference. The implied data ID must contain the 
  292         patchList : `list` of `lsst.skymap.PatchInfo` 
  293             Patches for which to fetch reference sources. 
  297         sources : iterable of `~lsst.afw.table.SourceRecord` 
  298             Reference sources. May be any Python iterable, including a lazy 
  303         An implementation of `BaseReferencesTask.fetchInPatches` that loads 
  304         ``Coadd_`` + `datasetSuffix` catalogs using the butler. 
  307         tract = dataRef.dataId[
"tract"]
 
  308         butler = dataRef.butlerSubset.butler
 
  309         for patch 
in patchList:
 
  310             dataId = {
'tract': tract, 
'patch': 
"%d,%d" % patch.getIndex()}
 
  311             if self.
config.filter 
is not None:
 
  312                 dataId[
'filter'] = self.
config.filter
 
  314             if not butler.datasetExists(dataset, dataId):
 
  315                 if self.
config.skipMissing:
 
  318             self.
log.
info(
"Getting references in %s" % (dataId,))
 
  319             catalog = butler.get(dataset, dataId, immediate=
True)
 
  320             if self.
config.removePatchOverlaps:
 
  322                 for source 
in catalog:
 
  323                     if bbox.contains(source.getCentroid()):
 
  326                 for source 
in catalog:
 
  330         """Return reference sources within a given bounding box. 
  332         Reference sources are selected if they overlap a region defined by a 
  333         pixel-coordinate bounding box and corresponding WCS. 
  337         dataRef : `lsst.daf.persistence.ButlerDataRef` 
  338             Butler data reference. The implied data ID must contain the 
  340         bbox : `lsst.afw.geom.Box2I` or `lsst.afw.geom.Box2D` 
  341             Defines the selection region in pixel coordinates. 
  342         wcs : `lsst.afw.image.SkyWcs` 
  343             Maps ``bbox`` to sky coordinates. 
  345             a buffer to grow the bounding box by after catalogs have been loaded, but 
  346             before filtering them to include just the given bounding box. 
  350         sources : iterable of `~lsst.afw.table.SourceRecord` 
  351             Reference sources. May be any Python iterable, including a lazy 
  354         skyMap = dataRef.get(self.
config.coaddName + 
"Coadd_skyMap", immediate=
True)
 
  355         tract = skyMap[dataRef.dataId[
"tract"]]
 
  356         coordList = [wcs.pixelToSky(corner) 
for corner 
in lsst.geom.Box2D(bbox).getCorners()]
 
  357         self.
log.
info(
"Getting references in region with corners %s [degrees]" %
 
  358                       ", ".join(
"(%s)" % (coord.getPosition(lsst.geom.degrees),) 
for coord 
in coordList))
 
  359         patchList = tract.findPatchList(coordList)
 
  368     """Default configuration for multi-band reference source selection. 
  372         if self.filter 
is not None:
 
  373             raise lsst.pex.config.FieldValidationError(
 
  374                 field=MultiBandReferencesConfig.filter,
 
  376                 msg=
"Filter should not be set for the multiband processing scheme")
 
  378         BaseReferencesTask.ConfigClass.validate(self)
 
  382     """Loads references from the multi-band processing scheme. 
  385     ConfigClass = MultiBandReferencesConfig
 
  386     datasetSuffix = 
"ref"