Coverage for metadetect / tests / test_masking.py: 8%
293 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-17 09:20 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-17 09:20 +0000
1import numpy as np
2import ngmix
4import pytest
6from metadetect.masking import (
7 _intersects,
8 _ap_kern_kern,
9 _do_apodization_mask,
10 make_foreground_apodization_mask,
11 _do_mask_foreground,
12 make_foreground_bmask,
13 apply_foreground_masking_corrections,
14 _build_square_apodization_mask,
15 apply_apodization_corrections,
16)
19def test_apply_apodization_corrections():
20 nband = 2
21 seed = 10
22 dims = (13, 13)
24 mbobs = ngmix.MultiBandObsList()
25 rng = np.random.RandomState(seed=seed)
26 for _ in range(nband):
27 image = rng.uniform(size=dims)
28 noise = rng.uniform(size=dims)
29 obs = ngmix.Observation(
30 image=image,
31 noise=noise,
32 weight=rng.uniform(size=dims),
33 bmask=np.zeros(dims, dtype=np.int32),
34 ormask=np.zeros(dims, dtype=np.int32),
35 )
36 obs.mfrac = rng.uniform(size=dims)
37 obslist = ngmix.ObsList()
38 obslist.append(obs)
39 mbobs.append(obslist)
41 apply_apodization_corrections(
42 mbobs=mbobs,
43 mask_bit_val=2**3,
44 ap_rad=1,
45 )
47 rng = np.random.RandomState(seed=seed)
48 for obslist in mbobs:
49 for obs in obslist:
50 msk = (obs.bmask & 2**3) != 0
51 image = rng.uniform(size=dims)
52 noise = rng.uniform(size=dims)
53 # we need to match these calls to the ones above
54 rng.uniform(size=dims)
55 rng.uniform(size=dims)
57 assert np.all(obs.mfrac[msk] == 1)
58 assert np.all(obs.weight[msk] == 0)
60 assert np.all(image[msk] != obs.image[msk])
61 assert np.all(image[~msk] == obs.image[~msk])
62 assert np.all(noise[msk] != obs.noise[msk])
63 assert np.all(noise[~msk] == obs.noise[~msk])
66def test_apply_apodization_corrections_all():
67 nband = 2
68 seed = 10
69 dims = (13, 13)
70 mbobs = ngmix.MultiBandObsList()
71 rng = np.random.RandomState(seed=seed)
72 for _ in range(nband):
73 image = rng.uniform(size=dims)
74 noise = rng.uniform(size=dims)
75 obs = ngmix.Observation(
76 image=image,
77 noise=noise,
78 weight=rng.uniform(size=dims),
79 bmask=np.zeros(dims, dtype=np.int32),
80 ormask=np.zeros(dims, dtype=np.int32),
81 )
82 obs.mfrac = rng.uniform(size=dims)
83 obslist = ngmix.ObsList()
84 obslist.append(obs)
85 mbobs.append(obslist)
87 apply_apodization_corrections(
88 mbobs=mbobs,
89 mask_bit_val=2**3,
90 ap_rad=4,
91 )
93 rng = np.random.RandomState(seed=seed)
94 for obslist in mbobs:
95 for obs in obslist:
96 assert np.all((obs.bmask & 2**3) != 0)
99@pytest.mark.parametrize("ap_rad", [0.5, 1, 1.2])
100def test_build_square_apodization_mask(ap_rad):
101 dim = 100
102 ap_mask = np.ones((dim, dim))
103 _build_square_apodization_mask(ap_rad, ap_mask)
105 ap_range = int(6*ap_rad + 0.5)
106 assert np.all(ap_mask[0:ap_range, :] < 1.0)
107 assert np.all(ap_mask[-ap_range:, :] < 1.0)
108 assert np.all(ap_mask[:, 0:ap_range] < 1.0)
109 assert np.all(ap_mask[:, -ap_range:] < 1.0)
111 assert np.all(ap_mask[ap_range, ap_range:-ap_range] == 1.0)
112 assert np.all(ap_mask[-ap_range-1, ap_range:-ap_range] == 1.0)
113 assert np.all(ap_mask[ap_range:-ap_range, ap_range] == 1.0)
114 assert np.all(ap_mask[ap_range:-ap_range, -ap_range-1] == 1.0)
116 if False:
117 import matplotlib.pyplot as plt
118 plt.figure()
119 plt.imshow(ap_mask)
120 import pdb
121 pdb.set_trace()
124def test_build_square_apodization_mask_all():
125 dim = 13
126 ap_mask = np.ones((dim, dim))
127 _build_square_apodization_mask(4, ap_mask)
129 assert np.all(ap_mask < 1.0)
132@pytest.mark.parametrize('row,col,radius_pixels,nrows,ncols,yes', [
133 # basic
134 (0, 0, 10, 10, 10, True),
135 (-1000, 0, 10, 10, 10, False),
136 (1000, 0, 10, 10, 10, False),
137 (0, -1000, 10, 10, 10, False),
138 (0, 1000, 10, 10, 10, False),
139 # edge cases
140 (-10, 0, 10, 10, 10, False),
141 (19, 0, 10, 10, 10, False),
142 (0, -10, 10, 10, 10, False),
143 (0, 19, 10, 10, 10, False),
144 # partial
145 (2, 5, 10, 7, 7, True),
146])
147def test_intersects(row, col, radius_pixels, nrows, ncols, yes):
148 if yes:
149 assert _intersects(row, col, radius_pixels, nrows, ncols)
150 else:
151 assert not _intersects(row, col, radius_pixels, nrows, ncols)
154@pytest.mark.parametrize("fac,val", [
155 (1, 1),
156 (0, 1),
157 (-3, 0.5),
158 (-6, 0),
159 (-7, 0),
160])
161def test_ap_kern_kern(fac, val):
162 h = 2.0
163 m = 10.0
164 assert np.allclose(_ap_kern_kern(m + fac*h, m, h), val)
167def test_do_apodization_mask_all_masked():
168 ap_mask = np.ones((10, 13))
169 rows = np.array([0, 3])
170 cols = rows = np.array([0, 5])
171 radius_pixels = np.array([100, 10])
173 _do_apodization_mask(
174 rows=rows,
175 cols=cols,
176 radius_pixels=radius_pixels,
177 ap_mask=ap_mask,
178 ap_rad=1.5,
179 )
181 assert np.all(ap_mask == 0)
184def test_do_apodization_mask_half_masked():
185 ap_mask = np.ones((10, 13))
186 rows = np.array([0])
187 cols = np.array([6])
188 radius_pixels = np.array([5])
190 _do_apodization_mask(
191 rows=rows,
192 cols=cols,
193 radius_pixels=radius_pixels,
194 ap_mask=ap_mask,
195 ap_rad=0.1,
196 )
198 assert np.all(ap_mask[6:, :] == 1)
199 assert not np.all(ap_mask[:6, :] == 1)
200 assert np.all(ap_mask[0:2, 6:8] == 0)
202 if False:
203 import matplotlib.pyplot as plt
204 plt.figure()
205 plt.pcolormesh(ap_mask)
206 import pdb
207 pdb.set_trace()
210def test_make_foreground_apodization_mask():
211 ap_mask = make_foreground_apodization_mask(
212 xm=np.array([6], dtype='f8'),
213 ym=np.array([0], dtype='f8'),
214 rm=np.array([5], dtype='f8'),
215 dims=(10, 13),
216 symmetrize=False,
217 ap_rad=0.1
218 )
220 assert np.all(ap_mask[6:, :] == 1)
221 assert not np.all(ap_mask[:6, :] == 1)
222 assert np.all(ap_mask[0:2, 6:8] == 0)
225def test_make_foreground_apodization_mask_symmetrize():
226 ap_mask = make_foreground_apodization_mask(
227 xm=np.array([6], dtype='f8'),
228 ym=np.array([0], dtype='f8'),
229 rm=np.array([5], dtype='f8'),
230 dims=(10, 10),
231 symmetrize=False,
232 ap_rad=0.1
233 )
235 ap_mask_sym = make_foreground_apodization_mask(
236 xm=np.array([6], dtype='f8'),
237 ym=np.array([0], dtype='f8'),
238 rm=np.array([5], dtype='f8'),
239 dims=(10, 10),
240 symmetrize=True,
241 ap_rad=0.1
242 )
244 msk = ap_mask == 0
245 assert np.allclose(ap_mask[msk], ap_mask_sym[msk])
247 msk = ap_mask_sym == 1
248 assert np.allclose(ap_mask[msk], ap_mask_sym[msk])
250 rot_ap_mask = np.rot90(ap_mask)
251 msk = rot_ap_mask == 0
252 assert np.allclose(ap_mask_sym[msk], rot_ap_mask[msk])
254 assert np.all(ap_mask[0:2, 6:8] == 0)
256 if False:
257 import matplotlib.pyplot as plt
258 plt.figure()
259 plt.pcolormesh(ap_mask_sym)
260 import pdb
261 pdb.set_trace()
264def test_do_mask_foreground_all_masked():
265 flag = 2**5
266 bmask = np.zeros((10, 13), dtype=np.int32)
267 rows = np.array([0, 3])
268 cols = rows = np.array([0, 5])
269 radius_pixels = np.array([100, 10])
270 bmask[4, 5] |= 2**3
272 _do_mask_foreground(
273 rows=rows,
274 cols=cols,
275 radius_pixels=radius_pixels,
276 bmask=bmask,
277 flag=flag,
278 )
280 assert np.all((bmask & flag) != 0)
281 assert (bmask[4, 5] & 2**3) != 0
282 assert (bmask[1, 2] & 2**3) == 0
285def test_do_mask_foreground_half_masked():
286 flag = 2**5
287 bmask = np.zeros((10, 13), dtype=np.int32)
288 rows = np.array([0])
289 cols = np.array([6])
290 radius_pixels = np.array([5])
291 bmask[4, 5] |= 2**3
293 _do_mask_foreground(
294 rows=rows,
295 cols=cols,
296 radius_pixels=radius_pixels,
297 bmask=bmask,
298 flag=flag,
299 )
301 assert np.all((bmask[6:, 6:] & flag) == 0)
302 assert np.all((bmask[0:2, 6:8] & flag) != 0)
303 assert (bmask[4, 5] & 2**3) != 0
304 assert (bmask[1, 2] & 2**3) == 0
307def test_make_foreground_bmask():
308 flag = 2**7
310 bmask = make_foreground_bmask(
311 xm=np.array([6], dtype='f8'),
312 ym=np.array([0], dtype='f8'),
313 rm=np.array([5], dtype='f8'),
314 dims=(10, 13),
315 symmetrize=False,
316 mask_bit_val=flag,
317 )
319 assert np.all((bmask[6:, 6:] & flag) == 0)
320 assert np.all((bmask[0:2, 6:8] & flag) != 0)
323def test_make_foreground_bmask_symmetrize():
324 flag = 2**9
326 bmask = make_foreground_bmask(
327 xm=np.array([6], dtype='f8'),
328 ym=np.array([0], dtype='f8'),
329 rm=np.array([5], dtype='f8'),
330 dims=(10, 10),
331 mask_bit_val=flag,
332 symmetrize=False,
333 )
335 bmask_sym = make_foreground_bmask(
336 xm=np.array([6], dtype='f8'),
337 ym=np.array([0], dtype='f8'),
338 rm=np.array([5], dtype='f8'),
339 dims=(10, 10),
340 mask_bit_val=flag,
341 symmetrize=True,
342 )
344 msk = bmask > 0
345 assert np.all((bmask[msk] & bmask_sym[msk]) != 0)
347 rot_bmask = np.rot90(bmask)
348 msk = rot_bmask > 0
349 assert np.all((rot_bmask[msk] & bmask_sym[msk]) != 0)
351 assert np.all((bmask_sym[0:2, 6:8] & flag) != 0)
354@pytest.mark.parametrize("msk_exp_rad", [0, 4])
355def test_apply_foreground_masking_corrections_interp(msk_exp_rad):
356 nband = 2
357 seed = 10
358 dims = (13, 13)
360 def _make_mbobs():
361 mbobs = ngmix.MultiBandObsList()
362 rng = np.random.RandomState(seed=seed)
363 for _ in range(nband):
364 image = rng.uniform(size=dims)
365 noise = rng.uniform(size=dims)
366 obs = ngmix.Observation(
367 image=image,
368 noise=noise,
369 weight=rng.uniform(size=dims),
370 bmask=np.zeros(dims, dtype=np.int32),
371 ormask=np.zeros(dims, dtype=np.int32),
372 )
373 obs.mfrac = rng.uniform(size=dims)
374 obslist = ngmix.ObsList()
375 obslist.append(obs)
376 mbobs.append(obslist)
378 return mbobs
380 res = {}
381 for method in ['interp', 'interp-noise']:
382 mbobs = _make_mbobs()
383 apply_foreground_masking_corrections(
384 mbobs=mbobs,
385 xm=np.array([6]),
386 ym=np.array([0]),
387 rm=np.array([5-msk_exp_rad]),
388 method=method,
389 mask_expand_rad=msk_exp_rad,
390 mask_bit_val=2**3,
391 expand_mask_bit_val=2**4,
392 interp_bit_val=2**5,
393 symmetrize=False,
394 ap_rad=1,
395 iso_buff=1,
396 rng=np.random.RandomState(seed=11)
397 )
398 res[method] = mbobs
400 for method in ['interp', 'interp-noise']:
401 mbobs = res[method]
402 rng = np.random.RandomState(seed=seed)
403 for obslist in mbobs:
404 for obs in obslist:
405 msk = (obs.bmask & 2**3) != 0
406 image = rng.uniform(size=dims)
407 noise = rng.uniform(size=dims)
408 # we need to match these calls to the ones above
409 rng.uniform(size=dims)
410 rng.uniform(size=dims)
412 assert np.all(obs.mfrac[msk] == 1)
413 assert np.all(obs.weight[msk] == 0)
414 assert np.all((obs.bmask[msk] & 2**5) != 0)
416 assert np.all(image[msk] != obs.image[msk])
417 assert np.all(image[~msk] == obs.image[~msk])
418 assert np.all(noise[msk] != obs.noise[msk])
419 assert np.all(noise[~msk] == obs.noise[~msk])
421 msk = (obs.bmask & 2**4) != 0
422 if msk_exp_rad > 0:
423 assert np.sum(msk) > 0
425 assert not np.all(obs.mfrac[msk] == 1)
426 assert not np.all(obs.weight[msk] == 0)
427 assert not np.all((obs.bmask[msk] & 2**5) != 0)
429 assert not np.all(image[msk] != obs.image[msk])
430 assert np.all(image[~msk] == obs.image[~msk])
431 assert not np.all(noise[msk] != obs.noise[msk])
432 assert np.all(noise[~msk] == obs.noise[~msk])
433 else:
434 assert np.sum(msk) == 0
436 for i in range(len(res['interp'])):
437 if msk_exp_rad > 0:
438 assert np.array_equal(
439 res['interp'][i][0].image, res['interp-noise'][i][0].image
440 )
441 else:
442 assert not np.array_equal(
443 res['interp'][i][0].image, res['interp-noise'][i][0].image
444 )
447@pytest.mark.parametrize('method', ['interp', 'interp-noise'])
448def test_apply_foreground_masking_corrections_interp_all(method):
449 nband = 2
450 seed = 10
451 dims = (13, 13)
452 mbobs = ngmix.MultiBandObsList()
453 rng = np.random.RandomState(seed=seed)
454 for _ in range(nband):
455 image = rng.uniform(size=dims)
456 noise = rng.uniform(size=dims)
457 obs = ngmix.Observation(
458 image=image,
459 noise=noise,
460 weight=rng.uniform(size=dims),
461 bmask=np.zeros(dims, dtype=np.int32),
462 ormask=np.zeros(dims, dtype=np.int32),
463 )
464 obs.mfrac = rng.uniform(size=dims)
465 obslist = ngmix.ObsList()
466 obslist.append(obs)
467 mbobs.append(obslist)
469 apply_foreground_masking_corrections(
470 mbobs=mbobs,
471 xm=np.array([6]),
472 ym=np.array([0]),
473 rm=np.array([100]),
474 method=method,
475 mask_expand_rad=0,
476 mask_bit_val=2**3,
477 expand_mask_bit_val=2**4,
478 interp_bit_val=2**5,
479 symmetrize=False,
480 ap_rad=1,
481 iso_buff=1,
482 rng=np.random.RandomState(seed=11)
483 )
485 rng = np.random.RandomState(seed=seed)
486 for obslist in mbobs:
487 for obs in obslist:
488 assert np.all(obs.mfrac == 1)
489 assert np.all(obs.weight == 0)
490 assert np.all((obs.bmask & 2**3) != 0)
493@pytest.mark.parametrize("msk_exp_rad", [0, 4])
494def test_apply_foreground_masking_corrections_apodize(msk_exp_rad):
495 nband = 2
496 seed = 10
497 dims = (13, 13)
499 mbobs = ngmix.MultiBandObsList()
500 rng = np.random.RandomState(seed=seed)
501 for _ in range(nband):
502 image = rng.uniform(size=dims)
503 noise = rng.uniform(size=dims)
504 obs = ngmix.Observation(
505 image=image,
506 noise=noise,
507 weight=rng.uniform(size=dims),
508 bmask=np.zeros(dims, dtype=np.int32),
509 ormask=np.zeros(dims, dtype=np.int32),
510 )
511 obs.mfrac = rng.uniform(size=dims)
512 obslist = ngmix.ObsList()
513 obslist.append(obs)
514 mbobs.append(obslist)
516 apply_foreground_masking_corrections(
517 mbobs=mbobs,
518 xm=np.array([6]),
519 ym=np.array([0]),
520 rm=np.array([5-msk_exp_rad]),
521 method="apodize",
522 mask_expand_rad=msk_exp_rad,
523 mask_bit_val=2**3,
524 expand_mask_bit_val=2**4,
525 interp_bit_val=2**5,
526 symmetrize=False,
527 ap_rad=1,
528 iso_buff=1,
529 rng=np.random.RandomState(seed=11)
530 )
532 rng = np.random.RandomState(seed=seed)
533 for obslist in mbobs:
534 for obs in obslist:
535 msk = (obs.bmask & 2**3) != 0
536 image = rng.uniform(size=dims)
537 noise = rng.uniform(size=dims)
538 # we need to match these calls to the ones above
539 rng.uniform(size=dims)
540 rng.uniform(size=dims)
542 assert np.all(obs.mfrac[msk] == 1)
543 assert np.all(obs.weight[msk] == 0)
545 assert np.all(image[msk] != obs.image[msk])
546 assert np.all(image[~msk] == obs.image[~msk])
547 assert np.all(noise[msk] != obs.noise[msk])
548 assert np.all(noise[~msk] == obs.noise[~msk])
550 msk = (obs.bmask & 2**4) != 0
551 if msk_exp_rad > 0:
552 assert np.sum(msk) > 0
554 assert not np.all(obs.mfrac[msk] == 1)
555 assert not np.all(obs.weight[msk] == 0)
557 assert not np.all(image[msk] != obs.image[msk])
558 assert np.all(image[~msk] == obs.image[~msk])
559 assert not np.all(noise[msk] != obs.noise[msk])
560 assert np.all(noise[~msk] == obs.noise[~msk])
561 else:
562 assert np.sum(msk) == 0
565def test_apply_foreground_masking_corrections_apodize_all():
566 nband = 2
567 seed = 10
568 dims = (13, 13)
569 mbobs = ngmix.MultiBandObsList()
570 rng = np.random.RandomState(seed=seed)
571 for _ in range(nband):
572 image = rng.uniform(size=dims)
573 noise = rng.uniform(size=dims)
574 obs = ngmix.Observation(
575 image=image,
576 noise=noise,
577 weight=rng.uniform(size=dims),
578 bmask=np.zeros(dims, dtype=np.int32),
579 ormask=np.zeros(dims, dtype=np.int32),
580 )
581 obs.mfrac = rng.uniform(size=dims)
582 obslist = ngmix.ObsList()
583 obslist.append(obs)
584 mbobs.append(obslist)
586 apply_foreground_masking_corrections(
587 mbobs=mbobs,
588 xm=np.array([6]),
589 ym=np.array([0]),
590 rm=np.array([100]),
591 method="apodize",
592 mask_expand_rad=0,
593 mask_bit_val=2**3,
594 expand_mask_bit_val=2**4,
595 interp_bit_val=2**5,
596 symmetrize=False,
597 ap_rad=1,
598 iso_buff=1,
599 rng=np.random.RandomState(seed=11)
600 )
602 rng = np.random.RandomState(seed=seed)
603 for obslist in mbobs:
604 for obs in obslist:
605 assert np.all(obs.mfrac == 1)
606 assert np.all(obs.weight == 0)
607 assert np.all((obs.bmask & 2**3) != 0)
608 assert np.all(obs.image == 0)
609 assert np.all(obs.noise == 0)