Loading [MathJax]/extensions/tex2jax.js
LSST Applications g0fba68d861+aff6b1d179,g1e78f5e6d3+b2e1eec3e3,g1fd858c14a+eb8d917efb,g35bb328faa+fcb1d3bbc8,g436fd98eb5+de86862952,g4af146b050+2f70285269,g4d2262a081+c17cfe15e3,g4e0f332c67+8616b824a5,g53246c7159+fcb1d3bbc8,g5a012ec0e7+d65fd7031a,g60b5630c4e+de86862952,g67b6fd64d1+c0248a1c13,g78460c75b0+2f9a1b4bcd,g786e29fd12+cf7ec2a62a,g7b71ed6315+fcb1d3bbc8,g87b7deb4dc+1a71b41694,g8852436030+40f6ec51d1,g89139ef638+c0248a1c13,g9125e01d80+fcb1d3bbc8,g94187f82dc+de86862952,g989de1cb63+c0248a1c13,g9f33ca652e+62adb22cd2,g9f7030ddb1+d892b2cb3e,ga2b97cdc51+de86862952,gabe3b4be73+1e0a283bba,gabf8522325+83c19109ce,gb1101e3267+1371da34ff,gb58c049af0+f03b321e39,gb89ab40317+c0248a1c13,gcf25f946ba+40f6ec51d1,gd6cbbdb0b4+d9e8db455e,gd9a9a58781+fcb1d3bbc8,gde0f65d7ad+fc726a16be,gded526ad44+763ef31e97,ge278dab8ac+4ce6343b44,ge410e46f29+c0248a1c13,gf67bdafdda+c0248a1c13,gfe06eef73a+95f9f0e40c,v29.0.0.rc3
LSST Data Management Base Package
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
_plugins.py
Go to the documentation of this file.
1# This file is part of pipe_tasks.
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
22from __future__ import annotations
23
24__all__ = ("PluginsRegistry", "plugins")
25
26from enum import Enum, auto
27from collections.abc import Callable
28from typing import TYPE_CHECKING, Generator
29from lsst.pipe.base import PipelineTaskConfig
30
31
32if TYPE_CHECKING:
33 from numpy.typing import NDArray
34 from collections.abc import Mapping
35
36 PLUGIN_TYPE = Callable[[NDArray, NDArray, Mapping[str, int]], NDArray]
37
38
39class PluginType(Enum):
40 """Enumeration to mark the type of data a plugin expects to work on"""
41
42 CHANNEL = auto()
43 """A plugin of this type expects to work on an individual channel
44 from a partial region of a mosaic, such as a `patch`.
45 """
46 PARTIAL = auto()
47 """A pluging that expects to work on a 3 channel image that is
48 a partial region of a mosaic, such as a `patch`.
49 """
50 FULL = auto()
51 """FULL plugins operate on a 3 channel image corresponding to
52 a complete mosaic.
53 """
54
55
57 """A class to serve as a registry for all pretty picture manipulation
58 plugins.
59
60 This class should not be instantiated directly other than the one
61 instantiation in this module.
62
63 example
64 -------
65 Using this registry to create a plugin would look somehting like the
66 following.
67
68 @plugins.register(1, PluginType.PARTIAL)
69 def fixNoData(
70 image: NDArray,
71 mask: NDArray,
72 maskDict: Mapping[str, int]
73 ) -> NDArray:
74 m = (mask & 2 ** maskDict["NO_DATA"]).astype(bool)
75 for i in range(3):
76 image[:, :, i] = cv2.inpaint(
77 image[:, :, i].astype(np.float32),
78 m.astype(np.uint8),
79 3,
80 cv2.INPAINT_TELEA
81 ).astype(image.dtype)
82 return image
83
84 """
85
86 def __init__(self) -> None:
87 self._full_values: list[tuple[float, PLUGIN_TYPE]] = []
88 self._partial_values: list[tuple[float, PLUGIN_TYPE]] = []
89 self._channel_values: list[tuple[float, PLUGIN_TYPE]] = []
90
91 def channel(self) -> Generator[PLUGIN_TYPE, None, None]:
92 yield from (func for _, func in self._channel_values)
93
94 def partial(self) -> Generator[PLUGIN_TYPE, None, None]:
95 yield from (func for _, func in self._partial_values)
96
97 def full(self) -> Generator[PLUGIN_TYPE, None, None]:
98 yield from (func for _, func in self._full_values)
99
100 def register(self, order: float, kind: PluginType) -> Callable:
101 """Register a plugin which is to be run when producing a
102 pretty picture.
103
104 parameters
105 ----------
106 order : `float`
107 This determines in what order plugins will be run. For
108 example, if plugin A specifies order 2, and plugin B
109 specifies order 1, and both are the same ``kind`` of
110 plugin type, plugin B will be run before plugin A.
111 kind : `PluginType`
112 This specifies what data the registered plugin expects
113 to run on, a channel, a partial image, or a full mosaic.
114
115 """
116
117 def wrapper(
118 func: Callable[[NDArray, NDArray, Mapping[str, int], PipelineTaskConfig], NDArray],
119 ) -> Callable[[NDArray, NDArray, Mapping[str, int], PipelineTaskConfig], NDArray]:
120 match kind:
121 case PluginType.PARTIAL:
122 self._partial_values.append((order, func))
123 case PluginType.FULL:
124 self._full_values.append((order, func))
125 case PluginType.CHANNEL:
126 self._channel_values.append((order, func))
127 return func
128
129 return wrapper
130
131
133"""
134This is the only instance of the plugin registry there should be. Users
135should import from here and use the register method as a decorator to
136register any plugins. Or, preferably, add them to this file to avoid
137needing any other import time logic elsewhere.
138"""
Generator[PLUGIN_TYPE, None, None] full(self)
Definition _plugins.py:97
Generator[PLUGIN_TYPE, None, None] partial(self)
Definition _plugins.py:94
Generator[PLUGIN_TYPE, None, None] channel(self)
Definition _plugins.py:91
Callable register(self, float order, PluginType kind)
Definition _plugins.py:100