Signal-to-noise and integration time
The signal-to-noise calculation lives in
AnalyticCoronagraphNoiseModel, the default noise_model
of a Simulation. It is an analytic photometric model that
works on the per-second electron rates returned by
count_rate_components(), all evaluated in the same
photometric aperture of \(N_\mathrm{pix}\) detector pixels
(Sensor.num_psf_pixels, see Concepts and architecture).
The noise budget
For an on-target integration \(t\) read out in frames of duration \(t_\mathrm{frame}\), the signal is the planet rate times the integration time and the noise variance, in electrons squared, is
The terms, in order:
Photon noise of the planet, the zodiacal and exozodiacal backgrounds, and the residual starlight (speckles). Each is a rate times the integration time.
Dark current, \(R_\mathrm{dark}\) per pixel, over the aperture.
Read noise, \(\sigma_\mathrm{read}\) per pixel per read, over the aperture and over \(N_\mathrm{reads} = \lceil t / t_\mathrm{frame} \rceil\) reads: whole frames plus one shorter final frame, and never fewer than one. An integration shorter than a frame is still one read.
Reference subtraction, present only with reference differential imaging (RDI): the scaled random variance of the subtracted reference image, \(\kappa = 1 / (\beta\,\tau)\), where \(\beta\) is the reference-to-host brightness ratio and \(\tau = t_\mathrm{ref} / t\) the reference-to-science time ratio. \(\mathrm{var}_\mathrm{ref}\) holds the reference’s speckle (scaled by \(\beta\)), zodi, exozodi, dark and read terms over \(t_\mathrm{ref}\). See the next section.
The post-processed speckle floor, a systematic term with \(M = R_\mathrm{speckle} / \mathrm{ppgain}\) (the coronagraph’s
noise floor factor).ppgainis an assumed suppression factor for the residual speckle pattern; the ETC does not predict post-processing performance.
The floor term grows linearly with time, exactly as the signal does, so at long integrations the SNR stops improving and tends to
At the default configuration the planet and speckle rates are equal, so
\(\mathrm{SNR}_\mathrm{max}\) is the ppgain of 10. The ceiling moves
with a lower raw_dh_contrast (fewer speckle photons) or a higher
ppgain; see Coronagraph and contrast.
Observing strategy
coronagraph.subtraction states what is assumed:
"none"(default): one science image; the budget above without the reference term."rdi": reference differential imaging. A reference starref_brightness_ratiotimes brighter than the host is observed forref_time_ratiotimes the science time, scaled to the target and subtracted. Roll subtraction and angular differential imaging are not modelled.
total_time is always the on-target science time. The result also reports
science_time, charged_time (the total telescope time, science plus
reference for RDI) and reference_noise_e, the reference’s contribution
in electrons:
sim.update(coronagraph__subtraction="rdi",
coronagraph__ref_brightness_ratio=5.0, # reference 5x brighter
coronagraph__ref_time_ratio=0.5) # observed for half the time
r = sim.get_snr(total_time=3600, frame_time=100)
r["reference_noise_e"], r["charged_time"] # -> ..., 5400 s
Computing SNR
result = sim.get_snr(total_time=3600, frame_time=100)
result["snr"] # signal-to-noise ratio
result["signal_e"] # planet electrons in total_time
result["noise_e"] # total noise (electrons)
result["M"] # post-processed speckle floor rate
result["reference_noise_e"], result["science_time"], result["charged_time"]
Inverting for integration time
get_int_time_for_snr() solves the same expression
for the integration time needed to reach a target SNR at a given
frame_time:
inv = sim.get_int_time_for_snr(snr=10, frame_time=100)
inv["int_time"] # whole frames: the shortest realizable schedule
inv["int_time_continuous"] # closed-form inversion with fractional reads
inv["noise_terms"] # [dark, read, zodi, exozodi, speckle, reference] rates
int_time rounds the closed-form solution up to a whole number of frames,
so it is always achievable and meets the target SNR; int_time_continuous
is the unrounded value. Non-positive times, target SNRs or ppgain, and a
negative contrast, raise ValueError; a frame_time above
saturation_time() emits a warning.
Important
A target SNR above \(\mathrm{SNR}_\mathrm{max}\) cannot be reached by
integrating longer; those entries come back as nan. Lower
raw_dh_contrast or raise ppgain to lift the ceiling.
Saturation
frame_time is bounded from above by detector saturation and from below by
read noise, which grows with the number of reads. Saturation explains
how saturation_time() and
is_saturated() bracket that choice:
sim.saturation_time() # seconds
sim.is_saturated(100) # True / False
Swapping the noise model
The noise model is a constructor argument, so you can pass your own object
with snr and int_time_for_snr methods (for instance an image-based
model) through Simulation.from_components.