202.6. Pixel mask planes#
202.6. Pixel mask planes¶
For the Rubin Science Platform at data.lsst.cloud.
Data Release: Data Preview 1
Container Size: large
LSST Science Pipelines version: r29.2.
Last verified to run: 2025-12-08
Repository: github.com/lsst/tutorial-notebooks
DOI: [10.11578/rubin/dc.20250909.20](https://doi.org/10.11578/rubin/dc.20250909.20\)
Learning objective: To illustrate the pixel mask planes in DP1 images.
LSST data products: deep_coadd
Packages: lsst.daf.butler, lsst.rsp, lsst.afw.display
Credit: Originally developed by Andrés A. Plazas Malagón, Melissa Graham, and the Rubin Community Science team with input from Jim Bosch and Yusra AlSayyad. Please consider acknowledging them if this notebook is used for the preparation of journal articles, software releases, or other notebooks.
Get Support: Everyone is encouraged to ask questions or raise issues in the Support Category of the Rubin Community Forum. Rubin staff will respond to all questions posted there.
1. Introduction¶
In the LSST Science Pipelines, each processed image includes not only the measured flux values but also a companion bit mask image that records the condition of every pixel. These mask planes encode information about detector defects, cosmic rays, saturation, missing data, and other effects that influence data quality. Each named mask plane corresponds to a specific bit flag that can be set independently or in combination with others on a given pixel.
For example, if bit 1 corresponds to a saturated pixel (SAT) and bit 3 to a pixel that has been hit by a cosmic ray (CR), a pixel with a mask value of 10 in binary indicates that both SAT and CR planes are active for that pixel (i.e., 2$^1$+ 2$^3$ = 10, see Section 3.3).
This compact representation makes it easy to test or combine conditions with bitwise operations.
This tutorial introduces the concept of mask planes in the LSST Science Pipelines and explains how to interpret them in Data Preview 1 (DP1) images. It also provides examples of how to visualize mask information, showing how colors correspond to specific mask flags, and how to use this information to assess image quality and understand the provenance of masked regions in the data.
Related tutorials: Image tutorials in the 200 series.
1.1. Import packages¶
From the LSST Science Pipelines import the packages for the Butler, 2-dimensional sky geometry, and for image display.
from lsst.daf.butler import Butler, Timespan
import lsst.afw.display as afwDisplay
import numpy as np
from astropy.time import Time
import matplotlib.pyplot as plt
1.2. Define parameters and functions¶
Instantiate the Butler.
butler = Butler("dp1", collections="LSSTComCam/DP1")
assert butler is not None
Set afw_display to use Firefly and open the Firefly display tab.
afwDisplay.setDefaultBackend('firefly')
afw_display = afwDisplay.Display(frame=1)
Function: show_mask_planes
Print all available mask planes with their bit value and display color.
def show_mask_planes(mask):
"""
Print all available mask planes with their bit value (2^n) and display color,
ordered by ascending bit value.
Parameters
----------
mask : `lsst.afw.image.Mask`
Mask object.
"""
plane_dict = mask.getMaskPlaneDict()
sorted_planes = sorted(plane_dict.items(), key=lambda item: item[1])
print(f"{'Mask Plane': <20} {'Bit': <5} {'2^n': <6} {'Hex': <10} {'Default Color'}")
print("-" * 60)
for name, bit in sorted_planes:
color = afw_display.getMaskPlaneColor(name)
value = 2**bit
hex_value = hex(value)
print(f"{name: <20} {bit: <5} {value: <6} {hex_value: <8} {color}")
2. Descriptions¶
Descriptions of the flags in the deep_coadd and visit_images mask planes can be found in the DP1 documentation.
The following table provides a summary.
| Mask Plane | Image Type | Description (DP1-specific) |
|---|---|---|
| BAD | visit + coadd | Permanently bad pixels, including entire bad amplifiers. Excluded from science use. |
| SAT | visit + coadd | The flux in this pixel was too high to be accurately recorded (exceeded the PTC turnoff point). In coadds, indicates saturation in at least part of the stack at this location. |
| INTRP | visit + coadd | Pixel value was replaced via interpolation (typically due to BAD, SAT, or CR). For coadds, all inputs had this pixel interpolated or it was interpolated during stacking. |
| CR | visit + coadd | Pixels hit by a cosmic ray; interpolated in visits. In coadds, one or more input visits flagged this pixel as a cosmic ray. |
| EDGE | visit + coadd | Region unprocessed where the convolution kernel footprint extended beyond the image edge. |
| DETECTED | visit + coadd | Pixel footprint belongs to a detected source above threshold. In coadds, detection occurred on the coadd. |
| DETECTED_NEGATIVE | difference | Negative source detection in difference images. |
| SUSPECT | visit + coadd | Pixel above the PTC turnoff but not fully saturated; not dilated like SAT. Propagates if a configurable fraction of inputs flagged it. |
| NO_DATA | visit + coadd | No valid data (chip gap, missing coverage, or failed amplifier). |
| VIGNETTED | visit + coadd | Pixels vignetted by optics; low-weight or low-quality data. In coadds, vignetted in all contributing visits. |
| STREAK | difference | Linear artifact such as a satellite trail or diffraction spike. |
| CLIPPED | coadd only | At least one input image for this pixel was identified as an artifact and excluded. |
| CROSSTALK | visit + coadd | Pixel affected by electronic crosstalk from a bright source in another amplifier. In coadds, flagged in at least one input. |
| INEXACT_PSF | coadd only | PSF poorly defined or inconsistent across inputs. Appears with at least one of SENSOR_EDGE, CLIPPED, or REJECTED. |
| ITL_DIP | visit + coadd | “ITL dip” artifact: dark vertical trails from bright sources on ITL CCDs. For coadds, flagged in at least one input. |
| NOT_DEBLENDED | visit + coadd | Pixel in a source footprint that was not successfully deblended. |
| REJECTED | coadd only | Pixel where a contributing image was masked and not used. |
| SENSOR_EDGE | coadd only | Pixel lies within a margin near the edge of at least one contributing input image. |
| UNMASKEDNAN | visit + coadd | Pixel contains a NaN without an accompanying mask flag; indicates invalid data. |
| INJECTED | visit only | Pixels with synthetic sources injected for testing or validation. |
| INJECTED_TEMPLATE | difference | Pixels with synthetic sources injected into template images for difference imaging tests. |
| SAT_TEMPLATE | difference | Pixel saturated in the template image used for difference imaging. |
Table 1: Summary of descriptions of the flags in the
deep_coaddandvisit_imagesmask planes.
2.1. Relation to artifacts¶
Several image artifacts caused by the camera, detector, or processing steps remain visible in DP1.
The DP1 artifacts documentation provides examples and definitions for many of these effects.
Some artifacts are explicitly flagged in the pixel-level mask plane, while others are not masked but may still impact photometry, shape, or background estimation.
The table below summarizes known artifact types in DP1 and indicates which, if any, mask planes are associated with each.
| Artifact Type | Description | Related Mask Planes | Notes |
|---|---|---|---|
| Bad pixels | Dead or misbehaving pixels, including “vampire” pixels. | BAD, INTRP |
BAD flags the defect; INTRP set if interpolated over. |
| Bad columns | Entire vertical columns of defective pixels. | BAD, INTRP |
Persistent column defects; often interpolated during visit processing. |
| Bleed trails | Overflow of charge from saturated stars vertically along columns. | SAT, INTRP, SUSPECT |
SAT is dilated to cover bleed; adjacent pixels may be flagged SUSPECT or INTRP. |
| Dark trails | Negative flux columns following a bleed trail (seen on ITL CCDs). | ITL_DIP |
Masked during ISR; modeled specifically for ITL sensors. |
| Edge bleed | Horizontal artifact along the edge after vertical bleeding reaches the CCD boundary. | SAT, SUSPECT, EDGE |
No unique plane. |
| Crosstalk | Ghost image from bright source mirrored into another amplifier. | CROSSTALK |
Subtracted in ISR; residual is masked with CROSSTALK. |
| Cosmic rays | Bright, sharp spots from high-energy particle hits. | CR, INTRP |
CR marks origin; INTRP used if patched. |
| Satellites / Streaks | Bright linear trails from satellites or debris. | STREAK |
In DP1, STREAK is set only in visit images if detected in difference imaging. |
| Interpolation | Pixel value filled in algorithmically (e.g. over CR, bad pixel, or bleed). | INTRP |
Indicates pixel value is not from real data. |
| Stray light | Off-axis light scattered into the focal plane. | None | Visually visible; not masked in DP1. |
| Ghost / Ghoul / Glint | Internal reflections from bright stars or camera hardware. | None | Visible as diffuse or bright patches; unmasked. |
| Amplifier jump | Blocky offsets between amplifiers due to gain mismatch. | None | ISR attempts correction; unmasked if residual remains. |
| Fringing | Interference pattern, most visible in z- and y-band exposures. | None | Processed photometrically; no associated mask plane. |
| Tree rings | Circular variations in pixel area from silicon manufacturing. | None | Small astrometric effect; no mask in DP1. |
| Crosshatch pattern | Correlated noise pattern from overscan subtraction. | None | Subtle; visible in low-background visits; unmasked. |
| Dark edge | Background over-subtraction at image edges or corners. | None | Artifact from sky subtraction; not masked. |
| Dark halo | Background over-subtraction near bright stars. | None | Common near very bright sources; visually evident but unmasked. |
Table 2: DP1 artifacts and relation to mask planes.
2.2. Key mask planes¶
Tables 3 and 4 describe how to treat mask planes when doing image analysis or source measurement with DP1 data, in a manner consistent with LSST Science Pipelines processing for DP1.
Note that pipelines may set certain planes during processing without always using them downstream (e.g., some algorithms ignore INTERP for PSF fitting).
Exclude: Pixels with this mask plane should be removed if they are still present; these generally indicate unusable data.
Retain: Pixels may remain; these planes are typically propagated by the pipelines without discarding the data.
Conditional: Use depends on science case; some algorithms may ignore or downweight these planes, but they are not universally excluded.
2.2.1. Visit images¶
For single-visit images, most mask planes trace detector-level effects. The most important mask planes to consider in image analyses are in Table 3.
| Mask Plane | Recommended Use | Notes |
|---|---|---|
| BAD | Conditional | Permanently bad pixels. Not suitable for science use if the affected area is large (e.g., an entire amplifier); usually well-interpolated and acceptable if the area is small (e.g., a bad column). |
| SAT | Exclude | Pixel saturated beyond the Photon Transfer Curve (PTC) turnoff point. Often propagates to coadds. |
| CR | Retain | Cosmic rays are well interpolated; no need to remove unless studying extremely rare or peculiar sources. |
| INTRP | Retain | Interpolated pixel (typically over BAD, SAT, or CR). Safe to retain for most analyses. |
| SUSPECT | Conditional | Near-saturation or uncertain response. Keep or reject depending on science goals. |
| EDGE / SENSOR_EDGE | Exclude | Marks detector edges; can propagate into coadds. |
| NO_DATA | Exclude | Region with no valid data (chip gap, missing coverage, failed amplifier). |
| CROSSTALK | Retain | Electronic signal induced by a bright source in a neighboring amplifier. |
| ITL_DIP | Exclude | "ITL dip" artifact: dark vertical trails from bright sources on ITL CCDs. |
| VIGNETTED | Conditional | Lower-quality data due to vignetting; may be included if weighted properly. |
Table 3: Key mask planes in
visit_images.
2.2.2. Deep coadd images¶
For coadds, several mask planes indicate whether individual visits contributing to a pixel were excluded or degraded. The most important mask planes to consider in image analyses are in Table 4.
| Mask Plane | Recommended Use | Notes |
|---|---|---|
| CLIPPED | Conditional | Input visit rejected during artifact removal (e.g., satellite trail). |
| REJECTED | Conditional | Input visits had masks intentionally removed (e.g., bad amplifier, bleed trail, vignetted region). |
| INEXACT_PSF | Conditional | Set if any of CLIPPED, REJECTED, or SENSOR_EDGE were true; this indicates potentially discontinuous PSF modeling. This flag should be used only when extremely high PSF accuracy is required or when there are very few visits (such that PSF discontinuities will not average down). |
| NO_DATA | Exclude | Every contributing visit was excluded, rejected, or clipped — often around saturated stars. |
| SAT | Exclude | Coadd pixel affected by saturation in one or more contributing visits. |
| CR | Retain | Cosmic-ray–affected pixels, interpolated in stacking. |
| INTRP | Retain | Interpolated values from single-visit images; generally fine for most science analyses. |
Table 4: Key mask planes in
deep_coadd.
3. Deep coadd mask¶
Query for deep_coadd images that overlap the coordinates RA, Dec (in degrees) near the center of the DP1 Extended Chandra Deep Fields South (ECDFS) field and were obtained with the r-band filter.
ra = 53.076
dec = -28.110
band = 'r'
query = f"band.name = '{band}' AND patch.region OVERLAPS POINT({ra}, {dec})"
dataset_refs = butler.query_datasets("deep_coadd", where=query)
assert len(dataset_refs) == 2
print(len(dataset_refs))
del ra, dec, band, query
2
For the first dataset reference returned by the query, get the corresponding deep_coadd.
ref = dataset_refs[0]
deep_coadd = butler.get(ref)
3.1. Get the mask plane¶
Get the mask plane from the deep_coadd object.
mask = deep_coadd.getMask()
3.2. Print the mask keys¶
Print the list of mask keys and default color.
show_mask_planes(mask)
Mask Plane Bit 2^n Hex Default Color ------------------------------------------------------------ BAD 0 1 0x1 red SAT 1 2 0x2 green INTRP 2 4 0x4 green CR 3 8 0x8 magenta EDGE 4 16 0x10 yellow DETECTED 5 32 0x20 blue DETECTED_NEGATIVE 6 64 0x40 cyan SUSPECT 7 128 0x80 yellow NO_DATA 8 256 0x100 orange VIGNETTED 9 512 0x200 None STREAK 10 1024 0x400 None CLIPPED 11 2048 0x800 None CROSSTALK 12 4096 0x1000 None INEXACT_PSF 13 8192 0x2000 None ITL_DIP 14 16384 0x4000 None NOT_DEBLENDED 15 32768 0x8000 None REJECTED 16 65536 0x10000 None SENSOR_EDGE 17 131072 0x20000 None UNMASKEDNAN 18 262144 0x40000 None
3.3. Interpret the mask values¶
Mask planes in the LSST Science Pipelines use a bitmask representation, meaning that each mask plane corresponds to one bit in the binary form of an integer.
Each bit represents whether a particular condition is True (1) or False (0) for a given pixel.
Computers store numbers in binary, where each bit position corresponds to a power of two.
For example:
| Bit Position | Binary | Power of Two | Decimal Value | Meaning (if used as a mask bit) |
|---|---|---|---|---|
| 0 | 0001 | $2^0$ | 1 | Plane #0 active (BAD) |
| 1 | 0010 | $2^1$ | 2 | Plane #1 active (SAT) |
| 2 | 0100 | $2^2$ | 4 | Plane #2 active (INTRP) |
| 3 | 1000 | $2^3$ | 8 | Plane #3 active (CR) |
If multiple planes are active, their bits are combined by addition (a bitwise OR operation).
This means that the total mask value is the sum of the powers of two corresponding to all active bits.
For example, a mask value of 73744 is equal to $2^1 + 2^2 + 2^3 + 2^5 + 2^{13} + 2^{16}$. The exponets of these power of two expressions represent the bits for the SAT, INTRP, CR, DETECTED, INEXACT_PSF, and REJECTED mask planes.
The mask object has a method to perform the conversion from value to mask planes automatically.
value = 73774
mask.interpret(value)
'CR,DETECTED,INEXACT_PSF,INTRP,REJECTED,SAT'
Warning: Bit values are assigned dynamically and are not guaranteed to be fixed.
3.4 Check the values in the mask array¶
Print a list of the unique mask array values, the number of pixels with that value, and the overlapping masks for pixels with that value.
values, counts = np.unique(mask.array, return_counts=True)
print(f"{'Hex': <8} {'Binary': <6} {'Counts': <8} {'Mask Planes': <30}")
print("-" * 60)
for value, count in zip(values, counts):
hex_value = hex(value)
print(f"{hex_value: <8} {value: <6} {count: <8} {mask.interpret(value): <30}")
Hex Binary Counts Mask Planes ------------------------------------------------------------ 0x0 0 76721 0xc 12 646 CR,INTRP 0x20 32 70815 DETECTED 0x2c 44 596 CR,DETECTED,INTRP 0x2800 10240 3540 CLIPPED,INEXACT_PSF 0x280c 10252 11 CLIPPED,CR,INEXACT_PSF,INTRP 0x2820 10272 3356 CLIPPED,DETECTED,INEXACT_PSF 0x282c 10284 33 CLIPPED,CR,DETECTED,INEXACT_PSF,INTRP 0x12000 73728 1184128 INEXACT_PSF,REJECTED 0x1200c 73740 10595 CR,INEXACT_PSF,INTRP,REJECTED 0x12020 73760 1035230 DETECTED,INEXACT_PSF,REJECTED 0x12022 73762 5521 DETECTED,INEXACT_PSF,REJECTED,SAT 0x1202c 73772 9191 CR,DETECTED,INEXACT_PSF,INTRP,REJECTED 0x1202e 73774 18 CR,DETECTED,INEXACT_PSF,INTRP,REJECTED,SAT 0x12124 74020 101 DETECTED,INEXACT_PSF,INTRP,NO_DATA,REJECTED 0x12800 75776 59334 CLIPPED,INEXACT_PSF,REJECTED 0x1280c 75788 457 CLIPPED,CR,INEXACT_PSF,INTRP,REJECTED 0x12820 75808 45218 CLIPPED,DETECTED,INEXACT_PSF,REJECTED 0x12822 75810 551 CLIPPED,DETECTED,INEXACT_PSF,REJECTED,SAT 0x1282c 75820 382 CLIPPED,CR,DETECTED,INEXACT_PSF,INTRP,REJECTED 0x12924 76068 42 CLIPPED,DETECTED,INEXACT_PSF,INTRP,NO_DATA,REJECTED 0x22000 139264 255566 INEXACT_PSF,SENSOR_EDGE 0x2200c 139276 2161 CR,INEXACT_PSF,INTRP,SENSOR_EDGE 0x22010 139280 1295 EDGE,INEXACT_PSF,SENSOR_EDGE 0x2201c 139292 8 CR,EDGE,INEXACT_PSF,INTRP,SENSOR_EDGE 0x22020 139296 225432 DETECTED,INEXACT_PSF,SENSOR_EDGE 0x2202c 139308 1912 CR,DETECTED,INEXACT_PSF,INTRP,SENSOR_EDGE 0x22030 139312 944 DETECTED,EDGE,INEXACT_PSF,SENSOR_EDGE 0x22800 141312 9979 CLIPPED,INEXACT_PSF,SENSOR_EDGE 0x2280c 141324 154 CLIPPED,CR,INEXACT_PSF,INTRP,SENSOR_EDGE 0x22810 141328 15 CLIPPED,EDGE,INEXACT_PSF,SENSOR_EDGE 0x22820 141344 4910 CLIPPED,DETECTED,INEXACT_PSF,SENSOR_EDGE 0x2282c 141356 66 CLIPPED,CR,DETECTED,INEXACT_PSF,INTRP,SENSOR_EDGE 0x22830 141360 30 CLIPPED,DETECTED,EDGE,INEXACT_PSF,SENSOR_EDGE 0x32000 204800 4327525 INEXACT_PSF,REJECTED,SENSOR_EDGE 0x3200c 204812 41000 CR,INEXACT_PSF,INTRP,REJECTED,SENSOR_EDGE 0x32010 204816 66083 EDGE,INEXACT_PSF,REJECTED,SENSOR_EDGE 0x3201c 204828 444 CR,EDGE,INEXACT_PSF,INTRP,REJECTED,SENSOR_EDGE 0x32020 204832 3694722 DETECTED,INEXACT_PSF,REJECTED,SENSOR_EDGE 0x32022 204834 18115 DETECTED,INEXACT_PSF,REJECTED,SAT,SENSOR_EDGE 0x3202c 204844 33706 CR,DETECTED,INEXACT_PSF,INTRP,REJECTED,SENSOR_EDGE 0x3202e 204846 67 CR,DETECTED,INEXACT_PSF,INTRP,REJECTED,SAT,SENSOR_EDGE 0x32030 204848 19706 DETECTED,EDGE,INEXACT_PSF,REJECTED,SENSOR_EDGE 0x3203c 204860 183 CR,DETECTED,EDGE,INEXACT_PSF,INTRP,REJECTED,SENSOR_EDGE 0x32124 205092 155 DETECTED,INEXACT_PSF,INTRP,NO_DATA,REJECTED,SENSOR_EDGE 0x32800 206848 195028 CLIPPED,INEXACT_PSF,REJECTED,SENSOR_EDGE 0x3280c 206860 1683 CLIPPED,CR,INEXACT_PSF,INTRP,REJECTED,SENSOR_EDGE 0x32810 206864 3744 CLIPPED,EDGE,INEXACT_PSF,REJECTED,SENSOR_EDGE 0x3281c 206876 49 CLIPPED,CR,EDGE,INEXACT_PSF,INTRP,REJECTED,SENSOR_EDGE 0x32820 206880 143225 CLIPPED,DETECTED,INEXACT_PSF,REJECTED,SENSOR_EDGE 0x32822 206882 1808 CLIPPED,DETECTED,INEXACT_PSF,REJECTED,SAT,SENSOR_EDGE 0x3282c 206892 1223 CLIPPED,CR,DETECTED,INEXACT_PSF,INTRP,REJECTED,SENSOR_EDGE 0x3282e 206894 1 CLIPPED,CR,DETECTED,INEXACT_PSF,INTRP,REJECTED,SAT,SENSOR_EDGE 0x32830 206896 2462 CLIPPED,DETECTED,EDGE,INEXACT_PSF,REJECTED,SENSOR_EDGE 0x3283c 206908 41 CLIPPED,CR,DETECTED,EDGE,INEXACT_PSF,INTRP,REJECTED,SENSOR_EDGE 0x32924 207140 72 CLIPPED,DETECTED,INEXACT_PSF,INTRP,NO_DATA,REJECTED,SENSOR_EDGE
3.6 Extract a specific plane¶
Calculate the fraction of pixels masked with the cosmic rays flag (CR).
cr_plane = mask.getPlaneBitMask("CR")
cr_mask = (mask.array & cr_plane) != 0
print("Fraction of pixels flagged as CR:", np.mean(cr_mask))
Fraction of pixels flagged as CR: 0.009050778546712802
3.7 Display with Firefly¶
Display the deep_coadd in frame 1, and set the mask transparency to 0 (not transparent; to show the mask).
afw_display.image(deep_coadd)
afw_display.setMaskTransparency(0)
With the mask plane fully opaque, it should look like this:
Figure 1: The mask plane of the r-band
deep_coaddimage for tract 5063, patch 14. The colors correspond to an informative mask flag value (Section 3.2). Almost every pixel has a color (has a nonzero mask value).
Display the mask in Firefly frame 2.
afw_display = afwDisplay.Display(frame=2)
afw_display.image(mask)
The mask plane should look like the image below. Note the coordinates (“WCS”) and values (“Flux”) shown in the lower left: the coordinates are in pixels, and the values correspond to combined integer bit values per pixel (labeled as “Flux,” although in this case they do not represent a physical flux).
Figure 2: The mask plane of the r-band
deep_coaddimage for tract 5063, patch 14.
Set all mask key names to transparent except the "DETECTED" mask bit, and display again in frame 1.
afw_display = afwDisplay.Display(frame=1)
afw_display.setMaskTransparency(100)
afw_display.setMaskTransparency(0, 'DETECTED')
Figure 3: Pixels marked with the
DETECTEDmask bit.
3.8 Display with Matplotlib¶
Mask objects are bitmasks, not booleans.
Each bit encodes a different mask plane, so the numeric values cannot be interpreted as straightforward true/false flags.
As a result, plotting the mask image plane array directly with matplotlib can be misleading or confusing.
However, each individual mask plane can be extracted and plotted using matplotlib to provide a visualization of which pixels are masked by that specific plane across the image.
fig = plt.figure(figsize=(12, 12))
for i, (name, bit) in enumerate(mask.getMaskPlaneDict().items()):
fig.add_subplot(4, 5, i + 1)
plt.imshow(mask.array & 2**bit, vmin=0, vmax=1,
origin='lower', cmap='Greys',
interpolation='nearest')
plt.title(name)
plt.axis('off')
Figure 4: Individual mask planes arrays for a
deep_coaddimage displayed withmatplotlib.
Cleanup.
del mask, values, counts, cr_plane, cr_mask
4. Visit image mask¶
Query for visit_images that overlap coordinates RA, Dec near the center of the ECDFS field, were obtained with the r-band filter, and a within timespan near the start of the LSSTComCam campaign.
ra = 53.076
dec = -28.110
band = "r"
time1 = Time("2024-11-09T00:00:00.0", format="isot", scale="tai")
time2 = Time(60624.0, format="mjd", scale="tai")
timespan = Timespan(time1, time2)
del time1, time2
dataset_refs = butler.query_datasets("visit_image",
where="band.name = :band AND \
visit.timespan OVERLAPS :timespan AND \
visit_detector_region.region OVERLAPS POINT(:ra, :dec)",
bind={"band": band, "timespan": timespan,
"ra": ra, "dec": dec},
order_by=["visit.timespan.begin"])
print(len(dataset_refs))
18
del ra, dec, band, timespan
Get an image.
ref = dataset_refs[1]
visit_image = butler.get(ref)
4.1. Get the mask plane¶
Get the mask plane from the visit_image object.
mask_visit_image = visit_image.getMask()
4.2. Print the mask keys¶
Print the list of mask keys and default color.
show_mask_planes(mask_visit_image)
Mask Plane Bit 2^n Hex Default Color ------------------------------------------------------------ BAD 0 1 0x1 red SAT 1 2 0x2 green INTRP 2 4 0x4 green CR 3 8 0x8 magenta EDGE 4 16 0x10 yellow DETECTED 5 32 0x20 blue DETECTED_NEGATIVE 6 64 0x40 cyan SUSPECT 7 128 0x80 yellow NO_DATA 8 256 0x100 orange VIGNETTED 9 512 0x200 red STREAK 10 1024 0x400 green CLIPPED 11 2048 0x800 blue CROSSTALK 12 4096 0x1000 cyan INEXACT_PSF 13 8192 0x2000 magenta ITL_DIP 14 16384 0x4000 yellow NOT_DEBLENDED 15 32768 0x8000 orange REJECTED 16 65536 0x10000 red SENSOR_EDGE 17 131072 0x20000 green UNMASKEDNAN 18 262144 0x40000 blue INJECTED 19 524288 0x80000 None INJECTED_TEMPLATE 20 1048576 0x100000 None SAT_TEMPLATE 21 2097152 0x200000 None
4.3. Check the values in the mask array.¶
Print a list of the unique mask array values, the number of pixels with that value, and the overlapping masks for pixels with that value.
Warning: Bit values are assigned dynamically and are not guaranteed to be fixed.
values, counts = np.unique(mask_visit_image.array, return_counts=True)
print(f"{'Hex': <8} {'Binary': <6} {'Counts': <8} {'Mask Planes': <30}")
print("-" * 60)
for value, count in zip(values, counts):
hex_value = hex(value)
print(f"{hex_value: <8} {value: <6} {count: <8} {mask_visit_image.interpret(value): <30}")
Hex Binary Counts Mask Planes ------------------------------------------------------------ 0x0 0 14915134 0x5 5 86587 BAD,INTRP 0x6 6 2006 INTRP,SAT 0x7 7 24 BAD,INTRP,SAT 0xc 12 188 CR,INTRP 0x10 16 13254 EDGE 0x15 21 112984 BAD,EDGE,INTRP 0x17 23 44 BAD,EDGE,INTRP,SAT 0x20 32 827038 DETECTED 0x25 37 6098 BAD,DETECTED,INTRP 0x26 38 1519 DETECTED,INTRP,SAT 0x2c 44 15 CR,DETECTED,INTRP 0x30 48 274 DETECTED,EDGE 0x35 53 714 BAD,DETECTED,EDGE,INTRP 0x86 134 664 INTRP,SAT,SUSPECT 0x87 135 1 BAD,INTRP,SAT,SUSPECT 0x97 151 14 BAD,EDGE,INTRP,SAT,SUSPECT 0xa6 166 637 DETECTED,INTRP,SAT,SUSPECT 0x1000 4096 102023 CROSSTALK 0x1005 4101 544 BAD,CROSSTALK,INTRP 0x1006 4102 8 CROSSTALK,INTRP,SAT 0x1010 4112 66 CROSSTALK,EDGE 0x1015 4117 841 BAD,CROSSTALK,EDGE,INTRP 0x1020 4128 5543 CROSSTALK,DETECTED 0x1026 4134 19 CROSSTALK,DETECTED,INTRP,SAT 0x1030 4144 2 CROSSTALK,DETECTED,EDGE 0x1035 4149 23 BAD,CROSSTALK,DETECTED,EDGE,INTRP 0x1086 4230 2 CROSSTALK,INTRP,SAT,SUSPECT 0x10a6 4262 4 CROSSTALK,DETECTED,INTRP,SAT,SUSPECT 0x8020 32800 199726 DETECTED,NOT_DEBLENDED 0x8026 32806 5270 DETECTED,INTRP,NOT_DEBLENDED,SAT 0x802c 32812 25 CR,DETECTED,INTRP,NOT_DEBLENDED 0x8030 32816 92 DETECTED,EDGE,NOT_DEBLENDED 0x8035 32821 494 BAD,DETECTED,EDGE,INTRP,NOT_DEBLENDED 0x8036 32822 5 DETECTED,EDGE,INTRP,NOT_DEBLENDED,SAT 0x8037 32823 54 BAD,DETECTED,EDGE,INTRP,NOT_DEBLENDED,SAT 0x80a6 32934 5384 DETECTED,INTRP,NOT_DEBLENDED,SAT,SUSPECT 0x80b6 32950 4 DETECTED,EDGE,INTRP,NOT_DEBLENDED,SAT,SUSPECT 0x80b7 32951 31 BAD,DETECTED,EDGE,INTRP,NOT_DEBLENDED,SAT,SUSPECT 0x9020 36896 645 CROSSTALK,DETECTED,NOT_DEBLENDED
values, counts = np.unique(mask_visit_image.array, return_counts=True)
print(f"{'Hex': <8} {'Binary': <6} {'Counts': <9} {'Mask Planes': <30}")
print("-" * 60)
for value, count in zip(values, counts):
hex_value = hex(value)
print(f"{hex_value: <8} {value: <6} {count: <9} {mask_visit_image.interpret(value): <30}")
Hex Binary Counts Mask Planes ------------------------------------------------------------ 0x0 0 14915134 0x5 5 86587 BAD,INTRP 0x6 6 2006 INTRP,SAT 0x7 7 24 BAD,INTRP,SAT 0xc 12 188 CR,INTRP 0x10 16 13254 EDGE 0x15 21 112984 BAD,EDGE,INTRP 0x17 23 44 BAD,EDGE,INTRP,SAT 0x20 32 827038 DETECTED 0x25 37 6098 BAD,DETECTED,INTRP 0x26 38 1519 DETECTED,INTRP,SAT 0x2c 44 15 CR,DETECTED,INTRP 0x30 48 274 DETECTED,EDGE 0x35 53 714 BAD,DETECTED,EDGE,INTRP 0x86 134 664 INTRP,SAT,SUSPECT 0x87 135 1 BAD,INTRP,SAT,SUSPECT 0x97 151 14 BAD,EDGE,INTRP,SAT,SUSPECT 0xa6 166 637 DETECTED,INTRP,SAT,SUSPECT 0x1000 4096 102023 CROSSTALK 0x1005 4101 544 BAD,CROSSTALK,INTRP 0x1006 4102 8 CROSSTALK,INTRP,SAT 0x1010 4112 66 CROSSTALK,EDGE 0x1015 4117 841 BAD,CROSSTALK,EDGE,INTRP 0x1020 4128 5543 CROSSTALK,DETECTED 0x1026 4134 19 CROSSTALK,DETECTED,INTRP,SAT 0x1030 4144 2 CROSSTALK,DETECTED,EDGE 0x1035 4149 23 BAD,CROSSTALK,DETECTED,EDGE,INTRP 0x1086 4230 2 CROSSTALK,INTRP,SAT,SUSPECT 0x10a6 4262 4 CROSSTALK,DETECTED,INTRP,SAT,SUSPECT 0x8020 32800 199726 DETECTED,NOT_DEBLENDED 0x8026 32806 5270 DETECTED,INTRP,NOT_DEBLENDED,SAT 0x802c 32812 25 CR,DETECTED,INTRP,NOT_DEBLENDED 0x8030 32816 92 DETECTED,EDGE,NOT_DEBLENDED 0x8035 32821 494 BAD,DETECTED,EDGE,INTRP,NOT_DEBLENDED 0x8036 32822 5 DETECTED,EDGE,INTRP,NOT_DEBLENDED,SAT 0x8037 32823 54 BAD,DETECTED,EDGE,INTRP,NOT_DEBLENDED,SAT 0x80a6 32934 5384 DETECTED,INTRP,NOT_DEBLENDED,SAT,SUSPECT 0x80b6 32950 4 DETECTED,EDGE,INTRP,NOT_DEBLENDED,SAT,SUSPECT 0x80b7 32951 31 BAD,DETECTED,EDGE,INTRP,NOT_DEBLENDED,SAT,SUSPECT 0x9020 36896 645 CROSSTALK,DETECTED,NOT_DEBLENDED
4.4 Display with Firefly¶
Display the visit_image in frame 1, and set the mask transparency to 0 (not transparent; to show the mask).
afw_display = afwDisplay.Display(frame=1)
afw_display.image(visit_image)
afw_display.setMaskTransparency(0)
With the mask fully opaque, it should look like this:
Figure 6:
visit_imageimage with mask overlaid.
Display the mask in Firefly frame 2.
afw_display = afwDisplay.Display(frame=2)
afw_display.image(mask_visit_image)
The mask plane should look like the image below.
Figure 7: Mask plane of the
visit_imageimage above.
Set all mask key names to transparent except the "DETECTED" mask bit, and display again in frame 1.
afw_display = afwDisplay.Display(frame=1)
afw_display.setMaskTransparency(100)
afw_display.setMaskTransparency(0, 'DETECTED')
Figure 8:
DETECTEDmask plane of thevisit_imageimage above.
4.5 Display with Matplotlib¶
Mask objects are bitmasks, not booleans.
Each bit encodes a different mask plane, so the numeric values cannot be interpreted as straightforward true/false flags.
As a result, plotting the mask image plane array directly with matplotlib can be misleading or confusing.
However, each individual mask plane can be extracted and plotted using matplotlib to provide a visualization of which pixels are masked by that specific plane across the image.
fig = plt.figure(figsize=(12, 12))
for i, (name, bit) in enumerate(mask_visit_image.getMaskPlaneDict().items()):
fig.add_subplot(5, 5, i + 1)
plt.imshow(mask_visit_image.array & 2**bit, vmin=0, vmax=1,
origin='lower', cmap='Greys',
interpolation='nearest')
plt.title(name)
plt.axis('off')
Clean up.
del mask_visit_image