Simulation (esc_etc.simulation)
Top-level ESC ETC orchestrator: composes Telescope, Sensor, Scene, Coronagraph.
count_rate_components extracts Observatory.make_observation: it normalizes the host on the FPM-free Sensor.bandpass, derives planet/speckle by scaling, computes zodi/exozodi with the resel factor, then multiplies EVERY rate by the flat FPM throughput k = coronagraph.off_axis_throughput (plan physics-fact #1).
Every SNR term is evaluated in ONE photometric aperture, chosen by
Sensor.aperture (the resel, Omega = pi (lambda/2D)^2, by default; issue #10)
with encircled energy EE = Sensor.ee_fraction for point sources:
R_planet = R_planet,ref * k * EE planet spectrum normalised dmag
fainter than the host; k = FPM
off-axis throughput
R_speckle = R_host * C * k * EE C = raw contrast, see Coronagraph
R_zodi = SB_zodi * Omega * k (exozodi likewise)
N_pix = Omega / plate_scale^2 (dark current, read noise)
k on the diffuse terms stands in for the diffuse-background transmission. ponytail: assumed equal to the point-source core throughput; split it out when the FPM data records total transmission separately.
- class esc_etc.simulation.Simulation(telescope, sensor, scene, coronagraph, noise_model=None)[source]
Bases:
_MetaHolder_A telescope, sensor, scene and coronagraph, turned into SNR and time.
Build one with
from_default()orfrom_components(). Change parameters withupdate(child__param=...)and put everything back withreset(). Times passed to the methods may be astropy quantities or plain numbers in seconds. Every standard plot is aplot_*method.- classmethod from_default(hoststarmag=-0.353, planetdeltamag=20.0, contrast=1e-08, ppgain=10, separation=0.2, bg_flux=22.5, exobg_flux=21.0, arm='arm_a', mag_system='vega', hoststar_band=None, filter='F630N', lifetime='eol')[source]
See
get_scenefor what band each magnitude is quoted in.filter(a key ofesc_etc.FILTERSsuch as"R1"/"F620N", defaultesc_etc.DEFAULT_FILTER) uses that ESC filter’s measured curve as the full sensor bandpass and its design wavelength as the telescope’s central wavelength.lifetimepicks the"eol"(end of life, default) or"bol"curve set.filter=Noneis the legacy option: the generic box-filter chain assembled from the configuration files, which has no BOL/EOL variants.
- get_snr(total_time, frame_time)[source]
SNR after
total_timeon target in frames offrame_time.Both times accept astropy quantities or plain numbers (seconds). Returns a dict with
snr,signal_e,noise_e,reference_noise_e,science_time,charged_timeand the speckle floor rateM. Warns when a frame would saturate.
- get_int_time_for_snr(snr, frame_time)[source]
Integration time to reach
snrwith frames offrame_time(quantity or seconds).Returns
int_time(whole frames),int_time_continuous(exact) and thenoise_termsrates. NaN whensnris above the speckle plateau.
- saturation_time()[source]
Frame time at which the brightest dark-hole pixel reaches
sensor.headroom * sensor.well_depth.Planet and speckle put
sensor.peak_pixel_fractionof their in-aperture rate on the peak pixel; zodi and exozodi spread uniformly overnum_psf_pixels; dark current adds per pixel. The occulted host is out of scope: this is the dark-hole science ROI, not the stellar core behind the FPM.
- is_saturated(frame_time)[source]
True when a frame of
frame_time(quantity or seconds) exceedssaturation_time().
- plot(**kw)[source]
2 x 3 overview; see
esc_etc.plotting.plot_overview().
- plot_snr_vs_time(**kw)[source]
See
esc_etc.plotting.plot_snr_vs_time()(supportssweep=).