deringeorge commited on
Commit
c0b6f8f
·
1 Parent(s): d901d8e

feat: add global settings constants and Streamlit app shell

Browse files
Files changed (2) hide show
  1. app.py +237 -0
  2. config/settings.py +326 -0
app.py CHANGED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ app.py
3
+
4
+ Entry point for the SONARIS Streamlit application. Runs as the top-level UI
5
+ shell. At this stage it is a project dashboard showing module status, dataset
6
+ acquisition progress, and navigation scaffolding. Module-specific pages are
7
+ added here as each module reaches a usable state.
8
+
9
+ Run locally with: streamlit run app.py
10
+ """
11
+
12
+ import sys
13
+ import os
14
+
15
+ # Ensure the project root is on sys.path regardless of where Streamlit is
16
+ # invoked from. On Hugging Face Spaces, the working directory is the repo root,
17
+ # but local invocation from a subdirectory can break relative imports.
18
+ # This block resolves that without requiring the user to set PYTHONPATH manually.
19
+ _PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
20
+ if _PROJECT_ROOT not in sys.path:
21
+ sys.path.insert(0, _PROJECT_ROOT)
22
+
23
+ import streamlit as st
24
+ from config import settings
25
+
26
+ # =============================================================================
27
+ # Page configuration — must be the first Streamlit call in the script
28
+ # =============================================================================
29
+
30
+ st.set_page_config(
31
+ page_title="SONARIS — Ship-Ocean Noise Acoustic Radiated Intelligence System",
32
+ page_icon="🌊",
33
+ layout="wide",
34
+ initial_sidebar_state="expanded",
35
+ )
36
+
37
+ # =============================================================================
38
+ # Sidebar
39
+ # =============================================================================
40
+
41
+ with st.sidebar:
42
+ st.title(settings.PROJECT_NAME)
43
+ st.caption(f"v{settings.PROJECT_VERSION} | {settings.PROJECT_LICENSE} License")
44
+ st.divider()
45
+
46
+ st.subheader("Navigation")
47
+ # Navigation options are placeholders. Each option will route to a dedicated
48
+ # Streamlit page once the corresponding module is built. For now they all
49
+ # render the "under construction" message in the main body.
50
+ nav_selection = st.radio(
51
+ label="Go to",
52
+ options=[
53
+ "Overview",
54
+ "Predict URN",
55
+ "Compliance Check",
56
+ "Bioacoustic Impact",
57
+ "Mitigation Planner",
58
+ "URN Database",
59
+ ],
60
+ index=0,
61
+ label_visibility="collapsed",
62
+ )
63
+
64
+ st.divider()
65
+ st.subheader("Resources")
66
+ st.markdown(
67
+ f"""
68
+ - [GitHub Repository]({settings.PROJECT_GITHUB})
69
+ - [IMO MEPC.1/Circ.906 Rev.1](https://www.imo.org/en/OurWork/Environment/Pages/Underwater-noise.aspx)
70
+ - [ShipsEar Dataset](http://www.noiseatsea.es/)
71
+ - [QiandaoEar22 Dataset](https://arxiv.org/abs/2406.04354)
72
+ """
73
+ )
74
+
75
+ st.divider()
76
+ st.caption(
77
+ "Built by a Naval Architecture student and music composer "
78
+ "working at the intersection of ship engineering and acoustic science."
79
+ )
80
+
81
+ # =============================================================================
82
+ # Main body
83
+ # =============================================================================
84
+
85
+ # Header
86
+ st.title("SONARIS")
87
+ st.subheader(settings.PROJECT_FULL_NAME)
88
+
89
+ col_m1, col_m2, col_m3 = st.columns(3)
90
+ with col_m1:
91
+ st.metric(label="IMO Guidelines", value=settings.IMO_GUIDELINES_VERSION)
92
+ with col_m2:
93
+ st.metric(label="Core Modules", value="6")
94
+ with col_m3:
95
+ st.metric(label="Status", value="Active Development")
96
+
97
+ st.divider()
98
+
99
+ # =============================================================================
100
+ # Routing: non-Overview pages
101
+ # =============================================================================
102
+
103
+ if nav_selection != "Overview":
104
+ st.info(
105
+ f"**{nav_selection}** module is under construction. "
106
+ "Check back as development progresses or follow the "
107
+ f"[GitHub repository]({settings.PROJECT_GITHUB}) for updates."
108
+ )
109
+ st.stop()
110
+
111
+ # =============================================================================
112
+ # Overview page content
113
+ # =============================================================================
114
+
115
+ # Mission statement
116
+ st.markdown(
117
+ """
118
+ SONARIS predicts a ship's underwater radiated noise spectrum from hull geometry,
119
+ propeller parameters, and engine data, then checks the result against IMO
120
+ MEPC.1/Circ.906 Rev.1 (2024) limits and calculates the biological interference
121
+ caused to five groups of marine mammals. It is designed for shipyards, researchers,
122
+ and environmental organisations that need design-stage acoustic assessment and cannot
123
+ access proprietary tools. The platform is open-source and free to use, modify, and
124
+ deploy anywhere in the world.
125
+ """
126
+ )
127
+
128
+ st.divider()
129
+
130
+ # =============================================================================
131
+ # Module Status Dashboard
132
+ # =============================================================================
133
+
134
+ st.header("Module Status")
135
+
136
+ # Row 1
137
+ row1_col1, row1_col2 = st.columns(2)
138
+
139
+ with row1_col1:
140
+ st.subheader("Module 1: Design Input Engine")
141
+ st.write(
142
+ "Accepts hull form coefficients, propeller geometry, engine type, "
143
+ "rated RPM, and operational speed in knots."
144
+ )
145
+ st.success("Coming Soon") # change to st.success("Active") once built
146
+ st.caption("Tech: Python, dataclasses, Pydantic validation")
147
+
148
+ with row1_col2:
149
+ st.subheader("Module 2: URN Prediction Core")
150
+ st.write(
151
+ "Predicts the full 1/3-octave band noise spectrum from 20 Hz to 20 kHz "
152
+ "using a hybrid physics simulation and deep learning pipeline."
153
+ )
154
+ st.success("Coming Soon")
155
+ st.caption("Tech: PyTorch, OpenFOAM, libAcoustics")
156
+
157
+ # Row 2
158
+ row2_col1, row2_col2 = st.columns(2)
159
+
160
+ with row2_col1:
161
+ st.subheader("Module 3: IMO Compliance Checker")
162
+ st.write(
163
+ "Checks the predicted URN spectrum against IMO MEPC.1/Circ.906 Rev.1 "
164
+ "(2024) limit tables and generates a downloadable compliance report."
165
+ )
166
+ st.success("Coming Soon")
167
+ st.caption("Tech: IMO limit tables, ReportLab PDF generation")
168
+
169
+ with row2_col2:
170
+ st.subheader("Module 4: Marine Bioacoustic Impact")
171
+ st.write(
172
+ "Maps ship noise against published audiogram curves for five marine mammal "
173
+ "hearing groups and computes a Biological Interference Score for each."
174
+ )
175
+ st.success("Coming Soon")
176
+ st.caption("Tech: librosa, scipy.signal, MFCC analysis")
177
+
178
+ # Row 3
179
+ row3_col1, row3_col2 = st.columns(2)
180
+
181
+ with row3_col1:
182
+ st.subheader("Module 5: Mitigation Recommendation Engine")
183
+ st.write(
184
+ "Produces speed reduction targets, geographic routing avoidance zones, "
185
+ "and hull and propeller modification suggestions ranked by expected dB reduction."
186
+ )
187
+ st.success("Coming Soon")
188
+ st.caption("Tech: Rule-based recommendation engine, routing data")
189
+
190
+ with row3_col2:
191
+ st.subheader("Module 6: Open URN Database")
192
+ st.write(
193
+ "A community-contributed, publicly searchable database of ship acoustic "
194
+ "signatures. The first open-source database of its kind."
195
+ )
196
+ st.success("Coming Soon")
197
+ st.caption("Tech: SQLite (dev), PostgreSQL (prod), public query API")
198
+
199
+ st.divider()
200
+
201
+ # =============================================================================
202
+ # Dataset Acquisition Status
203
+ # =============================================================================
204
+
205
+ st.header("Dataset Acquisition — Phase 1")
206
+
207
+ with st.expander("View dataset status", expanded=True):
208
+ dataset_status = {
209
+ "ShipsEar (Santos-Dominguez et al., 2016)": "Acquisition in progress",
210
+ "QiandaoEar22 (arXiv:2406.04354)": "Pending",
211
+ "Marine mammal audiograms (Southall et al., 2019)": "Pending",
212
+ "IMO MEPC.1/Circ.906 Rev.1 limit tables": "Pending",
213
+ }
214
+
215
+ for dataset, status in dataset_status.items():
216
+ col_ds, col_st = st.columns([3, 1])
217
+ with col_ds:
218
+ st.write(dataset)
219
+ with col_st:
220
+ if status == "Acquisition in progress":
221
+ st.warning(status)
222
+ else:
223
+ st.info(status)
224
+
225
+ # =============================================================================
226
+ # Footer
227
+ # =============================================================================
228
+
229
+ st.divider()
230
+ st.markdown(
231
+ f"<center style='color: grey; font-size: 0.85em;'>"
232
+ f"SONARIS v{settings.PROJECT_VERSION} | "
233
+ f"{settings.PROJECT_LICENSE} License | "
234
+ f"github.com/deringeorge-nebula/SONARIS"
235
+ f"</center>",
236
+ unsafe_allow_html=True,
237
+ )
config/settings.py CHANGED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ config/settings.py
3
+
4
+ Single source of truth for all constants and configuration values used across
5
+ the SONARIS platform. Every module imports from here. No module should define
6
+ a scientific constant, regulatory parameter, processing default, or system path
7
+ locally. If a value might be reused anywhere else in the codebase, it belongs
8
+ in this file.
9
+ """
10
+
11
+ import math
12
+ from typing import Dict, List, Tuple
13
+
14
+ # =============================================================================
15
+ # SECTION 1 - Acoustic Frequency Range
16
+ # =============================================================================
17
+
18
+ FREQ_MIN_HZ: int = 20
19
+ FREQ_MAX_HZ: int = 20_000
20
+
21
+ # Reference pressure for underwater acoustics: 1 micropascal.
22
+ # All dB values in SONARIS are expressed as dB re 1 uPa at 1m unless stated.
23
+ # This is the universal standard for underwater source levels (ISO 18405:2017).
24
+ FREQ_REF_UNDERWATER: float = 1e-6 # Pa
25
+
26
+ # Reference pressure for airborne acoustics: 20 micropascals.
27
+ # Included for comparison purposes only. All ship noise output is underwater.
28
+ # Standard defined in ISO 1683:2015.
29
+ FREQ_REF_AIRBORNE: float = 2e-5 # Pa
30
+
31
+
32
+ # =============================================================================
33
+ # SECTION 2 - 1/3 Octave Band Center Frequencies (ISO 266)
34
+ # =============================================================================
35
+
36
+ # Standard 1/3-octave band center frequencies from 20 Hz to 20 kHz.
37
+ # These are the exact preferred frequencies from ISO 266:1997.
38
+ # There are 31 bands in this range.
39
+ THIRD_OCTAVE_CENTER_FREQUENCIES: List[float] = [
40
+ 20, 25, 31.5, 40, 50, 63, 80, 100, 125, 160,
41
+ 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600,
42
+ 2000, 2500, 3150, 4000, 5000, 6300, 8000, 10000, 12500, 16000,
43
+ 20000,
44
+ ]
45
+
46
+ # Band edge calculation follows IEC 61260-1:2014.
47
+ # lower = f_center / 2^(1/6), upper = f_center * 2^(1/6)
48
+ _BAND_FACTOR: float = 2 ** (1 / 6)
49
+
50
+ THIRD_OCTAVE_LOWER_LIMITS: List[float] = [
51
+ round(f / _BAND_FACTOR, 4) for f in THIRD_OCTAVE_CENTER_FREQUENCIES
52
+ ]
53
+
54
+ THIRD_OCTAVE_UPPER_LIMITS: List[float] = [
55
+ round(f * _BAND_FACTOR, 4) for f in THIRD_OCTAVE_CENTER_FREQUENCIES
56
+ ]
57
+
58
+
59
+ # =============================================================================
60
+ # SECTION 3 - Marine Mammal Functional Hearing Groups
61
+ # =============================================================================
62
+ # Frequency ranges are based on NOAA/NMFS (2018) acoustic weighting functions
63
+ # and audiogram data compiled in Southall et al. (2019) "Marine Mammal Noise
64
+ # Exposure Criteria: Updated Scientific Recommendations for Residual Hearing
65
+ # Effects", Aquatic Mammals, 45(2).
66
+ #
67
+ # communication_freq_min/max represents the band where the species group
68
+ # primarily signals to conspecifics. This is the band used for BIS calculation.
69
+ # hearing_freq_min/max is the full audiometric range.
70
+
71
+ LOW_FREQUENCY_CETACEANS: Dict = {
72
+ "name": "Low-Frequency Cetaceans (Baleen Whales)",
73
+ "examples": ["Blue whale", "Fin whale", "Humpback whale", "Sei whale", "Minke whale"],
74
+ "hearing_freq_min_hz": 7,
75
+ "hearing_freq_max_hz": 35_000,
76
+ "communication_freq_min_hz": 10,
77
+ "communication_freq_max_hz": 1_000,
78
+ # Fin whale 20 Hz calls and blue whale 17-20 Hz infrasonic pulses anchor
79
+ # the lower bound. Upper bound follows NOAA LF weighting function.
80
+ "imo_group": "LF",
81
+ }
82
+
83
+ MID_FREQUENCY_CETACEANS: Dict = {
84
+ "name": "Mid-Frequency Cetaceans (Dolphins, Toothed Whales)",
85
+ "examples": ["Bottlenose dolphin", "Sperm whale", "Killer whale", "Beluga whale"],
86
+ "hearing_freq_min_hz": 150,
87
+ "hearing_freq_max_hz": 160_000,
88
+ "communication_freq_min_hz": 5_000,
89
+ "communication_freq_max_hz": 80_000,
90
+ # Bottlenose dolphin signature whistles peak 3-15 kHz. Sperm whale clicks
91
+ # are broadband but centre around 15 kHz. Upper bound follows NOAA MF weighting.
92
+ "imo_group": "MF",
93
+ }
94
+
95
+ HIGH_FREQUENCY_CETACEANS: Dict = {
96
+ "name": "High-Frequency Cetaceans (Porpoises, Small Odontocetes)",
97
+ "examples": ["Harbour porpoise", "Dall's porpoise", "Commerson's dolphin"],
98
+ "hearing_freq_min_hz": 200,
99
+ "hearing_freq_max_hz": 180_000,
100
+ "communication_freq_min_hz": 100_000,
101
+ "communication_freq_max_hz": 150_000,
102
+ # Harbour porpoise echolocation clicks are narrowband around 130 kHz.
103
+ # This group is the most sensitive to high-frequency shipping noise components.
104
+ "imo_group": "HF",
105
+ }
106
+
107
+ PHOCID_PINNIPEDS_UNDERWATER: Dict = {
108
+ "name": "Phocid Pinnipeds in Water (True Seals)",
109
+ "examples": ["Harbour seal", "Grey seal", "Weddell seal", "Ringed seal"],
110
+ "hearing_freq_min_hz": 50,
111
+ "hearing_freq_max_hz": 86_000,
112
+ "communication_freq_min_hz": 1_000,
113
+ "communication_freq_max_hz": 50_000,
114
+ # Phocids hear well underwater; audiogram peak sensitivity is around 10-30 kHz.
115
+ # Communication calls (e.g. Weddell seal trills) fall 1-10 kHz.
116
+ "imo_group": "PPW",
117
+ }
118
+
119
+ OTARIID_PINNIPEDS_UNDERWATER: Dict = {
120
+ "name": "Otariid Pinnipeds in Water (Sea Lions, Fur Seals)",
121
+ "examples": ["California sea lion", "Northern fur seal", "Steller sea lion"],
122
+ "hearing_freq_min_hz": 60,
123
+ "hearing_freq_max_hz": 39_000,
124
+ "communication_freq_min_hz": 1_000,
125
+ "communication_freq_max_hz": 30_000,
126
+ # Otariids have narrower underwater hearing than phocids. California sea lion
127
+ # audiogram shows best sensitivity around 1-16 kHz (Kastak & Schusterman 1998).
128
+ "imo_group": "OW",
129
+ }
130
+
131
+ # Ordered list consumed by Module 4's BIS calculator. Order is preserved
132
+ # in all output tables and visualizations.
133
+ MARINE_MAMMAL_GROUPS: List[Dict] = [
134
+ LOW_FREQUENCY_CETACEANS,
135
+ MID_FREQUENCY_CETACEANS,
136
+ HIGH_FREQUENCY_CETACEANS,
137
+ PHOCID_PINNIPEDS_UNDERWATER,
138
+ OTARIID_PINNIPEDS_UNDERWATER,
139
+ ]
140
+
141
+
142
+ # =============================================================================
143
+ # SECTION 4 - Biological Interference Score (BIS) Thresholds
144
+ # =============================================================================
145
+ # BIS is a SONARIS-defined metric: 0 to 100, representing the fraction of a
146
+ # species group's communication band that is energetically masked by ship noise.
147
+ # Thresholds are defined by analogy with audiological masking literature and
148
+ # calibrated to the frequency resolution of 1/3-octave bands.
149
+ # "Critical" at 75% is grounded in the observation that communication
150
+ # success in cetaceans drops sharply when SNR falls below -6 dB across
151
+ # more than 3/4 of the call bandwidth (Erbe et al., 2016, "The effects of
152
+ # ship noise on marine mammals", Frontiers in Marine Science).
153
+
154
+ BIS_THRESHOLDS: Dict[str, Tuple[float, float]] = {
155
+ "negligible": (0.0, 10.0), # < 10% of communication band masked
156
+ "low": (10.0, 25.0), # 10 to 25%
157
+ "moderate": (25.0, 50.0), # 25 to 50%
158
+ "high": (50.0, 75.0), # 50 to 75%
159
+ "critical": (75.0, 100.0), # > 75%: species group is functionally deaf
160
+ # to conspecific signals in this environment
161
+ }
162
+
163
+ # Standalone threshold used in Module 3 and Module 5 logic.
164
+ BIS_CRITICAL_THRESHOLD: float = 75.0
165
+
166
+
167
+ # =============================================================================
168
+ # SECTION 5 - IMO Vessel Type Categories
169
+ # =============================================================================
170
+ # Vessel type codes follow the categorization in IMO MEPC.1/Circ.906 Rev.1.
171
+ # These codes are used as keys in the URN limit tables below and in database
172
+ # records. Short codes are snake_case for use as dict keys and URL parameters.
173
+
174
+ IMO_VESSEL_TYPES: Dict[str, str] = {
175
+ "bulk_carrier": "Bulk Carrier",
176
+ "tanker": "Tanker (Oil / Chemical / LNG)",
177
+ "container": "Container Ship",
178
+ "general_cargo": "General Cargo Ship",
179
+ "roro": "Ro-Ro Cargo Ship",
180
+ "passenger": "Passenger Ship",
181
+ "cruise": "Cruise Ship",
182
+ "ferry": "Ferry",
183
+ "naval": "Naval Vessel",
184
+ "research": "Research Vessel",
185
+ "offshore": "Offshore Support Vessel",
186
+ "tug": "Tug",
187
+ "fishing": "Fishing Vessel",
188
+ "icebreaker": "Icebreaker",
189
+ }
190
+
191
+
192
+ # =============================================================================
193
+ # SECTION 6 - IMO URN Limit Tables
194
+ # =============================================================================
195
+ # Source level limits by vessel type and 1/3-octave band center frequency.
196
+ # Units: dB re 1 uPa at 1m.
197
+ # Reference: IMO MEPC.1/Circ.906 Rev.1 (2024), Annex, Table 1.
198
+ #
199
+ # TODO (Phase 1): Digitize the full limit table from the official IMO document
200
+ # for all vessel types and all 31 bands. The three container ship values below
201
+ # are representative placeholders derived from the published figure in
202
+ # MEPC.1/Circ.906 Rev.1 and should be replaced with exact table values
203
+ # once the document is formally acquired.
204
+
205
+ IMO_URN_LIMITS: Dict[str, Dict[int, float]] = {
206
+ "container": {
207
+ # Freq (Hz): max allowed source level (dB re 1 uPa at 1m)
208
+ 100: 149.0, # placeholder — confirm against MEPC.1/Circ.906 Rev.1 Annex Table 1
209
+ 315: 144.0, # placeholder
210
+ 1000: 136.0, # placeholder
211
+ },
212
+ # TODO: populate all vessel types from the official IMO document
213
+ "bulk_carrier": {},
214
+ "tanker": {},
215
+ "general_cargo": {},
216
+ "roro": {},
217
+ "passenger": {},
218
+ "cruise": {},
219
+ "ferry": {},
220
+ "naval": {},
221
+ "research": {},
222
+ "offshore": {},
223
+ "tug": {},
224
+ "fishing": {},
225
+ "icebreaker": {},
226
+ }
227
+
228
+
229
+ # =============================================================================
230
+ # SECTION 7 - Signal Processing Configuration
231
+ # =============================================================================
232
+
233
+ # Default sample rate for librosa operations.
234
+ # 22050 Hz is librosa's default and covers the full 20 Hz to 10 kHz range
235
+ # at Nyquist. For analysis above 10 kHz, resample to 44100 Hz before processing.
236
+ SAMPLE_RATE: int = 22_050 # Hz
237
+
238
+ # FFT window size. 2048 samples at 22050 Hz gives ~93 ms windows,
239
+ # which resolves frequency to ~10.8 Hz per bin. Adequate for 1/3-octave grouping.
240
+ N_FFT: int = 2048
241
+
242
+ # Hop length: number of samples between consecutive STFT frames.
243
+ # 512 gives ~75% overlap with a 2048-point window, standard for acoustic analysis.
244
+ HOP_LENGTH: int = 512
245
+
246
+ # Number of MFCC coefficients. 40 resolves the 20 Hz to 20 kHz range
247
+ # across the Mel scale without redundancy. Matching the standard used in
248
+ # the ShipsEar dataset feature extraction pipeline keeps the AI layer consistent.
249
+ N_MFCC: int = 40
250
+
251
+ # Hann window is the default for acoustic STFT analysis. It minimises spectral
252
+ # leakage without excessive main-lobe broadening (Harris, 1978).
253
+ WINDOW_FUNCTION: str = "hann"
254
+
255
+ # Alias so module code can reference CENTER_FREQUENCIES without importing
256
+ # the full list name, which is verbose in signal processing loops.
257
+ CENTER_FREQUENCIES: List[float] = THIRD_OCTAVE_CENTER_FREQUENCIES
258
+
259
+
260
+ # =============================================================================
261
+ # SECTION 8 - OpenFOAM Simulation Defaults
262
+ # =============================================================================
263
+
264
+ # Number of parallel MPI processes for OpenFOAM runs.
265
+ # 4 cores is a safe default for development machines. Override in .env for HPC.
266
+ OPENFOAM_DEFAULT_CORES: int = 4
267
+
268
+ # End time for cavitation transient simulation in seconds.
269
+ # 0.5 s captures several propeller blade-pass cycles at typical shaft speeds
270
+ # without excessive computation.
271
+ SIMULATION_END_TIME: float = 0.5 # seconds
272
+
273
+ # Time step for the simulation. 1e-5 s satisfies the Courant condition for
274
+ # typical ship speeds and mesh resolutions used in propeller cavitation cases.
275
+ SIMULATION_TIMESTEP: float = 1e-5 # seconds
276
+
277
+ # Write OpenFOAM results to disk every 100 time steps.
278
+ # At 1e-5 s per step, this gives output every 1 ms of simulated time.
279
+ OUTPUT_WRITE_INTERVAL: int = 100 # time steps
280
+
281
+
282
+ # =============================================================================
283
+ # SECTION 9 - Database Configuration
284
+ # =============================================================================
285
+
286
+ # SQLite connection strings for development and test environments.
287
+ # Format follows SQLAlchemy engine URL syntax so switching to PostgreSQL
288
+ # requires only changing this string, not the query logic in db_manager.py.
289
+ DATABASE_DEV: str = "sqlite:///data/databases/sonaris_dev.db"
290
+ DATABASE_TEST: str = "sqlite:///data/databases/sonaris_test.db"
291
+
292
+ # PostgreSQL connection string template for production.
293
+ # Actual credentials are loaded from .env; this is the format reference only.
294
+ DATABASE_PROD_TEMPLATE: str = "postgresql://{user}:{password}@{host}:{port}/{dbname}"
295
+
296
+ # Table name for the URN signature records in both SQLite and PostgreSQL.
297
+ URN_DATABASE_TABLE: str = "urn_signatures"
298
+
299
+ # Minimum fields required for a valid URN database contribution.
300
+ # Records missing any of these fields are rejected at the write layer.
301
+ MIN_REQUIRED_FIELDS: List[str] = [
302
+ "vessel_type",
303
+ "loa_m",
304
+ "speed_knots",
305
+ "propulsion_type",
306
+ "blade_count",
307
+ "measurement_standard",
308
+ "spectrum_data",
309
+ ]
310
+
311
+
312
+ # =============================================================================
313
+ # SECTION 10 - Project Metadata
314
+ # =============================================================================
315
+
316
+ PROJECT_NAME: str = "SONARIS"
317
+ PROJECT_FULL_NAME: str = "Ship-Ocean Noise Acoustic Radiated Intelligence System"
318
+ PROJECT_VERSION: str = "0.1.0"
319
+ PROJECT_LICENSE: str = "MIT"
320
+ PROJECT_GITHUB: str = "https://github.com/deringeorge-nebula/SONARIS"
321
+
322
+ # The specific IMO circular version this codebase implements.
323
+ # Update this string whenever a new revision of the guidelines is adopted.
324
+ IMO_GUIDELINES_VERSION: str = "MEPC.1/Circ.906 Rev.1 (2024)"
325
+
326
+ SUPPORTED_PYTHON: str = ">=3.11"