89) -> tuple[Box, np.ndarray | None]:
90 """Initialize a morphology for a monotonic source
91
92 Parameters
93 ----------
94 detect:
95 The 2D detection image contained in `full_box`.
96 center:
97 The center of the monotonic source.
98 full_box:
99 The bounding box of `detect`.
100 padding:
101 The number of pixels to grow the morphology in each direction.
102 This can be useful if initializing a source with a kernel that
103 is known to be narrower than the expected value of the source.
104 normalize:
105 Whether or not to normalize the morphology.
106 monotonicity:
107 When `monotonicity` is `None`,
108 the component is initialized with only the
109 monotonic pixels, otherwise the monotonicity operator is used to
110 project the morphology to a monotonic solution.
111 threshold:
112 The minimum value to use for trimming the
113 morphology.
114 max_iter:
115 The maximum number of iterations to use in the monotonicity operator.
116 Only used if `monotonicity` is `None`.
117 center_radius:
118 The amount that the center can be shifted to a local maximum.
119 Only used if `monotonicity` is `None`.
120 variance_factor:
121 The average variance in the image.
122 This is used to allow pixels to be non-monotonic up to
123 `variance` * `noise_rms`, so setting `variance = 0`
124 will force strict monotonicity in the mask.
125 Only used if `monotonicity` is `None`.
126
127 Returns
128 -------
129 bbox:
130 The bounding box of the morphology.
131 morph:
132 The initialized morphology.
133 """
134 center: tuple[int, int] = tuple(center[i] - full_box.origin[i] for i in range(2))
135
136 if monotonicity is None:
137 _, morph, bounds = prox_monotonic_mask(
138 x=detect,
139 center=center,
140 center_radius=center_radius,
141 variance=variance_factor,
142 max_iter=max_iter,
143 )
144 bbox = bounds_to_bbox(bounds)
145 if bbox.shape == (1, 1) and morph[bbox.slices][0, 0] == 0:
146 return Box((0, 0)), None
147
148 if threshold > 0:
149 morph, bbox = trim_morphology(morph, threshold=threshold, padding=padding)
150
151 else:
152 morph = monotonicity(detect, center)
153
154
155 morph, bbox = trim_morphology(morph, threshold=threshold, padding=padding)
156
157
158 bbox += full_box.origin
159
160 if np.max(morph) == 0:
161 return Box((0, 0), origin=full_box.origin), None
162
163 if normalize:
164 morph /= np.max(morph)
165
166 if padding is not None and padding > 0:
167
168 bbox = bbox.grow(padding)
169
170
171
172 bbox = bbox & full_box
173 return bbox, morph
174
175