Saturation
wcc-etc tracks detector saturation at the brightest-pixel level so you can
tell whether an exposure clips before you commit to it.
The peak pixel
get_peak_pixel() returns the value of the brightest
pixel for a given exposure time, summing source, background, dark current, and
bias:
sim.get_peak_pixel(60, units="e-") # electrons
sim.get_peak_pixel(60, units="adu") # ADU (uses gain + bias)
time may be a scalar or an array.
The saturation flag
is_saturated() compares the peak pixel in ADU to the
sensor’s ADC maximum (adc_max = 2**bit_depth - 1):
sim.is_saturated(60) # True / False
sim.is_saturated(np.array([10, 60])) # array of bools
The relevant sensor properties are bit_depth,
bias_level, and adc_max. For
example, the Sony IMX455 (sony:*) is 16-bit
(adc_max = 65535) and the qCMOS (qcmos:*) is 12-bit
(adc_max = 4095).
Saturation in the image and SNR paths
A simulated image carries a per-pixel mask:
img = imsim.simulate(time=60, add_noise=True)
img.saturation_mask.any() # did anything saturate?
The image-based SNR methods also report saturation of the rendered per-frame
image via the n_saturated (count) and saturated (bool) keys in their
result dict, and emit a warning when a pixel clips (unless warn=False):
r = sim.get_snr(60)
r["saturated"], r["n_saturated"]
Tip
When using multiple reads, saturation is evaluated per frame — a long total exposure split into several reads may avoid clipping that a single long frame would hit.