4 from .
import algorithmsLib
6 @pexConf.wrap(algorithmsLib.AlgorithmControl)
10 @pexConf.wrap(algorithmsLib.CentroidControl)
14 @pexConf.wrap(algorithmsLib.ShapeControl)
18 @pexConf.wrap(algorithmsLib.FluxControl)
22 class AlgorithmRegistry(pexConf.Registry):
23 """A customized registry for source measurement algorithms.
25 Using a customizated registry allows us to avoid a lot of the
26 boilerplate that would otherwise be necessary when implementing a
27 new source measurement algorithm.
29 First, this registry class has the ability to views and associated
30 Fields that can only refer to algorithms with a particular
31 intermediate base class, all while referencing the same underlying
32 registry. This allows some fields to be restricted to a
33 particular subclass while others are not:
35 class MyConfig(Config):
36 any = AlgorithmRegistry.all.makeField(
37 "field that accepts any algorithm"
39 centroids = AlgorithmRegistry.filter(CentroidConfig).makeField(
40 "only allows centroiders"
43 The only instance of this registry is the class attribute 'all'
44 (hence 'AlgorithmRegistry.all', above). The 'filter' class method
45 is used to create filtered views into it. Note that the base
46 class is a config class, not a control class.
48 Second, because all algorithms must have swigged C++ control
49 classes, and these are essentially duplicates of the Config
50 classes users interact with in a RegistryField, the Config classes
51 themselves can be created transparently from the control classes
52 when the control class is registered. This is only done if the
53 control class does not already have a ConfigClass attribute and no
54 explicit ConfigClass argument is passed to the register method.
56 Third, the registry provides a customized instance dict for its
57 associated registry fields, which ensures the list of active
58 algorithms is always sorted according to their config's 'order'
61 The 'configurable' held in this registry is a callable that
62 returns a control object instance, and takes no additional
63 arguments. This simply calls config.makeControl() and sets the
64 control object's name data member (the config does not have a name
65 field, since it would be confusing to allow it to differ from the
68 All config classes registered must have a makeControl() method
69 that returns a control instance (this is usually provided by using
70 pex.config.makeConfigClass on the swigged control class). """
73 """A read-only view into registry that filters out items whose
74 config classes don't inherit from a particular base class."""
82 if not issubclass(t.ConfigClass, self.
base):
83 raise TypeError(
"%r is not a subclass of %r" % (t.ConfigClass, self.
base))
87 return len(tuple(
iter(self)))
90 return (k
for k, v
in self.registry.iteritems()
if issubclass(v.ConfigClass, self.
base))
93 v = self.registry.get(k)
94 return v
is not None and issubclass(v.ConfigClass, self.
base)
96 def makeField(self, doc, default=None, optional=False, multi=False):
97 return pexConf.RegistryField(doc, self, default, optional, multi)
100 """Class used as the actual element in the registry; a
101 callable that returns a swigged C++ control object with its
102 name set from the registry when called."""
104 __slots__ =
"ConfigClass",
"name"
111 ctrl = config.makeControl()
112 ctrl.name = self.
name
116 if hasattr(cls,
"all"):
117 raise TypeError(
"AlgorithmRegistry should be a singleton, and must "\
118 "not be copied (this is probably a bug in pex_config).")
119 return pexConf.Registry.__new__(cls, AlgorithmConfig)
123 """Register an AlgorithmControl subclass.
125 This is a class method, so you can either use it on the
126 registry instance or its class (this works because the
127 registry is a singleton, so the class knows to use cls.all as
130 If it does not have a ConfigClass attribute pointing to the
131 corresponding Config class, a config class will be created
132 using pex.config.makeConfigClass. A new config class will
133 also be created if the ConfigClass attribute was inherited
136 @param[in] name Name the algorithm will be registered
137 with; also the name of the source fields
139 @param[in] target An AlgorithmControl subclass.
140 @param[in] ConfigClass A Config class to be paired with the
144 if not issubclass(target, algorithmsLib.AlgorithmControl):
145 raise TypeError(
"Registry targets must be subclasses of AlgorithmControl")
146 if ConfigClass
is None:
147 if hasattr(target,
"ConfigClass")
and (
not hasattr(target.__base__,
"ConfigClass")
148 or target.ConfigClass != target.__base__.ConfigClass):
149 ConfigClass = target.ConfigClass
151 if not hasattr(target.__base__,
"ConfigClass"):
152 raise ValueError(
"Cannot create a config class for %s unless its base class "
153 "has a ConfigClass attribute." % target)
154 ConfigClass = pexConf.makeConfigClass(target, base=target.__base__.ConfigClass, module=2)
156 pexConf.Registry.register(self, name, target)
159 """Register an existing algorithm class with a new name."""
162 pexConf.Registry.register(self, newName, target)
164 def makeField(self, doc, default=None, optional=False, multi=False):
165 return pexConf.RegistryField(doc, self, default, optional, multi)
169 """Return a lazy read-only view that only contains items with
170 the given Config (not Control) base class.
172 return cls.SubclassRegistryView(cls.all, base)
176 AlgorithmRegistry.register(
"correctfluxes", algorithmsLib.CorrectFluxesControl)
177 AlgorithmRegistry.register(
"classification.extendedness", algorithmsLib.ClassificationControl)
178 AlgorithmRegistry.register(
"flags.pixel", algorithmsLib.PixelFlagControl)
179 AlgorithmRegistry.register(
"skycoord", algorithmsLib.SkyCoordControl)
180 AlgorithmRegistry.register(
"centroid.gaussian", algorithmsLib.GaussianCentroidControl)
181 AlgorithmRegistry.register(
"centroid.naive", algorithmsLib.NaiveCentroidControl)
182 AlgorithmRegistry.register(
"centroid.sdss", algorithmsLib.SdssCentroidControl)
183 AlgorithmRegistry.register(
"centroid.record", algorithmsLib.RecordCentroidControl)
184 AlgorithmRegistry.register(
"shape.sdss", algorithmsLib.SdssShapeControl)
185 AlgorithmRegistry.register(
"flux.aperture", algorithmsLib.ApertureFluxControl)
186 AlgorithmRegistry.register(
"flux.aperture.elliptical", algorithmsLib.EllipticalApertureFluxControl)
187 AlgorithmRegistry.register(
"flux.peakLikelihood", algorithmsLib.PeakLikelihoodFluxControl)
188 AlgorithmRegistry.register(
"flux.gaussian", algorithmsLib.GaussianFluxControl)
189 AlgorithmRegistry.register(
"flux.naive", algorithmsLib.NaiveFluxControl)
190 AlgorithmRegistry.register(
"flux.psf", algorithmsLib.PsfFluxControl)
193 @pexConf.wrap(algorithmsLib.SincFluxControl)
197 radius = property(_get_radius, _set_radius, doc=
"synonym for radius2")
198 AlgorithmRegistry.register(
"flux.sinc", target=algorithmsLib.SincFluxControl, ConfigClass=SincFluxConfig)