2 __all__ = [
"DirectMatchConfig", 
"DirectMatchTask", 
"DirectMatchConfigWithoutLoader"]
 
    4 from lsst.pex.config 
import Config, Field, ConfigurableField
 
    7                                   ReferenceSourceSelectorTask)
 
    9 from lsst.geom import arcseconds, averageSpherePoint
 
   13     """Configuration for `DirectMatchTask` when an already-initialized 
   14     ``refObjLoader`` will be passed to this task. 
   16     matchRadius = Field(dtype=float, default=0.25, doc=
"Matching radius, arcsec")
 
   17     sourceSelection = ConfigurableField(target=ScienceSourceSelectorTask,
 
   18                                         doc=
"Selection of science sources")
 
   19     referenceSelection = ConfigurableField(target=ReferenceSourceSelectorTask,
 
   20                                            doc=
"Selection of reference sources")
 
   24     """Configuration for `DirectMatchTask`. 
   26     refObjLoader = ConfigurableField(target=LoadIndexedReferenceObjectsTask, doc=
"Load reference objects")
 
   30     """Simple, brute force matching of a source catalog to a reference catalog. 
   34     butler : `lsst.daf.persistence.Butler` 
   35         Data butler containing the relevant reference catalog data. 
   36     refObjLoader : `lsst.meas.algorithms.LoadReferenceObjectsTask` or `None` 
   37         For loading reference objects. 
   39         Other keyword arguments required for instantiating a Task (such as 
   42     ConfigClass = DirectMatchConfig
 
   43     _DefaultName = 
"directMatch" 
   45     def __init__(self, butler=None, refObjLoader=None, **kwargs):
 
   46         Task.__init__(self, **kwargs)
 
   49                 if not isinstance(self.
config, DirectMatchConfig):
 
   50                     raise RuntimeError(
"DirectMatchTask must be initialized with DirectMatchConfig " 
   51                                        "if a refObjLoader is not supplied at initialization")
 
   62         """Set the reference object loader for the task. 
   67             An instance of a reference object loader, either a 
   68             `lsst.meas.algorithms.LoadReferenceObjectsTask` task or a 
   69             `lsst.meas.algorithms.ReferenceObjectLoader` instance. A task can 
   70             be used as a subtask and is generally used in gen2 middleware. The 
   71             class is designed to be used with gen3 middleware and is 
   72             initialized outside the normal task framework. 
   76     def run(self, catalog, filterName=None, epoch=None):
 
   77         """Load reference objects and match to them. 
   81         catalog : `lsst.afw.table.SourceCatalog` 
   84             Name of filter loading fluxes. 
   85         epoch : `astropy.time.Time` or `None` 
   86             Epoch to which to correct proper motion and parallax, or `None` to 
   87             not apply such corrections. 
   91         result : `lsst.pipe.base.Struct` 
   92             Result struct with components: 
   95                 Matched sources with associated reference 
   96                 (`lsst.afw.table.SourceMatchVector`). 
   98                 Match metadata (`lsst.meas.astrom.MatchMetadata`). 
  101             raise RuntimeError(
"Running matcher task with no refObjLoader set in __ini__ or setRefObjLoader")
 
  103         matchMeta = self.
refObjLoader.getMetadataCircle(circle.center, circle.radius, filterName, epoch=epoch)
 
  104         emptyResult = 
Struct(matches=[], matchMeta=matchMeta)
 
  105         sourceSelection = self.sourceSelection.
run(catalog)
 
  106         if len(sourceSelection.sourceCat) == 0:
 
  107             self.
log.
warn(
"No objects selected from %d objects in source catalog", len(catalog))
 
  109         refData = self.
refObjLoader.loadSkyCircle(circle.center, circle.radius, filterName, epoch=epoch)
 
  110         refCat = refData.refCat
 
  111         refSelection = self.referenceSelection.
run(refCat)
 
  112         if len(refSelection.sourceCat) == 0:
 
  113             self.
log.
warn(
"No objects selected from %d objects in reference catalog", len(refCat))
 
  116                                       self.
config.matchRadius*arcseconds)
 
  117         self.
log.
info(
"Matched %d from %d/%d input and %d/%d reference sources" %
 
  118                       (len(matches), len(sourceSelection.sourceCat), len(catalog),
 
  119                        len(refSelection.sourceCat), len(refCat)))
 
  120         return Struct(matches=matches, matchMeta=matchMeta, refCat=refCat, sourceSelection=sourceSelection,
 
  121                       refSelection=refSelection)
 
  124         """Calculate a circle enclosing the catalog. 
  128         catalog : `lsst.afw.table.SourceCatalog` 
  133         result : `lsst.pipe.base.Struct` 
  134             Result struct with components: 
  137                 ICRS center coordinate (`lsst.afw.geom.SpherePoint`). 
  139                 Radius of the circle (`lsst.geom.Angle`). 
  141         coordList = [src.getCoord() 
for src 
in catalog]
 
  143         radius = 
max(center.separation(coord) 
for coord 
in coordList)
 
  144         return Struct(center=center, radius=radius + self.
config.matchRadius*arcseconds)