LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
pluginRegistry.py
Go to the documentation of this file.
1 # This file is part of meas_base.
2 #
3 # Developed for the LSST Data Management System.
4 # This product includes software developed by the LSST Project
5 # (https://www.lsst.org).
6 # See the COPYRIGHT file at the top-level directory of this distribution
7 # for details of code ownership.
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 
22 """Registry for measurement plugins and utilities for plugin management.
23 """
24 
25 import collections
26 
27 import lsst.pipe.base
28 import lsst.pex.config
29 from .apCorrRegistry import addApCorrName
30 
31 __all__ = ("generateAlgorithmName", "PluginRegistry", "register", "PluginMap")
32 
33 
34 def generateAlgorithmName(AlgClass):
35  """Generate a name for an algorithm.
36 
37  This generates a short name for an algorithmic class that strips away
38  terms that are generally redundant while remaining easy to trace to the
39  code.
40 
41  Parameters
42  ----------
43  AlgClass : subclass of `BaseAlgorithm`
44  The class to generate a name for.
45 
46  Returns
47  -------
48  name : `str`
49  A short name for the algorithm.
50 
51  Notes
52  -----
53  The returned name will cobmine the package name, with any ``lsst`` and/or
54  ``meas`` prefix removed, with the class name, with any ``Algorithm``
55  suffix removed. For instance, ``lsst.meas.base.SdssShapeAlgorithm``
56  becomes ``base_SdssShape``.
57  """
58  name = AlgClass.__name__
59  pkg = AlgClass.__module__
60  name = name.replace("Algorithm", "")
61  terms = pkg.split(".")
62  # Hide private module name only if it's part of a public package
63  if len(terms) > 1 and terms[-1].startswith("_"):
64  terms = terms[:-1]
65  if len(terms) > 1 and terms[-1].endswith("Lib"):
66  terms = terms[:-1]
67  if terms[0] == "lsst":
68  terms = terms[1:]
69  if terms[0] == "meas":
70  terms = terms[1:]
71  if name.lower().startswith(terms[-1].lower()):
72  terms = terms[:-1]
73  return "%s_%s" % ("_".join(terms), name)
74 
75 
76 class PluginRegistry(lsst.pex.config.Registry):
77  """Base class for plugin registries.
78 
79  Notes
80  -----
81  The class of plugins allowed in the registry is defined in the constructor
82  of the registry.
83 
84  Single-frame and forced plugins have different registries.
85  """
86 
87  class Configurable:
88  """Class used as the element in the plugin registry.
89 
90  Parameters
91  ----------
92  name : `str`
93  Name under which the plugin is registerd.
94  PluginClass : subclass of `BasePlugin`
95  The class of plugin which can be stored in the registry.
96 
97  Notes
98  -----
99  Rather than constructing a Plugin instance, its __call__ method
100  (invoked by RegistryField.apply) returns a tuple
101  of ``(executionOrder, name, config, PluginClass)``, which can then
102  be sorted before the plugins are instantiated.
103  """
104 
105  __slots__ = "PluginClass", "name"
106 
107  def __init__(self, name, PluginClass):
108  self.name = name
109  self.PluginClass = PluginClass
110 
111  @property
112  def ConfigClass(self):
113  return self.PluginClass.ConfigClass
114 
115  def __call__(self, config):
116  return (self.PluginClass.getExecutionOrder(), self.name, config, self.PluginClass)
117 
118  def register(self, name, PluginClass, shouldApCorr=False, apCorrList=()):
119  """Register a plugin class with the given name.
120 
121  Parameters
122  ----------
123  name : `str`
124  The name of the plugin. This is used as a prefix for all fields
125  produced by the plugin, and it should generally contain the name
126  of the plugin or algorithm class itself as well as enough of the
127  namespace to make it clear where to find the code. For example
128  ``base_GaussianFlux`` indicates an algorithm in `lsst.meas.base`
129  that measures Gaussian Flux and produces fields such as
130  ``base_GaussianFlux_instFlux``, ``base_GaussianFlux_instFluxErr``
131  and ``base_GaussianFlux_flag``.
132  shouldApCorr : `bool`
133  If `True`, then this algorithm measures an instFlux that should
134  be aperture corrected. This is shorthand for ``apCorrList=[name]``
135  and is ignored if ``apCorrList`` is specified.
136  apCorrList : `list` of `str`
137  List of field name prefixes for instFlux fields to be aperture
138  corrected. If an algorithm produces a single instFlux that should
139  be aperture corrected then it is simpler to set
140  ``shouldApCorr=True``. But if an algorithm produces multiple such
141  fields then it must specify ``apCorrList`` instead. For example,
142  ``modelfit_CModel`` produces three such fields:
143  ``apCorrList=("modelfit_CModel_exp", "modelfit_CModel_exp",
144  "modelfit_CModel_def")``. If ``apCorrList`` is not empty then
145  shouldApCorr is ignored.
146 
147  Notes
148  -----
149  The same plugin may be registered multiple times with different names;
150  this can be useful if we often want to run it multiple times with
151  different configuration.
152  """
153  lsst.pex.config.Registry.register(self, name, self.Configurable(name, PluginClass))
154  if shouldApCorr and not apCorrList:
155  apCorrList = [name]
156  for prefix in apCorrList:
157  addApCorrName(prefix)
158 
159  def makeField(self, doc, default=None, optional=False, multi=False):
160  return lsst.pex.config.RegistryField(doc, self, default, optional, multi)
161 
162 
163 def register(name, shouldApCorr=False, apCorrList=()):
164  """A decorator to register a plugin class in its base class's registry.
165 
166  Parameters
167  ----------
168  shouldApCorr : `bool`
169  If `True`, then this algorithm measures an instFlux that should be
170  aperture corrected. This is shorthand for ``apCorrList=[name]`` and is
171  ignored if ``apCorrList`` is specified.
172  apCorrList : `list` of `str`
173  List of field name prefixes for instFlux fields to be aperture
174  corrected. If an algorithm produces a single instFlux that should be
175  aperture corrected then it is simpler to set ``shouldApCorr=True``.
176  But if an algorithm produces multiple such fields then it must specify
177  ``apCorrList`` instead. For example, ``modelfit_CModel`` produces
178  three such fields: ``apCorrList=("modelfit_CModel_exp",
179  "modelfit_CModel_exp", "modelfit_CModel_def")``. If ``apCorrList`` is
180  not empty then shouldApCorr is ignored.
181 
182  """
183 
184  def decorate(PluginClass):
185  PluginClass.registry.register(name, PluginClass, shouldApCorr=shouldApCorr, apCorrList=apCorrList)
186  return PluginClass
187  return decorate
188 
189 
190 class PluginMap(collections.OrderedDict):
191  """Map of plugins to be run for a given task.
192 
193  Notes
194  -----
195  Plugins are classes derived from `BasePlugin`.
196 
197  We assume plugins are added to the plugin map according to their
198  "Execution Order", so this class doesn't actually do any of the sorting
199  (though it does have to maintain that order, which it does by inheriting
200  from `collections.OrderedDict`).
201  """
202 
203  def iter(self):
204  """Return an iterator over plugins for use in single-object mode.
205 
206  Notes
207  -----
208  Plugins which should be used in single-object mode are identified by
209  having the `doMeasure` config attribute evaluate to `True`. This is
210  usually a simple boolean class attribute.
211  """
212  for plugin in self.values():
213  if plugin.config.doMeasure:
214  yield plugin
215 
216  def iterN(self):
217  """Return an iterator over plugins for use in multi-object mode.
218 
219  Notes
220  -----
221  Plugins which should be used in multi-object mode are identified by
222  having the `doMeasureN` config attribute evaluate to `True`.
223  This is usually a simple boolean class attribute.
224  """
225  for plugin in self.values():
226  if plugin.config.doMeasureN:
227  yield plugin
def makeField(self, doc, default=None, optional=False, multi=False)
def register(name, shouldApCorr=False, apCorrList=())
def register(self, name, PluginClass, shouldApCorr=False, apCorrList=())