Run ecological plausibility checks on OSMOSE simulation outputs (biomass stability, trophic structure, size spectrum, diversity, extinction, mass conservation)
Validate that OSMOSE simulation outputs are ecologically plausible. This goes beyond engine parity (Python vs Java) to check whether the modeled ecosystem behaves like a real marine ecosystem.
output_dir (required): path to the simulation output directoryconfig (optional): "bob" (Bay of Biscay), "eec" (EEC), or path to config. Used for context in the reportyears (optional): number of simulation years to analyze (default: all available)checks (optional): comma-separated list of checks to run (default: all). Options: stability, trophic, spectrum, diversity, extinction, mortality, growth, dietRun checks in order. For each, load data via OsmoseResults, compute the diagnostic, and compare against the ecological threshold. Report PASS/WARN/FAIL for each.
stabilityGoal: Biomass trajectories should stabilize, not crash to zero or explode.
from osmose.results import OsmoseResults
results = OsmoseResults(Path(output_dir))
bio = results.biomass()
For each species, compute the coefficient of variation (CV) of biomass over the last 50% of the time series (skip spin-up):
Also flag if any species has final biomass < 1% of initial biomass (population collapse).
trophic)Goal: Mean trophic levels should follow expected marine ecosystem patterns.
tl = results.mean_trophic_level()
Check per species:
Check community-level:
analysis.mean_tl_catch() if yield data is available.spectrum)Goal: Community size spectrum should approximate a power law with negative slope.
from osmose.analysis import size_spectrum_slope
spectrum = results.size_spectrum()
slope, intercept, r2 = size_spectrum_slope(spectrum)
diversity)Goal: Species diversity should remain stable and non-zero.
from osmose.analysis import shannon_diversity
bio = results.biomass()
shannon = shannon_diversity(bio)
extinction)Goal: No focal species should go extinct unless expected.
For each species, check if biomass drops to zero at any point after spin-up:
Report which species go extinct and at what timestep.
mortality)Goal: Mortality rates should be within ecologically realistic bounds.
mort = results.mortality_rate()
For each mortality source per species:
growth)Goal: Mean size at age should follow Von Bertalanffy-like curves (non-decreasing).
size_by_age = results.mean_size_by_age()
For each species:
diet)Goal: Diet matrices should be non-trivial and reflect size-based feeding.
diet = results.diet_matrix()
Print a structured report:
══════════════════════════════════════════════════════════════
OSMOSE Scientific Validation Report
Config: {config} | Output: {output_dir}
══════════════════════════════════════════════════════════════
── 1. Biomass Stability ──────────────────────────────────────
Species Final (t) CV (last 50%) Status
Anchovy 1,234.5 0.21 PASS
Hake 892.1 0.73 WARN
...
── 2. Trophic Structure ──────────────────────────────────────
Species Mean TL Status
Anchovy 3.1 PASS
...
Community mean TL of catch: 3.4 PASS
── 3. Size Spectrum ──────────────────────────────────────────
Slope: -1.82 Intercept: 12.3 R²: 0.89 PASS
── 4. Diversity ──────────────────────────────────────────────
Initial Shannon H': 1.92
Final Shannon H': 1.78 (-7.3%) PASS
── 5. Extinction Check ───────────────────────────────────────
All 8 focal species persist PASS
── 6. Mortality Rates ────────────────────────────────────────
Species Z (total) Pred% Starv% Fish% Status
Anchovy 1.23 62% 5% 33% PASS
...
── 7. Growth ─────────────────────────────────────────────────
Species Ages monotonic? Status
Anchovy Yes PASS
...
── 8. Diet Composition ───────────────────────────────────────
Predator N prey Max prey % Status
Hake 5 42% PASS
...
══════════════════════════════════════════════════════════════
SUMMARY: 7 PASS | 1 WARN | 0 FAIL
══════════════════════════════════════════════════════════════
.venv/bin/python, never system python/home/razinka/osmose/osmose-python/OsmoseResults and osmose.analysis — do NOT parse CSV files manually