pycoustic 0.1.11__py3-none-any.whl → 0.1.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,234 +0,0 @@
1
- # streamlit_pycoustic_app.py
2
- import ast
3
- import datetime as dt
4
- import tempfile
5
- from pathlib import Path
6
- from typing import Any, Dict, Iterable
7
-
8
- import streamlit as st
9
-
10
- from pycoustic import Log, Survey
11
-
12
-
13
- def _parse_kwargs(text: str) -> Dict[str, Any]:
14
- """
15
- Safely parse a Python dict literal from text area.
16
- Returns {} if empty or invalid.
17
- """
18
- if not text or not text.strip():
19
- return {}
20
- try:
21
- parsed = ast.literal_eval(text)
22
- return parsed if isinstance(parsed, dict) else {}
23
- except Exception:
24
- return {}
25
-
26
-
27
- def _display_result(obj: Any):
28
- """
29
- Display helper to handle common return types.
30
- """
31
- # Plotly Figure-like
32
- if hasattr(obj, "to_plotly_json"):
33
- st.plotly_chart(obj, use_container_width=True)
34
- return
35
-
36
- # Pandas DataFrame-like
37
- if hasattr(obj, "to_dict") and hasattr(obj, "columns"):
38
- st.dataframe(obj, use_container_width=True)
39
- return
40
-
41
- # Dict/list -> JSON
42
- if isinstance(obj, (dict, list)):
43
- st.json(obj)
44
- return
45
-
46
- # Fallback
47
- st.write(obj)
48
-
49
-
50
- def _ensure_state():
51
- if "survey" not in st.session_state:
52
- st.session_state["survey"] = None
53
- if "periods" not in st.session_state:
54
- st.session_state["periods"] = {"day": (7, 0), "evening": (19, 0), "night": (23, 0)}
55
-
56
-
57
- def _write_uploaded_to_temp(uploaded) -> str:
58
- """
59
- Persist an UploadedFile to a temporary file and return the path.
60
- Using a real file path keeps Log(...) happy across environments.
61
- """
62
- suffix = Path(uploaded.name).suffix or ".csv"
63
- with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
64
- tmp.write(uploaded.getbuffer())
65
- return tmp.name
66
-
67
-
68
- def _build_survey_from_files(files) -> Survey:
69
- """
70
- Create a Survey and attach Log objects for each uploaded file.
71
- """
72
- survey = Survey()
73
- for f in files:
74
- # Persist to disk to ensure compatibility with pandas and any path usage in Log
75
- tmp_path = _write_uploaded_to_temp(f)
76
- log_obj = Log(path=tmp_path)
77
-
78
- key = Path(f.name).stem
79
- # Attach Log to survey
80
- if hasattr(survey, "add_log"):
81
- try:
82
- survey.add_log(key, log_obj)
83
- except TypeError:
84
- survey.add_log(log_obj, key)
85
- else:
86
- # Fallback to internal storage if no public API is available
87
- survey._logs[key] = log_obj # noqa: SLF001
88
- return survey
89
-
90
-
91
- def _apply_periods_to_all_logs(survey: Survey, times: Dict[str, tuple[int, int]]):
92
- """
93
- Apply set_periods to each Log attached to the Survey.
94
- This avoids calling set_periods on Survey if it doesn't exist.
95
- """
96
- logs: Iterable[Log] = getattr(survey, "_logs", {}).values()
97
- for log in logs:
98
- if hasattr(log, "set_periods"):
99
- log.set_periods(times=times)
100
-
101
-
102
- def _render_period_controls(survey: Survey):
103
- st.subheader("Assessment Periods")
104
-
105
- # Current periods from session (defaults set in _ensure_state)
106
- periods = st.session_state["periods"]
107
- day_h, day_m = periods["day"]
108
- eve_h, eve_m = periods["evening"]
109
- night_h, night_m = periods["night"]
110
-
111
- c1, c2, c3 = st.columns(3)
112
- with c1:
113
- day_time = st.time_input("Day starts", value=dt.time(day_h, day_m), key="period_day_start")
114
- with c2:
115
- eve_time = st.time_input("Evening starts", value=dt.time(eve_h, eve_m), key="period_eve_start")
116
- with c3:
117
- night_time = st.time_input("Night starts", value=dt.time(night_h, night_m), key="period_night_start")
118
-
119
- new_periods = {
120
- "day": (int(day_time.hour), int(day_time.minute)),
121
- "evening": (int(eve_time.hour), int(eve_time.minute)),
122
- "night": (int(night_time.hour), int(night_time.minute)),
123
- }
124
-
125
- if st.button("Apply periods to all logs", key="apply_periods"):
126
- try:
127
- _apply_periods_to_all_logs(survey, new_periods)
128
- st.session_state["periods"] = new_periods
129
- st.success("Periods applied to all logs.")
130
- except Exception as e:
131
- st.warning(f"Could not set periods: {e}")
132
-
133
-
134
- def _render_method_runner(survey: Survey, method_name: str, help_text: str = ""):
135
- """
136
- Generic UI for running a Survey method with kwargs provided via text area.
137
- """
138
- with st.expander(method_name, expanded=True):
139
- if help_text:
140
- st.caption(help_text)
141
-
142
- kwargs_text = st.text_area(
143
- "kwargs (Python dict literal)",
144
- value="{}",
145
- key=f"kwargs_{method_name}",
146
- placeholder='Example: {"position": "UA1", "date": "2023-06-01"}',
147
- height=100,
148
- )
149
-
150
- kwargs = _parse_kwargs(kwargs_text)
151
- if st.button(f"Run {method_name}", key=f"run_{method_name}"):
152
- try:
153
- fn = getattr(survey, method_name)
154
- result = fn(**kwargs)
155
- _display_result(result)
156
- except AttributeError:
157
- st.error(f"Survey has no method named '{method_name}'.")
158
- except Exception as e:
159
- st.error(f"Error running {method_name}: {e}")
160
-
161
-
162
- def main():
163
- st.set_page_config(page_title="pycoustic GUI", layout="wide")
164
- st.title("pycoustic – Streamlit GUI")
165
-
166
- _ensure_state()
167
-
168
- st.sidebar.header("Load CSV Logs")
169
- files = st.sidebar.file_uploader(
170
- "Upload one or more CSV files",
171
- type=["csv"],
172
- accept_multiple_files=True,
173
- help="Each file becomes a Log; all Logs go into one Survey."
174
- )
175
-
176
- build = st.sidebar.button("Create / Update Survey", type="primary")
177
-
178
- if build and files:
179
- try:
180
- survey = _build_survey_from_files(files)
181
- # Apply default periods to all logs
182
- _apply_periods_to_all_logs(survey, st.session_state["periods"])
183
- st.session_state["survey"] = survey
184
- st.success("Survey created/updated.")
185
- except Exception as e:
186
- st.error(f"Unable to create Survey: {e}")
187
-
188
- survey: Survey = st.session_state.get("survey")
189
-
190
- if survey is None:
191
- st.info("Upload CSV files in the sidebar and click 'Create / Update Survey' to begin.")
192
- return
193
-
194
- # Period controls
195
- _render_period_controls(survey)
196
-
197
- st.markdown("---")
198
- st.header("Survey Outputs")
199
-
200
- _render_method_runner(
201
- survey,
202
- "resi_summary",
203
- help_text="Summary results for residential assessment. Provide any optional kwargs here."
204
- )
205
- _render_method_runner(
206
- survey,
207
- "modal",
208
- help_text="Run modal analysis over the survey. Provide any optional kwargs here."
209
- )
210
- _render_method_runner(
211
- survey,
212
- "leq_spectra",
213
- help_text="Compute or plot Leq spectra. Provide any optional kwargs here."
214
- )
215
- _render_method_runner(
216
- survey,
217
- "lmax_spectra",
218
- help_text="Compute or plot Lmax spectra. Provide any optional kwargs here."
219
- )
220
-
221
- st.markdown("---")
222
- with st.expander("Loaded Logs", expanded=False):
223
- try:
224
- names = list(getattr(survey, "_logs", {}).keys())
225
- if names:
226
- st.write(", ".join(names))
227
- else:
228
- st.write("No logs found in survey.")
229
- except Exception:
230
- st.write("Unable to list logs.")
231
-
232
-
233
- if __name__ == "__main__":
234
- main()
@@ -1,14 +0,0 @@
1
- pycoustic/__init__.py,sha256=jq9Tzc5nEgXh8eNf0AkAypmw3Dda9A-iSy-tyFaTksA,89
2
- pycoustic/log.py,sha256=e8rAy9hIYP2H-3vTDVe0-6swe_n_gXjuFCu6Q-xNiYQ,17827
3
- pycoustic/pycoustic_gui_app-ai.py,sha256=nEX7Q5oWzTLmtC_xqbh74vXpQak8gwuqf2ScPq1Ir7o,24432
4
- pycoustic/pycoustic_gui_app.py,sha256=Hs61Y8fAp7uoRONa4RLSVl0UvGXZZ96n5eJGilErlAU,11143
5
- pycoustic/pycoustic_streamlit_gpt5.py,sha256=gpkPPBGwADt9HFI4S7YD1U-TjpLTMVwcBUJd7wTefek,14259
6
- pycoustic/streamlit-ai.py,sha256=OZdrQbGwQyVvA_4Q8bTOCZUZGdSlZG9NL9z3f16W-A8,16414
7
- pycoustic/streamlit-new.py,sha256=AR5dwQinMXugvGcyNvI_W59bfFRGj6E90Fqah9toKto,4885
8
- pycoustic/streamlit_pycoustic_gpt5_dead.py,sha256=sFUxLkvNUZoh2cVzruqsJJiLIlJxOQQpYYK6oHZfPlM,7309
9
- pycoustic/survey.py,sha256=GFbesunnfsDMP6rpEmVNBRxFkQ3c0NgHEVn0mGfeQCY,28120
10
- pycoustic/tkgui.py,sha256=YAy5f_qkXZ3yU8BvB-nIVQX1fYwPs_IkwmDEXHPMAa4,13997
11
- pycoustic/weather.py,sha256=q9FbDKjY0WaNvaYMHeDk7Bhbq0_Q7ehsTM_vUaCjeAk,3753
12
- pycoustic-0.1.11.dist-info/METADATA,sha256=ne7ZzFdkEEapdG6P9xl4zMIwUzFTnCcjuCmV32Fhz7s,8516
13
- pycoustic-0.1.11.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
14
- pycoustic-0.1.11.dist-info/RECORD,,