Receiver

DeepSpaceTelemetry.ReceiverModule
Receiver

The ground-station loop and post-processing: bandwidth-paced ingestion with stochastic loss and retransmission, the retention custodian, metrics and events_rx.csv recording, and the derived products (mission/session figures, the 2D batch-state mask timeline, batch epoch map). Re-entrant: a restarted receiver reseeds retry and custodial state from the event log.

source
DeepSpaceTelemetry.Receiver.generate_mission_plotsFunction
generate_mission_plots(run_dir::String; style, plots_dir, formats, suffix) -> Vector{String}

Reads mission_profile.csv and renders the mission summary (plot_mission_summary) and one session figure per contact window (plot_session) into plots_dir (default <run_dir>/plots) in formats (default PNG + PDF) with the file-name suffix, all under the telemetry theme of style (PlotTheme.PlotStyle); returns the paths written. Windows are enumerated from the contact model — the nominal daily passes, scheduled or generated, and the low-latency periods — not detected from the effective bandwidth, so a fully blacked-out day still receives its zero-throughput figure and file names share the summary's 0-based day coordinates.

source
DeepSpaceTelemetry.Receiver.PlotContextType
PlotContext

Per-run inputs shared by the mission summary and the session figures: the metrics frame with its elapsed-hour axis, the mission epoch, the visibility and link models, the disruption, component-outage, low-latency and event-marker spans in plot coordinates, and the loss-panel policy. Built once by plot_context.

source
DeepSpaceTelemetry.Receiver.plot_contextFunction
plot_context(run_dir::String, df::DataFrame, cfg::AbstractDict) -> PlotContext

Assembles the PlotContext of a run from its metrics frame and its configuration snapshot. The time axis is anchored at start_sim_time — not at the first metrics row, which lands whenever the receiver first flushes — so day ticks and disruption shading sit exactly on mission-day boundaries; a legacy or corrupt snapshot falls back to the first row. A malformed disruption section warns and yields an empty timeline rather than aborting the post-processing of an otherwise complete run.

source
DeepSpaceTelemetry.Receiver.plot_mission_summaryFunction
plot_mission_summary(ctx::PlotContext) -> String

Renders the mission summary — capacity with the onboard buffer on a twin axis, cumulative received batches (total and archive share), and, when the loss channel was active, the Lost strip — to <run_dir>/plots/mission_summary_global.png with a vector PDF twin. Must run inside the telemetry theme. Returns the PNG path.

source
DeepSpaceTelemetry.Receiver.plot_state_rasterFunction
plot_state_raster(run_dir::String; style, plots_dir, formats, suffix) -> Union{Nothing,String}

Renders masks/telemetry_mask_timeline.csv as a raster — one column per batch, one row per recorded event, one color per state — to <plots_dir>/state_raster.png with a vector twin, and returns its path (nothing when the timeline is absent, so a run that skipped generate_telemetry_masks is not an error). Must run inside the telemetry theme.

The figure is the routing doctrine in one panel: the boundary between the future wash and the onboard color is generation, each pass turns a block of columns to the ground color, and within a block the higher batch identifiers turn first — the LIFO backfill, advancing backwards in batch identifier. What survives to the top of the figure in the onboard color is the backlog the run never cleared.

source
DeepSpaceTelemetry.Receiver.raster_figureFunction
raster_figure(states, hours, style, plots_dir, formats, suffix) -> String

The raster itself, once plot_state_raster has read the timeline: states is one row per recorded event and one column per batch, hours the mission hour of each row. Must run inside the telemetry theme.

source
DeepSpaceTelemetry.Receiver.session_figure_stemsFunction
session_figure_stems(model, t_start::DateTime, t_end::DateTime) -> Vector{Tuple{String,ContactWindow}}

File-name stems of the session figures of every contact window of model overlapping [t_start, t_end] (TelemetryCore.contact_windows): day<kk> from the 0-based mission day of the window start, _low_latency appended for low-latency periods, and a letter suffix (b, c, …) when several windows of the same kind start on the same day.

source
DeepSpaceTelemetry.Receiver.plot_sessionFunction
plot_session(ctx::PlotContext, window::TelemetryCore.ContactWindow, stem::String; style, plots_dir, formats, suffix) -> Union{Nothing,String}

Renders the session figure of one contact window — a nominal pass or a low-latency period: smooth nominal and effective capacity with the onboard buffer on a twin axis, and the batches received within the window (total and archive share) with ✕ pins and a count badge for any losses — to <run_dir>/plots/session_<stem>_detail.png with a vector PDF twin (session_figure_stems names the stems). Returns nothing when the window lies outside the recorded span or holds fewer than two metrics rows. Must run inside the telemetry theme.

source
DeepSpaceTelemetry.Receiver.hours_sinceFunction
hours_since(t::DateTime, t0::DateTime) -> Float64

Elapsed mission hours from t0 to t — the plot-coordinate transform of every figure (time axes are anchored at start_sim_time, 0-based days).

source
DeepSpaceTelemetry.Receiver.component_outage_spansFunction
component_outage_spans(run_dir, t_start, x_end) -> Vector{NTuple{2,Float64}}

Component-outage windows from the supervisor's component_events.csv: each down opens a window closed by the next restart of the same component, or by the mission end x_end [h]. Empty when the record is absent.

source
DeepSpaceTelemetry.Receiver.generation_gap_spansFunction
generation_gap_spans(run_dir, t_start, x_end, tag) -> Vector{NTuple{2,Float64}}

Generation-gap windows from the emitter's events_tx.csv: gap_start / gap_end pairs whose Batch column equals tag (SCHEDULED for planned gaps, RECORDER for recorder overflows, STREAM for outages recorded by the supervisor), in hours since t_start; an unclosed gap ends at x_end.

source
DeepSpaceTelemetry.Receiver.low_latency_spansFunction
low_latency_spans(model::TelemetryCore.VisibilityModel, t_start, x_end) -> Vector{NTuple{2,Float64}}

Low-latency periods of the run — scheduled ones and those triggered by an event marker — as (start, stop) pairs in hours since t_start, clipped to [0, x_end]. Empty when contacts.low_latency_enabled is unset, the TelemetryCore.VisibilityModel then carrying no such window.

source
DeepSpaceTelemetry.Receiver.marker_timesFunction
marker_times(run_dir::String, t_start::DateTime) -> Vector{Float64}

Declared event markers of the run, in hours since t_start, read from the run's own markers.csv. Empty when the run declared none or predates the marker record — the figures then draw no marker rules.

source
DeepSpaceTelemetry.Receiver.spans_overlapFunction
spans_overlap(spans, x_lo, x_hi, lo, hi) -> Bool

true when any span's [s[lo], s[hi]] phase intersects the plotted window [x_lo, x_hi]. Legends must only advertise what their own figure draws, so blackout (lo = 1, hi = 2) and recovery-ramp (lo = 2, hi = 3) phases are gated independently.

source
DeepSpaceTelemetry.Receiver.shade_disruptions!Function
shade_disruptions!(ax, x_lo, x_hi, disruption_spans; style)

Shades every disruption event onto ax, clamped to the plotted range: a uniform wash over the blackout, fading linearly to zero alpha across the recovery ramp (mirroring the capacity ramp), with dashed same-hue lines at the data line width of style delimiting event start and full recovery. All shading is pushed far back along z so it renders behind the data identically on every panel — but strictly above z = -100, where the white background of a twin axis (dual-y panels) would cover it.

source
DeepSpaceTelemetry.Receiver.shading_patchFunction
shading_patch(fill, edge, linestyle::Symbol, style::PlotTheme.PlotStyle) -> Vector

Legend entry of a shaded event window: the fill patch under a line in the color and line style of the window's edge lines, at the legend line weight of style.

source
DeepSpaceTelemetry.Receiver.shade_outages!Function
shade_outages!(ax, x_lo, x_hi, outage_spans; color, edgecolor, linestyle, style)

Shades component-outage windows onto ax, clamped to the plotted range: a neutral wash (PlotTheme.COLOR_OUTAGE) with dotted same-hue edge lines at the data line width of style, pushed behind the data. Distinct from the configured disruption shading — these are unscheduled infrastructure outages.

source
DeepSpaceTelemetry.Receiver.shade_generation_gaps!Function
shade_generation_gaps!(ax, x_lo, x_hi, ctx::PlotContext; style)

Scheduled generation gaps (onboard-family color, dash-dot edges) and recorder overflows (loss color, dash-dot edges) behind the data of ax, edge lines at the data line width of style.

source
DeepSpaceTelemetry.Receiver.shade_low_latency!Function
shade_low_latency!(ax, x_lo, x_hi, ctx::PlotContext; style)

Low-latency periods behind the data of ax, in the capacity color at low alpha with dotted same-hue edges — the periods run at low_latency_capacity_fraction of peak capacity, so the wash sits under the capacity curve it explains.

source
DeepSpaceTelemetry.Receiver.mark_events!Function
mark_events!(ax, x_lo, x_hi, times; style)

Draws one upright rule per declared event marker onto ax, clamped to the plotted range, in PlotTheme.COLOR_MARKER at the data line width of style and behind the data. The rule is solid, the one vertical style no shaded window uses for its edges, so a marker never reads as an event boundary. The markers are the instants at which the alert-latency metric is evaluated, and the origin of any triggered low-latency period.

source
DeepSpaceTelemetry.Receiver.figure_legend_entriesFunction
figure_legend_entries(; degraded, blackout, ramp, lost, outage = false, …) -> (elements, labels)

Legend elements and labels of a figure, with composite fill+edge patches for the band+stair pairs. Entries are strictly limited to what that figure draws: degraded swaps the single capacity entry for the nominal/effective pair, blackout/ramp/outage/scheduled_gap/recorder/low_latency gate the shading patches, marker gates the event-marker rule, and lost is :strip (summary stairs + marks), :marks (session ✕ pins), or :none. Labels shorten below the narrow-figure threshold of PlotTheme.label: a single-column export fits three legend columns with the short forms and two with the long ones, and the rows it saves are panel height.

Returned separately from add_figure_legend! so a caller can size its figure for the legend it is about to place (legend_banks).

source
DeepSpaceTelemetry.Receiver.legend_banksFunction
legend_banks(labels::Vector{String}, style::PlotTheme.PlotStyle) -> Int

Number of rows of the horizontal figure legend so that no row runs past the figure width. Makie packs a horizontal legend column-major into nbanks rows, so a row is as wide as the sum of the widest entry of each column; entry widths are estimated as the patch and its gap plus the label at 0.45 em per character (measured for the Computer Modern face), and the smallest row count whose widest row fits the figure width less the padding is returned.

source
DeepSpaceTelemetry.Receiver.upright_rulesFunction
upright_rules(ctx::PlotContext) -> Vector{Float64}

Every x position at which a figure of ctx draws an upright rule: the boundaries of the disruption, outage, generation-gap and low-latency windows, and the event markers. In-axis annotations pick their end of the axis against this list (PlotTheme.annotation_side), so a rule never crosses a text block.

source
DeepSpaceTelemetry.Receiver.LOST_STRIP_SHAREConstant
LOST_STRIP_SHARE

Row share of the Lost strip against a full panel of the mission summary: the strip carries rare discrete events and needs about a third of the height its neighbours do. Shared by the layout and by the height floor (summary_figure_height), which sizes the figure so the strip's label clears the panel above.

source
DeepSpaceTelemetry.Receiver.summary_figure_heightFunction
summary_figure_height(style, legend_rows, panels, base_height) -> Int

Height of a stacked figure in Makie units: base_height, the height the figure would take from its width alone, raised whenever the rotated y-labels of two adjacent panels would meet. panels pairs each panel's y-label with its row share, top to bottom.

A rotated label is centred on its panel and overruns it freely, so the constraint is not that a label fit its own panel but that two neighbours keep apart: the distance between the centres of adjacent panels, (hᵢ + hᵢ₊₁)/2, must exceed half the sum of their label extents. Solving that for the axes height and adding the legend and the x-decorations gives the floor. At the design width it never binds; below about 100 mm, where the label sizes hold at their 7 pt floor while the panels keep shrinking, it does.

source
DeepSpaceTelemetry.Receiver.summary_tick_step_hoursFunction
summary_tick_step_hours(total_days) -> Float64

Day-tick spacing of the mission summary [h]: the smallest step of 1, 2, 5, 10, 20, 30, or 60 days that places at most eleven Day n labels on the axis (the labels touch beyond that at the design width), 120 days beyond.

source
DeepSpaceTelemetry.Receiver.BatchStatesType
BatchStates

Alias for the per-snapshot batch-location record shared by the mask generator and the GIF animation: batch-ID vectors for every (stage × stream) bucket plus the terminal lost bucket.

source
DeepSpaceTelemetry.Receiver.reconstruct_batch_statesFunction
reconstruct_batch_states(run_dir::String, df::DataFrame)

Exact replay of every batch's location from the ground-truth event logs (events_tx.csv: gen/tx milestones written by the emitter; events_rx.csv: ingested/lost milestones written by the receiver — the state-preserving retry events are skipped). Returns one BatchStates record per mission_profile.csv row, evaluated at that row's SimTime.

Each packet loss is attributed to its exact batch ID, which is what makes mask state 4 = Lost possible. Emitter and receiver stamp milestones from separate clock reads, so recorded timestamps can invert within a batch at high speed-up; the replay enforces per-batch causal order (gentx → terminal) with later stages absorbing, keeping every batch's state sequence monotone.

source
DeepSpaceTelemetry.Receiver.generate_telemetry_masksFunction
generate_telemetry_masks(run_dir::String)

A post-processing utility that reconstructs the LIFO/FIFO transmission state machine from the event logs (see batch_states). It outputs a 2D matrix telemetry_mask_timeline.csv where rows are time steps and columns are specific Batch_IDs, indicating their exact physical location (0=Future, 1=Onboard, 2=Link, 3=Ground, 4=Lost).

source
DeepSpaceTelemetry.Receiver.delivered_payload_queueFunction
delivered_payload_queue(run_dir::String, ground_path::String)
    -> Vector{Tuple{DateTime,String,Int}}

Materializes the retention custodian's pruning queue from the run's ground census and events_rx.csv: delivered (ingested) batches whose payload has not been pruned, oldest-ingested first, each with its current seg_*.csv payload size in bytes. Consulted at startup for the payload tally and lazily on watermark breach, so the in-memory queue stays empty outside breach episodes.

source
DeepSpaceTelemetry.Receiver.expand_pointwise_maskFunction
expand_pointwise_mask(run_dir, total_points, event_idx, output_path) -> Int

Expands one row of masks/telemetry_mask_timeline.csv (event_idx; -1 selects the final snapshot) into a point-wise 0/1 availability array of total_points samples — 1 where the owning batch is on the ground (state 3); states 0 (future), 1 (onboard), 2 (link), and 4 (lost) stay 0, a lost batch never becoming available — and writes it as Time_Index, Ground_Available to output_path (with safe_csv_write rotation). Points per batch follow the run's own configuration snapshot. Returns the number of available points; throws an ArgumentError when the mask file is absent or event_idx lies outside the timeline.

source
DeepSpaceTelemetry.Receiver.run_receiverFunction
run_receiver(clock, link, run_id; ...)

The main ground-station loop. It continually checks the link/ directory for incoming data batches, simulates a delay based on the effective link capacity (visibility profile × disruption factor), draws a stochastic loss realization per transfer attempt from loss_model, moves successful batches to ground/ and exhausted ones to lost/, and — when status_panel is set — renders a console status panel to orig_stdout.

A lost transfer leaves the batch on the link; its retransmission is served no earlier than one round-trip light time after the loss was detected (round_trip_light_time_sec, deferred negative acknowledgement), while the other in-flight batches keep being served; after max_retries failed attempts the batch is moved to lost/ — never deleted — which frees the emitter's transmission window slot (in-flight occupancy is the link/ listing). Every milestone is appended to events_rx.csv for exact post-processing reconstruction. At startup, a re-attaching receiver reseeds retry and custodial state from the event log and synthesizes ingested records (at the re-attach instant) for batches delivered to ground/ whose record was lost to a crash between the delivery move and the log append.

When retention.enabled the loop also runs the retention custodian: once the delivered-payload tally exceeds watermark_bytes, the oldest-ingested batches beyond the grace mission-time guarantee have their seg_*.csv payload files deleted — the batch directory keeps metadata.json, gains a PRUNED marker, and a pruned event is appended to events_rx.csv. Event logs, metrics, masks, and lost/ are never pruned. The pruning queue is materialized lazily on watermark breach (delivered_payload_queue).

Keyword arguments

  • orig_stdout: stream receiving the console status panel.
  • status_panel: render the clear-screen console status panel (mission day, link state, ground and lost tallies) to orig_stdout on every loop iteration; off by default, the supervisor sets it from dashboard.receiver_status_panel.
  • batch_transfer_sec: transfer time of one batch at full link capacity [mission s] (telemetry_settings(cfg).nominal_batch_transfer_sec).
  • loss_model: stochastic packet-loss channel (ChannelEffects.LossModel).
  • max_retries: failed attempts before a batch moves to lost/.
  • retention: the custodian's TelemetryCore.RetentionPolicy.
  • deadline: absolute wall-clock stop shared by both components.
  • stop: cooperative stop flag raised by the supervisor.
  • heartbeat_path: liveness file touched once per second when set.
  • min_link_factor: capacity floor below which no transfer is attempted.
  • round_trip_light_time_sec: earliest retransmission delay after a detected loss [mission s]; 0.0 retries immediately.
source