Complete reference for tuning Aethelix's behavior.
Default values (in source code)
(down)
Configuration file (if present)
(down)
Runtime parameters (in function calls)
(down)
Environment variables (optional)
Each level overrides the one above it.
from simulator.power import PowerSimulator
sim = PowerSimulator(
duration_hours=24, # Simulation length
sampling_rate_hz=0.1, # Telemetry frequency
initial_soc=95.0, # Initial battery state of charge (%)
nominal_solar_input=600.0, # Nominal solar power (W)
nominal_bus_voltage=28.0, # Nominal bus voltage (V)
)
# Nominal scenario (healthy satellite)
nominal = sim.run_nominal(
eclipse_duration_hours=0.5, # Orbital eclipse duration
eclipse_depth=1.0, # Eclipse depth (1.0 = total darkness)
)
# Degraded scenario (with faults)
degraded = sim.run_degraded(
# Solar panel fault
solar_degradation_hour=6.0, # Start time (hours)
solar_factor=0.7, # Remaining efficiency (0.7 = 30% loss)
# Battery aging fault
battery_degradation_hour=8.0,
battery_factor=0.8, # Remaining efficiency (0.8 = 20% loss)
)| Parameter | Type | Default | Range | Effect |
|---|---|---|---|---|
duration_hours |
float | 24 | 0.1-720 | Total simulation time |
sampling_rate_hz |
float | 0.1 | 0.01-10 | Telemetry sample frequency |
initial_soc |
float | 95.0 | 0-100 | Starting battery charge |
nominal_solar_input |
float | 600.0 | 100-1000 | Healthy solar power |
nominal_bus_voltage |
float | 28.0 | 20-36 | Nominal voltage |
eclipse_duration_hours |
float | 0.5 | 0-12 | Darkness time per orbit |
eclipse_depth |
float | 1.0 | 0-1.0 | Darkness intensity |
solar_degradation_hour |
float | 6.0 | 0-duration | Fault start time |
solar_factor |
float | 0.7 | 0-1.0 | Efficiency multiplier |
battery_degradation_hour |
float | 8.0 | 0-duration | Fault start time |
battery_factor |
float | 0.8 | 0-1.0 | Efficiency multiplier |
from simulator.thermal import ThermalSimulator
sim = ThermalSimulator(
duration_hours=24,
sampling_rate_hz=0.1,
ambient_temp=3.0, # Space temperature (K)
battery_capacity=100.0, # Battery Wh
)
# Nominal thermal scenario
nominal = sim.run_nominal(
solar_input, # From power simulator
battery_charge, # From power simulator
battery_voltage, # From power simulator
)
# Degraded with cooling failure
degraded = sim.run_degraded(
solar_input,
battery_charge,
battery_voltage,
battery_cooling_hour=8.0, # Start time
battery_cooling_factor=0.5, # Effectiveness (0.5 = 50% loss)
)| Parameter | Type | Default | Range | Effect |
|---|---|---|---|---|
ambient_temp |
float | 3.0 | 1-300 | Absolute space temperature |
battery_capacity |
float | 100.0 | 10-1000 | Watt-hours |
battery_cooling_hour |
float | 8.0 | 0-duration | Cooling fault start |
battery_cooling_factor |
float | 0.5 | 0-1.0 | Cooling effectiveness |
from analysis.residual_analyzer import ResidualAnalyzer
analyzer = ResidualAnalyzer(
deviation_threshold=0.15, # Anomaly threshold (15% = 15% deviation)
smoothing_window=10, # Moving average window size
severity_scaling=1.0, # Severity score multiplier
)
stats = analyzer.analyze(nominal, degraded)| Parameter | Type | Default | Effect |
|---|---|---|---|
deviation_threshold |
float (0-1) | 0.15 | What's considered an anomaly |
smoothing_window |
int | 10 | Samples for moving average |
severity_scaling |
float | 1.0 | Multiply all severity scores |
Deviation Threshold Guidance:
0.05(5%): Very sensitive, many false positives0.10(10%): Sensitive, good for real-time monitoring0.15(15%): Standard, balances sensitivity and specificity0.20(20%): Conservative, misses subtle anomalies0.30(30%): Very conservative, only major faults
The causal graph is configured in causal_graph/graph_definition.py:
from causal_graph.graph_definition import CausalGraph
graph = CausalGraph()
# Inspect configuration
print(f"Root causes: {[n.name for n in graph.root_causes]}")
print(f"Intermediates: {[n.name for n in graph.intermediates]}")
print(f"Observables: {[n.name for n in graph.observables]}")-
Root Causes (7 nodes)
- Solar degradation
- Battery aging
- Battery thermal stress
- Sensor bias
- Panel insulation failure
- Heatsink failure
- Radiator degradation
-
Intermediates (8 nodes)
- Solar input
- Battery state
- Battery temperature
- Bus regulation
- Battery efficiency
- Thermal stress
- Payload state
- Bus current
-
Observables (8 nodes)
- Measured solar input
- Measured battery voltage
- Measured battery charge
- Measured bus voltage
- Measured battery temperature
- Measured solar panel temperature
- Measured payload temperature
- Measured bus current
To extend or customize the causal graph:
from causal_graph.graph_definition import CausalGraph, Node, Edge
# Create custom graph
class CustomGraph(CausalGraph):
def __init__(self):
super().__init__()
# Add new node
new_cause = Node(
name="radiator_degradation_new",
node_type="root_cause"
)
self.root_causes.append(new_cause)
self.nodes.append(new_cause)
# Add new edge
new_edge = Edge(
source="radiator_degradation_new",
target="battery_temp",
weight=0.7,
mechanism="Poor radiator efficiency reduces heat dissipation"
)
self.edges.append(new_edge)
# Use custom graph
graph = CustomGraph()
ranker = RootCauseRanker(graph)See Causal Graph Design for detailed structure.
from causal_graph.root_cause_ranking import RootCauseRanker
ranker = RootCauseRanker(
graph,
prior_probabilities=None, # Uniform by default
consistency_weight=1.0, # How much consistency affects score
severity_weight=1.0, # How much severity affects score
)
hypotheses = ranker.analyze(
nominal,
degraded,
deviation_threshold=0.15,
confidence_threshold=0.5, # Minimum confidence to report
)Set custom prior probabilities (before evidence):
priors = {
"solar_degradation": 0.3, # 30% prior (more likely a priori)
"battery_aging": 0.2, # 20%
"battery_thermal": 0.1, # 10%
# ... others
}
ranker = RootCauseRanker(graph, prior_probabilities=priors)Use cases:
- Historical data shows solar faults are more common: increase solar prior
- In winter, thermal faults are rare: decrease thermal prior
- New satellite with known issues: adjust based on fleet data
Customize how scores are computed:
ranker = RootCauseRanker(
graph,
consistency_weight=2.0, # Consistency is more important
severity_weight=0.5, # Severity is less important
)- High
consistency_weight: Favor hypotheses consistent with graph - High
severity_weight: Favor hypotheses with strong evidence
from visualization.plotter import TelemetryPlotter
plotter = TelemetryPlotter(
figsize=(14, 10), # Figure size in inches
dpi=150, # Resolution
style="default", # Matplotlib style
)
plotter.plot_comparison(
nominal,
degraded,
degradation_hours=(6, 24), # Highlight period
save_path="output/plot.png",
)
plotter.plot_residuals(
nominal,
degraded,
save_path="output/residuals.png",
)| Parameter | Type | Default | Effect |
|---|---|---|---|
figsize |
tuple | (14, 10) | Width x height in inches |
dpi |
int | 150 | Resolution (dots per inch) |
style |
str | "default" | Matplotlib style |
degradation_hours |
tuple | (6, 24) | Highlight period |
Create aethelix_config.yaml:
# Simulation
simulation:
duration_hours: 24
sampling_rate_hz: 0.1
initial_soc: 95.0
# Power faults
power_faults:
solar_degradation_hour: 6.0
solar_factor: 0.7
battery_degradation_hour: 8.0
battery_factor: 0.8
# Thermal faults
thermal_faults:
battery_cooling_hour: 8.0
battery_cooling_factor: 0.5
# Analysis
analysis:
deviation_threshold: 0.15
smoothing_window: 10
# Visualization
visualization:
figsize: [14, 10]
dpi: 150
style: default
# Inference
inference:
consistency_weight: 1.0
severity_weight: 1.0Load configuration:
import yaml
with open("aethelix_config.yaml") as f:
config = yaml.safe_load(f)
power_sim = PowerSimulator(**config["simulation"])
power_deg = power_sim.run_degraded(**config["power_faults"])
analyzer = ResidualAnalyzer(**config["analysis"])Set options via environment variables:
export PRAVAHA_OUTPUT_DIR="./results"
export PRAVAHA_DEVIATION_THRESHOLD="0.10"
export PRAVAHA_SAMPLING_RATE_HZ="1.0"Access in code:
import os
output_dir = os.getenv("PRAVAHA_OUTPUT_DIR", "output")
threshold = float(os.getenv("PRAVAHA_DEVIATION_THRESHOLD", "0.15"))
sampling_rate = float(os.getenv("PRAVAHA_SAMPLING_RATE_HZ", "0.1"))PowerSimulator(
duration_hours=0.5, # Last 30 minutes
sampling_rate_hz=1.0, # 1 Hz (real-time)
)
analyzer = ResidualAnalyzer(deviation_threshold=0.10) # SensitivePowerSimulator(
duration_hours=720, # Last 30 days
sampling_rate_hz=0.01, # 1 sample/100 seconds (low data volume)
)
analyzer = ResidualAnalyzer(deviation_threshold=0.20) # ConservativePowerSimulator(
duration_hours=168, # One week
sampling_rate_hz=0.1, # Standard sampling
)
analyzer = ResidualAnalyzer(deviation_threshold=0.15) # StandardPowerSimulator(
duration_hours=6, # Short, fast
sampling_rate_hz=0.1, # Standard sampling
)
analyzer = ResidualAnalyzer(deviation_threshold=0.15)Cause: Faults too subtle or deviation threshold too high
Solution:
# Reduce threshold
analyzer = ResidualAnalyzer(deviation_threshold=0.10)
# Or increase fault severity
power_deg = power_sim.run_degraded(solar_factor=0.5) # Worse degradationCause: Deviation threshold too low or inconsistent priors
Solution:
# Increase threshold
analyzer = ResidualAnalyzer(deviation_threshold=0.20)
# Or adjust priors based on known failure modes
priors = {
"solar_degradation": 0.1, # Less likely for this satellite
"battery_aging": 0.5, # More likely
}
ranker = RootCauseRanker(graph, prior_probabilities=priors)Cause: Large simulation duration or high sampling rate
Solution:
# Reduce duration
PowerSimulator(duration_hours=12) # Instead of 24
# Or reduce sampling rate
PowerSimulator(sampling_rate_hz=0.5) # Instead of 1.0- Run with custom config: Running the Framework
- Understand inference: Inference Algorithm
- Extend causal graph: Causal Graph Design
- Optimize performance: Performance Tuning
Continue to: Output Interpretation ->
This documentation page includes updates from the v2.0 evaluation suite, incorporating empirical validation on European Space Agency (ESA) flight telemetry and improved hierarchical network rendering:
-
ESA OPS-SAT (OPSSAT-AD): Evaluated on ADCS reaction wheel magnetic interference and magnetometer attitude anomalies. By applying subsystem-aware persistence filtering (
$N=15$ consecutive samples for noisy magnetometer channels,$N=3$ for clean optical sensors), Aethelix achieves a 78.3% F1 score, comparable to deep LSTM autoencoder baselines (78.0% F1) without requiring historical model training. -
ESA-ADB Multi-Mission: Evaluated on satellite telemetry subject to periodic orbital thermal variation. To prevent false alarms caused by 90-minute day/night baseline oscillations, the engine evaluates innovation residuals (
$\Delta x_t = x_t - x_{t-1}$ ). Decoupling slow orbital dynamics from step-change fault signatures isolates transient subsystem anomalies.
-
Bounded Functional Corridors: The visualization script (
scripts/generate_dag_visuals.py) enforces strict vertical coordinate bounding (maximum node altitude$y=0.68$ ), ensuring clean separation from structural layer labels ($y=0.87$ ). -
Normalized Ranking Score Visualization: In accordance with project semantics, node color intensity maps directly to normalized ranking scores (e.g., 0.94 normalized score weight for
PCDU Regulator Failureon GSAT-6A; 0.89 normalized score weight forReaction Wheel Magnetic Interferenceon OPS-SAT). Active causal propagation paths connecting dominant root causes to observed telemetry deviations are highlighted along directed edges.
Benchmark datasets and diagnostic charts can be generated locally using the standalone scripts:
# Render hierarchical causal DAGs with normalized score weighting
python3 scripts/generate_dag_visuals.py
# Generate empirical validation charts across ESA datasets
python3 scripts/generate_validation_plots.py
# Execute benchmark suite evaluation
python3 scripts/esa_benchmark.py --dataset allGenerated diagnostic charts in docs/:
causal_dag_intensity_gsat6a.png— Multi-subsystem causal DAG mapping normalized ranking scores.causal_dag_intensity_opssat.png— ADCS magnetometer interference DAG structure.validation_signal_overlay.png— Telemetry Z-score deviations and persistence window thresholds.validation_confusion_matrix.png— Detection performance comparison against sequence-level baselines.validation_subsystem_metrics.png— Subsystem-level precision, recall, and F1 evaluation.validation_causal_attribution.png— Normalized root-cause score distribution across benchmark scenarios.