Update src/streamlit_app.py
Browse files- src/streamlit_app.py +22 -46
src/streamlit_app.py
CHANGED
|
@@ -1182,29 +1182,6 @@ def show_data_processing():
|
|
| 1182 |
format_func=lambda x: f"Dataset {x + 1}"
|
| 1183 |
)
|
| 1184 |
|
| 1185 |
-
# Pre-compute this dataset's actual time span (in 0.1 ms units) so we can
|
| 1186 |
-
# default the interpolation range sensibly and avoid extrapolation.
|
| 1187 |
-
def _dataset_time_max(idx):
|
| 1188 |
-
try:
|
| 1189 |
-
t_nd = np.array(st.session_state.t_nondim_all[0, idx]).flatten()
|
| 1190 |
-
zc = np.where(np.abs(t_nd) < 1e-10)[0]
|
| 1191 |
-
z = zc[0] if len(zc) else int(np.argmin(np.abs(t_nd)))
|
| 1192 |
-
tc = st.session_state.physical_params['tc_exp']
|
| 1193 |
-
t_ph = (t_nd * tc)[z:]
|
| 1194 |
-
return float(np.max(t_ph) * 1e4) # scale_exp = 1e4
|
| 1195 |
-
except Exception:
|
| 1196 |
-
return 1.0
|
| 1197 |
-
|
| 1198 |
-
data_t_max = _dataset_time_max(dataset_idx)
|
| 1199 |
-
# Round up to a clean step so the default fully covers the data
|
| 1200 |
-
default_range = float(np.ceil(data_t_max * 10) / 10) if data_t_max > 0 else 1.0
|
| 1201 |
-
default_range = min(max(default_range, 0.1), 2.0)
|
| 1202 |
-
|
| 1203 |
-
st.caption(
|
| 1204 |
-
f"π This dataset spans **t = 0 β {data_t_max:.3f}** (0.1 ms units). "
|
| 1205 |
-
f"Set the Interpolation Range at or below this value to avoid extrapolation."
|
| 1206 |
-
)
|
| 1207 |
-
|
| 1208 |
# Processing parameters
|
| 1209 |
col1, col2 = st.columns(2)
|
| 1210 |
with col1:
|
|
@@ -1212,10 +1189,9 @@ def show_data_processing():
|
|
| 1212 |
"Interpolation Range",
|
| 1213 |
min_value=0.1,
|
| 1214 |
max_value=2.0,
|
| 1215 |
-
value=
|
| 1216 |
step=0.1,
|
| 1217 |
-
help="Time range for interpolation
|
| 1218 |
-
"(shown above) so the curve is not extrapolated."
|
| 1219 |
)
|
| 1220 |
|
| 1221 |
with col2:
|
|
@@ -1264,23 +1240,31 @@ def show_data_processing():
|
|
| 1264 |
t_newunit_exp = t_newunit_exp[sort_indices]
|
| 1265 |
R_newunit_exp = R_newunit_exp[sort_indices]
|
| 1266 |
|
| 1267 |
-
# Interpolate
|
| 1268 |
-
#
|
| 1269 |
-
#
|
| 1270 |
-
|
| 1271 |
-
|
| 1272 |
-
effective_range = min(requested_range, t_data_max)
|
| 1273 |
-
|
| 1274 |
-
t_interp_newunit = np.arange(0, effective_range + time_step, time_step)
|
| 1275 |
pchip_interpolator = PchipInterpolator(
|
| 1276 |
t_newunit_exp, R_newunit_exp, extrapolate=False
|
| 1277 |
)
|
| 1278 |
R_interp_newunit = pchip_interpolator(t_interp_newunit)
|
| 1279 |
|
| 1280 |
-
#
|
| 1281 |
-
|
| 1282 |
-
|
| 1283 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1284 |
|
| 1285 |
# Store results
|
| 1286 |
st.session_state.t_interp_newunit = t_interp_newunit
|
|
@@ -1292,14 +1276,6 @@ def show_data_processing():
|
|
| 1292 |
|
| 1293 |
st.success(f"β
Data processed successfully! {len(R_interp_newunit)} interpolated points created.")
|
| 1294 |
|
| 1295 |
-
if requested_range > t_data_max + 1e-9:
|
| 1296 |
-
st.warning(
|
| 1297 |
-
f"β οΈ The Interpolation Range you set ({requested_range:.2f}) is larger than "
|
| 1298 |
-
f"this dataset's measured span (t ends at {t_data_max:.3f} in 0.1 ms units). "
|
| 1299 |
-
f"It was automatically clamped to {effective_range:.3f} so the curve is not "
|
| 1300 |
-
f"extrapolated. For best results, set the Interpolation Range to β {t_data_max:.3f}."
|
| 1301 |
-
)
|
| 1302 |
-
|
| 1303 |
except Exception as e:
|
| 1304 |
st.error(f"Processing failed: {str(e)}")
|
| 1305 |
|
|
|
|
| 1182 |
format_func=lambda x: f"Dataset {x + 1}"
|
| 1183 |
)
|
| 1184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1185 |
# Processing parameters
|
| 1186 |
col1, col2 = st.columns(2)
|
| 1187 |
with col1:
|
|
|
|
| 1189 |
"Interpolation Range",
|
| 1190 |
min_value=0.1,
|
| 1191 |
max_value=2.0,
|
| 1192 |
+
value=1.0,
|
| 1193 |
step=0.1,
|
| 1194 |
+
help="Time range for interpolation"
|
|
|
|
| 1195 |
)
|
| 1196 |
|
| 1197 |
with col2:
|
|
|
|
| 1240 |
t_newunit_exp = t_newunit_exp[sort_indices]
|
| 1241 |
R_newunit_exp = R_newunit_exp[sort_indices]
|
| 1242 |
|
| 1243 |
+
# Interpolate over the full requested range (default 1.0).
|
| 1244 |
+
# PchipInterpolator with extrapolate=False returns NaN beyond the
|
| 1245 |
+
# measured data; instead of extrapolating (which explodes), we hold
|
| 1246 |
+
# the last valid value constant (forward-fill).
|
| 1247 |
+
t_interp_newunit = np.arange(0, interp_range + time_step, time_step)
|
|
|
|
|
|
|
|
|
|
| 1248 |
pchip_interpolator = PchipInterpolator(
|
| 1249 |
t_newunit_exp, R_newunit_exp, extrapolate=False
|
| 1250 |
)
|
| 1251 |
R_interp_newunit = pchip_interpolator(t_interp_newunit)
|
| 1252 |
|
| 1253 |
+
# Forward-fill NaNs (points beyond the data) with the previous valid value
|
| 1254 |
+
nan_mask = np.isnan(R_interp_newunit)
|
| 1255 |
+
if nan_mask.any():
|
| 1256 |
+
valid_idx = np.where(~nan_mask)[0]
|
| 1257 |
+
if len(valid_idx) > 0:
|
| 1258 |
+
# Standard numpy forward-fill
|
| 1259 |
+
fill_idx = np.where(~nan_mask, np.arange(len(nan_mask)), 0)
|
| 1260 |
+
np.maximum.accumulate(fill_idx, out=fill_idx)
|
| 1261 |
+
R_interp_newunit = R_interp_newunit[fill_idx]
|
| 1262 |
+
# Guard against any leading NaNs (use first valid value)
|
| 1263 |
+
first_valid = valid_idx[0]
|
| 1264 |
+
if first_valid > 0:
|
| 1265 |
+
R_interp_newunit[:first_valid] = R_interp_newunit[first_valid]
|
| 1266 |
+
else:
|
| 1267 |
+
R_interp_newunit = np.zeros_like(R_interp_newunit)
|
| 1268 |
|
| 1269 |
# Store results
|
| 1270 |
st.session_state.t_interp_newunit = t_interp_newunit
|
|
|
|
| 1276 |
|
| 1277 |
st.success(f"β
Data processed successfully! {len(R_interp_newunit)} interpolated points created.")
|
| 1278 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1279 |
except Exception as e:
|
| 1280 |
st.error(f"Processing failed: {str(e)}")
|
| 1281 |
|