File size: 8,229 Bytes
c0b6f8f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
"""
app.py

Entry point for the SONARIS Streamlit application. Runs as the top-level UI
shell. At this stage it is a project dashboard showing module status, dataset
acquisition progress, and navigation scaffolding. Module-specific pages are
added here as each module reaches a usable state.

Run locally with: streamlit run app.py
"""

import sys
import os

# Ensure the project root is on sys.path regardless of where Streamlit is
# invoked from. On Hugging Face Spaces, the working directory is the repo root,
# but local invocation from a subdirectory can break relative imports.
# This block resolves that without requiring the user to set PYTHONPATH manually.
_PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
if _PROJECT_ROOT not in sys.path:
    sys.path.insert(0, _PROJECT_ROOT)

import streamlit as st
from config import settings

# =============================================================================
# Page configuration β€” must be the first Streamlit call in the script
# =============================================================================

st.set_page_config(
    page_title="SONARIS β€” Ship-Ocean Noise Acoustic Radiated Intelligence System",
    page_icon="🌊",
    layout="wide",
    initial_sidebar_state="expanded",
)

# =============================================================================
# Sidebar
# =============================================================================

with st.sidebar:
    st.title(settings.PROJECT_NAME)
    st.caption(f"v{settings.PROJECT_VERSION} | {settings.PROJECT_LICENSE} License")
    st.divider()

    st.subheader("Navigation")
    # Navigation options are placeholders. Each option will route to a dedicated
    # Streamlit page once the corresponding module is built. For now they all
    # render the "under construction" message in the main body.
    nav_selection = st.radio(
        label="Go to",
        options=[
            "Overview",
            "Predict URN",
            "Compliance Check",
            "Bioacoustic Impact",
            "Mitigation Planner",
            "URN Database",
        ],
        index=0,
        label_visibility="collapsed",
    )

    st.divider()
    st.subheader("Resources")
    st.markdown(
        f"""
- [GitHub Repository]({settings.PROJECT_GITHUB})
- [IMO MEPC.1/Circ.906 Rev.1](https://www.imo.org/en/OurWork/Environment/Pages/Underwater-noise.aspx)
- [ShipsEar Dataset](http://www.noiseatsea.es/)
- [QiandaoEar22 Dataset](https://arxiv.org/abs/2406.04354)
        """
    )

    st.divider()
    st.caption(
        "Built by a Naval Architecture student and music composer "
        "working at the intersection of ship engineering and acoustic science."
    )

# =============================================================================
# Main body
# =============================================================================

# Header
st.title("SONARIS")
st.subheader(settings.PROJECT_FULL_NAME)

col_m1, col_m2, col_m3 = st.columns(3)
with col_m1:
    st.metric(label="IMO Guidelines", value=settings.IMO_GUIDELINES_VERSION)
with col_m2:
    st.metric(label="Core Modules", value="6")
with col_m3:
    st.metric(label="Status", value="Active Development")

st.divider()

# =============================================================================
# Routing: non-Overview pages
# =============================================================================

if nav_selection != "Overview":
    st.info(
        f"**{nav_selection}** module is under construction. "
        "Check back as development progresses or follow the "
        f"[GitHub repository]({settings.PROJECT_GITHUB}) for updates."
    )
    st.stop()

# =============================================================================
# Overview page content
# =============================================================================

# Mission statement
st.markdown(
    """
SONARIS predicts a ship's underwater radiated noise spectrum from hull geometry,
propeller parameters, and engine data, then checks the result against IMO
MEPC.1/Circ.906 Rev.1 (2024) limits and calculates the biological interference
caused to five groups of marine mammals. It is designed for shipyards, researchers,
and environmental organisations that need design-stage acoustic assessment and cannot
access proprietary tools. The platform is open-source and free to use, modify, and
deploy anywhere in the world.
"""
)

st.divider()

# =============================================================================
# Module Status Dashboard
# =============================================================================

st.header("Module Status")

# Row 1
row1_col1, row1_col2 = st.columns(2)

with row1_col1:
    st.subheader("Module 1: Design Input Engine")
    st.write(
        "Accepts hull form coefficients, propeller geometry, engine type, "
        "rated RPM, and operational speed in knots."
    )
    st.success("Coming Soon")  # change to st.success("Active") once built
    st.caption("Tech: Python, dataclasses, Pydantic validation")

with row1_col2:
    st.subheader("Module 2: URN Prediction Core")
    st.write(
        "Predicts the full 1/3-octave band noise spectrum from 20 Hz to 20 kHz "
        "using a hybrid physics simulation and deep learning pipeline."
    )
    st.success("Coming Soon")
    st.caption("Tech: PyTorch, OpenFOAM, libAcoustics")

# Row 2
row2_col1, row2_col2 = st.columns(2)

with row2_col1:
    st.subheader("Module 3: IMO Compliance Checker")
    st.write(
        "Checks the predicted URN spectrum against IMO MEPC.1/Circ.906 Rev.1 "
        "(2024) limit tables and generates a downloadable compliance report."
    )
    st.success("Coming Soon")
    st.caption("Tech: IMO limit tables, ReportLab PDF generation")

with row2_col2:
    st.subheader("Module 4: Marine Bioacoustic Impact")
    st.write(
        "Maps ship noise against published audiogram curves for five marine mammal "
        "hearing groups and computes a Biological Interference Score for each."
    )
    st.success("Coming Soon")
    st.caption("Tech: librosa, scipy.signal, MFCC analysis")

# Row 3
row3_col1, row3_col2 = st.columns(2)

with row3_col1:
    st.subheader("Module 5: Mitigation Recommendation Engine")
    st.write(
        "Produces speed reduction targets, geographic routing avoidance zones, "
        "and hull and propeller modification suggestions ranked by expected dB reduction."
    )
    st.success("Coming Soon")
    st.caption("Tech: Rule-based recommendation engine, routing data")

with row3_col2:
    st.subheader("Module 6: Open URN Database")
    st.write(
        "A community-contributed, publicly searchable database of ship acoustic "
        "signatures. The first open-source database of its kind."
    )
    st.success("Coming Soon")
    st.caption("Tech: SQLite (dev), PostgreSQL (prod), public query API")

st.divider()

# =============================================================================
# Dataset Acquisition Status
# =============================================================================

st.header("Dataset Acquisition β€” Phase 1")

with st.expander("View dataset status", expanded=True):
    dataset_status = {
        "ShipsEar (Santos-Dominguez et al., 2016)": "Acquisition in progress",
        "QiandaoEar22 (arXiv:2406.04354)": "Pending",
        "Marine mammal audiograms (Southall et al., 2019)": "Pending",
        "IMO MEPC.1/Circ.906 Rev.1 limit tables": "Pending",
    }

    for dataset, status in dataset_status.items():
        col_ds, col_st = st.columns([3, 1])
        with col_ds:
            st.write(dataset)
        with col_st:
            if status == "Acquisition in progress":
                st.warning(status)
            else:
                st.info(status)

# =============================================================================
# Footer
# =============================================================================

st.divider()
st.markdown(
    f"<center style='color: grey; font-size: 0.85em;'>"
    f"SONARIS v{settings.PROJECT_VERSION} | "
    f"{settings.PROJECT_LICENSE} License | "
    f"github.com/deringeorge-nebula/SONARIS"
    f"</center>",
    unsafe_allow_html=True,
)