""" 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"