SONARIS / config /settings.py
deringeorge's picture
feat: add global settings constants and Streamlit app shell
c0b6f8f
"""
config/settings.py
Single source of truth for all constants and configuration values used across
the SONARIS platform. Every module imports from here. No module should define
a scientific constant, regulatory parameter, processing default, or system path
locally. If a value might be reused anywhere else in the codebase, it belongs
in this file.
"""
import math
from typing import Dict, List, Tuple
# =============================================================================
# SECTION 1 - Acoustic Frequency Range
# =============================================================================
FREQ_MIN_HZ: int = 20
FREQ_MAX_HZ: int = 20_000
# Reference pressure for underwater acoustics: 1 micropascal.
# All dB values in SONARIS are expressed as dB re 1 uPa at 1m unless stated.
# This is the universal standard for underwater source levels (ISO 18405:2017).
FREQ_REF_UNDERWATER: float = 1e-6 # Pa
# Reference pressure for airborne acoustics: 20 micropascals.
# Included for comparison purposes only. All ship noise output is underwater.
# Standard defined in ISO 1683:2015.
FREQ_REF_AIRBORNE: float = 2e-5 # Pa
# =============================================================================
# SECTION 2 - 1/3 Octave Band Center Frequencies (ISO 266)
# =============================================================================
# Standard 1/3-octave band center frequencies from 20 Hz to 20 kHz.
# These are the exact preferred frequencies from ISO 266:1997.
# There are 31 bands in this range.
THIRD_OCTAVE_CENTER_FREQUENCIES: List[float] = [
20, 25, 31.5, 40, 50, 63, 80, 100, 125, 160,
200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600,
2000, 2500, 3150, 4000, 5000, 6300, 8000, 10000, 12500, 16000,
20000,
]
# Band edge calculation follows IEC 61260-1:2014.
# lower = f_center / 2^(1/6), upper = f_center * 2^(1/6)
_BAND_FACTOR: float = 2 ** (1 / 6)
THIRD_OCTAVE_LOWER_LIMITS: List[float] = [
round(f / _BAND_FACTOR, 4) for f in THIRD_OCTAVE_CENTER_FREQUENCIES
]
THIRD_OCTAVE_UPPER_LIMITS: List[float] = [
round(f * _BAND_FACTOR, 4) for f in THIRD_OCTAVE_CENTER_FREQUENCIES
]
# =============================================================================
# SECTION 3 - Marine Mammal Functional Hearing Groups
# =============================================================================
# Frequency ranges are based on NOAA/NMFS (2018) acoustic weighting functions
# and audiogram data compiled in Southall et al. (2019) "Marine Mammal Noise
# Exposure Criteria: Updated Scientific Recommendations for Residual Hearing
# Effects", Aquatic Mammals, 45(2).
#
# communication_freq_min/max represents the band where the species group
# primarily signals to conspecifics. This is the band used for BIS calculation.
# hearing_freq_min/max is the full audiometric range.
LOW_FREQUENCY_CETACEANS: Dict = {
"name": "Low-Frequency Cetaceans (Baleen Whales)",
"examples": ["Blue whale", "Fin whale", "Humpback whale", "Sei whale", "Minke whale"],
"hearing_freq_min_hz": 7,
"hearing_freq_max_hz": 35_000,
"communication_freq_min_hz": 10,
"communication_freq_max_hz": 1_000,
# Fin whale 20 Hz calls and blue whale 17-20 Hz infrasonic pulses anchor
# the lower bound. Upper bound follows NOAA LF weighting function.
"imo_group": "LF",
}
MID_FREQUENCY_CETACEANS: Dict = {
"name": "Mid-Frequency Cetaceans (Dolphins, Toothed Whales)",
"examples": ["Bottlenose dolphin", "Sperm whale", "Killer whale", "Beluga whale"],
"hearing_freq_min_hz": 150,
"hearing_freq_max_hz": 160_000,
"communication_freq_min_hz": 5_000,
"communication_freq_max_hz": 80_000,
# Bottlenose dolphin signature whistles peak 3-15 kHz. Sperm whale clicks
# are broadband but centre around 15 kHz. Upper bound follows NOAA MF weighting.
"imo_group": "MF",
}
HIGH_FREQUENCY_CETACEANS: Dict = {
"name": "High-Frequency Cetaceans (Porpoises, Small Odontocetes)",
"examples": ["Harbour porpoise", "Dall's porpoise", "Commerson's dolphin"],
"hearing_freq_min_hz": 200,
"hearing_freq_max_hz": 180_000,
"communication_freq_min_hz": 100_000,
"communication_freq_max_hz": 150_000,
# Harbour porpoise echolocation clicks are narrowband around 130 kHz.
# This group is the most sensitive to high-frequency shipping noise components.
"imo_group": "HF",
}
PHOCID_PINNIPEDS_UNDERWATER: Dict = {
"name": "Phocid Pinnipeds in Water (True Seals)",
"examples": ["Harbour seal", "Grey seal", "Weddell seal", "Ringed seal"],
"hearing_freq_min_hz": 50,
"hearing_freq_max_hz": 86_000,
"communication_freq_min_hz": 1_000,
"communication_freq_max_hz": 50_000,
# Phocids hear well underwater; audiogram peak sensitivity is around 10-30 kHz.
# Communication calls (e.g. Weddell seal trills) fall 1-10 kHz.
"imo_group": "PPW",
}
OTARIID_PINNIPEDS_UNDERWATER: Dict = {
"name": "Otariid Pinnipeds in Water (Sea Lions, Fur Seals)",
"examples": ["California sea lion", "Northern fur seal", "Steller sea lion"],
"hearing_freq_min_hz": 60,
"hearing_freq_max_hz": 39_000,
"communication_freq_min_hz": 1_000,
"communication_freq_max_hz": 30_000,
# Otariids have narrower underwater hearing than phocids. California sea lion
# audiogram shows best sensitivity around 1-16 kHz (Kastak & Schusterman 1998).
"imo_group": "OW",
}
# Ordered list consumed by Module 4's BIS calculator. Order is preserved
# in all output tables and visualizations.
MARINE_MAMMAL_GROUPS: List[Dict] = [
LOW_FREQUENCY_CETACEANS,
MID_FREQUENCY_CETACEANS,
HIGH_FREQUENCY_CETACEANS,
PHOCID_PINNIPEDS_UNDERWATER,
OTARIID_PINNIPEDS_UNDERWATER,
]
# =============================================================================
# SECTION 4 - Biological Interference Score (BIS) Thresholds
# =============================================================================
# BIS is a SONARIS-defined metric: 0 to 100, representing the fraction of a
# species group's communication band that is energetically masked by ship noise.
# Thresholds are defined by analogy with audiological masking literature and
# calibrated to the frequency resolution of 1/3-octave bands.
# "Critical" at 75% is grounded in the observation that communication
# success in cetaceans drops sharply when SNR falls below -6 dB across
# more than 3/4 of the call bandwidth (Erbe et al., 2016, "The effects of
# ship noise on marine mammals", Frontiers in Marine Science).
BIS_THRESHOLDS: Dict[str, Tuple[float, float]] = {
"negligible": (0.0, 10.0), # < 10% of communication band masked
"low": (10.0, 25.0), # 10 to 25%
"moderate": (25.0, 50.0), # 25 to 50%
"high": (50.0, 75.0), # 50 to 75%
"critical": (75.0, 100.0), # > 75%: species group is functionally deaf
# to conspecific signals in this environment
}
# Standalone threshold used in Module 3 and Module 5 logic.
BIS_CRITICAL_THRESHOLD: float = 75.0
# =============================================================================
# SECTION 5 - IMO Vessel Type Categories
# =============================================================================
# Vessel type codes follow the categorization in IMO MEPC.1/Circ.906 Rev.1.
# These codes are used as keys in the URN limit tables below and in database
# records. Short codes are snake_case for use as dict keys and URL parameters.
IMO_VESSEL_TYPES: Dict[str, str] = {
"bulk_carrier": "Bulk Carrier",
"tanker": "Tanker (Oil / Chemical / LNG)",
"container": "Container Ship",
"general_cargo": "General Cargo Ship",
"roro": "Ro-Ro Cargo Ship",
"passenger": "Passenger Ship",
"cruise": "Cruise Ship",
"ferry": "Ferry",
"naval": "Naval Vessel",
"research": "Research Vessel",
"offshore": "Offshore Support Vessel",
"tug": "Tug",
"fishing": "Fishing Vessel",
"icebreaker": "Icebreaker",
}
# =============================================================================
# SECTION 6 - IMO URN Limit Tables
# =============================================================================
# Source level limits by vessel type and 1/3-octave band center frequency.
# Units: dB re 1 uPa at 1m.
# Reference: IMO MEPC.1/Circ.906 Rev.1 (2024), Annex, Table 1.
#
# TODO (Phase 1): Digitize the full limit table from the official IMO document
# for all vessel types and all 31 bands. The three container ship values below
# are representative placeholders derived from the published figure in
# MEPC.1/Circ.906 Rev.1 and should be replaced with exact table values
# once the document is formally acquired.
IMO_URN_LIMITS: Dict[str, Dict[int, float]] = {
"container": {
# Freq (Hz): max allowed source level (dB re 1 uPa at 1m)
100: 149.0, # placeholder — confirm against MEPC.1/Circ.906 Rev.1 Annex Table 1
315: 144.0, # placeholder
1000: 136.0, # placeholder
},
# TODO: populate all vessel types from the official IMO document
"bulk_carrier": {},
"tanker": {},
"general_cargo": {},
"roro": {},
"passenger": {},
"cruise": {},
"ferry": {},
"naval": {},
"research": {},
"offshore": {},
"tug": {},
"fishing": {},
"icebreaker": {},
}
# =============================================================================
# SECTION 7 - Signal Processing Configuration
# =============================================================================
# Default sample rate for librosa operations.
# 22050 Hz is librosa's default and covers the full 20 Hz to 10 kHz range
# at Nyquist. For analysis above 10 kHz, resample to 44100 Hz before processing.
SAMPLE_RATE: int = 22_050 # Hz
# FFT window size. 2048 samples at 22050 Hz gives ~93 ms windows,
# which resolves frequency to ~10.8 Hz per bin. Adequate for 1/3-octave grouping.
N_FFT: int = 2048
# Hop length: number of samples between consecutive STFT frames.
# 512 gives ~75% overlap with a 2048-point window, standard for acoustic analysis.
HOP_LENGTH: int = 512
# Number of MFCC coefficients. 40 resolves the 20 Hz to 20 kHz range
# across the Mel scale without redundancy. Matching the standard used in
# the ShipsEar dataset feature extraction pipeline keeps the AI layer consistent.
N_MFCC: int = 40
# Hann window is the default for acoustic STFT analysis. It minimises spectral
# leakage without excessive main-lobe broadening (Harris, 1978).
WINDOW_FUNCTION: str = "hann"
# Alias so module code can reference CENTER_FREQUENCIES without importing
# the full list name, which is verbose in signal processing loops.
CENTER_FREQUENCIES: List[float] = THIRD_OCTAVE_CENTER_FREQUENCIES
# =============================================================================
# SECTION 8 - OpenFOAM Simulation Defaults
# =============================================================================
# Number of parallel MPI processes for OpenFOAM runs.
# 4 cores is a safe default for development machines. Override in .env for HPC.
OPENFOAM_DEFAULT_CORES: int = 4
# End time for cavitation transient simulation in seconds.
# 0.5 s captures several propeller blade-pass cycles at typical shaft speeds
# without excessive computation.
SIMULATION_END_TIME: float = 0.5 # seconds
# Time step for the simulation. 1e-5 s satisfies the Courant condition for
# typical ship speeds and mesh resolutions used in propeller cavitation cases.
SIMULATION_TIMESTEP: float = 1e-5 # seconds
# Write OpenFOAM results to disk every 100 time steps.
# At 1e-5 s per step, this gives output every 1 ms of simulated time.
OUTPUT_WRITE_INTERVAL: int = 100 # time steps
# =============================================================================
# SECTION 9 - Database Configuration
# =============================================================================
# SQLite connection strings for development and test environments.
# Format follows SQLAlchemy engine URL syntax so switching to PostgreSQL
# requires only changing this string, not the query logic in db_manager.py.
DATABASE_DEV: str = "sqlite:///data/databases/sonaris_dev.db"
DATABASE_TEST: str = "sqlite:///data/databases/sonaris_test.db"
# PostgreSQL connection string template for production.
# Actual credentials are loaded from .env; this is the format reference only.
DATABASE_PROD_TEMPLATE: str = "postgresql://{user}:{password}@{host}:{port}/{dbname}"
# Table name for the URN signature records in both SQLite and PostgreSQL.
URN_DATABASE_TABLE: str = "urn_signatures"
# Minimum fields required for a valid URN database contribution.
# Records missing any of these fields are rejected at the write layer.
MIN_REQUIRED_FIELDS: List[str] = [
"vessel_type",
"loa_m",
"speed_knots",
"propulsion_type",
"blade_count",
"measurement_standard",
"spectrum_data",
]
# =============================================================================
# SECTION 10 - Project Metadata
# =============================================================================
PROJECT_NAME: str = "SONARIS"
PROJECT_FULL_NAME: str = "Ship-Ocean Noise Acoustic Radiated Intelligence System"
PROJECT_VERSION: str = "0.1.0"
PROJECT_LICENSE: str = "MIT"
PROJECT_GITHUB: str = "https://github.com/deringeorge-nebula/SONARIS"
# The specific IMO circular version this codebase implements.
# Update this string whenever a new revision of the guidelines is adopted.
IMO_GUIDELINES_VERSION: str = "MEPC.1/Circ.906 Rev.1 (2024)"
SUPPORTED_PYTHON: str = ">=3.11"