github-actions[bot] commited on
Commit
245b5cd
·
1 Parent(s): 4f7ea6b

Deploy from GitHub Actions

Browse files
Files changed (3) hide show
  1. analysis.py +54 -18
  2. pages.py +14 -10
  3. ui/pages/dissolved_oxygen.py +17 -9
analysis.py CHANGED
@@ -1224,39 +1224,75 @@ def plot_do_temp_relationship(df: pd.DataFrame) -> Figure:
1224
  .dropna(subset=["Dissolved Oxygen", "Temperature, Water"])
1225
  )
1226
 
1227
- sns.set_palette("muted")
 
1228
 
1229
- # Create plot with regression line
1230
  g = sns.lmplot(
1231
  data=do_temp_data,
1232
  x="Temperature, Water",
1233
  y="Dissolved Oxygen",
1234
  hue="Sample_Position",
1235
- hue_order=["Surface", "Bottom"],
1236
- scatter_kws={"alpha": 0.6},
 
 
1237
  height=8,
1238
  aspect=1.5,
1239
  legend=False,
1240
  )
1241
 
1242
- # Add DO threshold and customize plot
1243
  ax = g.axes[0, 0]
1244
- ax.axhline(y=5, color="red", linestyle=":", alpha=0.5)
 
 
1245
  ax.text(
1246
  ax.get_xlim()[0],
1247
- 5.1,
1248
- " 5 mg/L DO threshold",
1249
  ha="left",
1250
  va="bottom",
1251
- color="red",
1252
- alpha=0.5,
1253
  )
1254
 
 
 
 
 
 
 
 
1255
  g.set_axis_labels("Water Temperature (°C)", "Dissolved Oxygen (mg/L)")
1256
  ax.set_title("Dissolved Oxygen vs Water Temperature", pad=20, fontsize=16)
1257
- ax.legend(title="Sample Position", bbox_to_anchor=(1.05, 1), loc="upper left")
1258
- # Add grid
1259
- ax.grid(True, alpha=0.3)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1260
 
1261
  return g.figure
1262
 
@@ -1348,16 +1384,16 @@ def plotly_plot_do_temp_relationship(df: pd.DataFrame) -> go.Figure:
1348
 
1349
  # Add DO threshold line
1350
  fig.add_hline(
1351
- y=5,
1352
- line=dict(color="red", width=1, dash="dot"),
1353
  opacity=0.5,
1354
- annotation_text="5 mg/L DO threshold",
1355
  annotation_position="left",
1356
  annotation=dict(
1357
- font=dict(color="red", size=12),
1358
  xanchor="left",
1359
  yanchor="bottom",
1360
- opacity=0.5,
1361
  ),
1362
  )
1363
 
 
1224
  .dropna(subset=["Dissolved Oxygen", "Temperature, Water"])
1225
  )
1226
 
1227
+ # Create custom color palette matching DO timeseries
1228
+ custom_palette = {"Surface": "#5AA4D8", "Bottom": "#1B4B8A"}
1229
 
1230
+ # Create plot with regression line and adjust the hue order
1231
  g = sns.lmplot(
1232
  data=do_temp_data,
1233
  x="Temperature, Water",
1234
  y="Dissolved Oxygen",
1235
  hue="Sample_Position",
1236
+ hue_order=["Bottom", "Surface"], # Plot 'Bottom' first
1237
+ palette=custom_palette,
1238
+ scatter_kws={"alpha": 0.5, "zorder": 2, "s": 20}, # Scatter plots at zorder=2
1239
+ line_kws={"zorder": 3, "linewidth": 1}, # Trend lines at zorder=3
1240
  height=8,
1241
  aspect=1.5,
1242
  legend=False,
1243
  )
1244
 
1245
+ # Add DO threshold and set z-order
1246
  ax = g.axes[0, 0]
1247
+ ax.axhline(
1248
+ y=4.8, color="#FF8C00", linestyle="--", alpha=0.9, zorder=1, linewidth=1
1249
+ ) # Threshold line at zorder=1
1250
  ax.text(
1251
  ax.get_xlim()[0],
1252
+ 4.9,
1253
+ " 4.8 mg/L DO threshold",
1254
  ha="left",
1255
  va="bottom",
1256
+ color="#FF8C00",
1257
+ alpha=0.9,
1258
  )
1259
 
1260
+ # Customize spines - only show bottom spine
1261
+ ax.spines["top"].set_visible(False)
1262
+ ax.spines["right"].set_visible(False)
1263
+ ax.spines["left"].set_visible(False)
1264
+ ax.spines["bottom"].set_color("black")
1265
+ ax.spines["bottom"].set_linewidth(0.5)
1266
+
1267
  g.set_axis_labels("Water Temperature (°C)", "Dissolved Oxygen (mg/L)")
1268
  ax.set_title("Dissolved Oxygen vs Water Temperature", pad=20, fontsize=16)
1269
+
1270
+ # Adjust legend to show 'Surface' first
1271
+ handles, labels = ax.get_legend_handles_labels()
1272
+ # Reverse the order of handles and labels
1273
+ handles = handles[::-1]
1274
+ labels = labels[::-1]
1275
+ ax.legend(
1276
+ handles,
1277
+ labels,
1278
+ bbox_to_anchor=(1.0, 1.0),
1279
+ loc="upper right",
1280
+ frameon=False,
1281
+ handletextpad=0.5,
1282
+ )
1283
+
1284
+ # Add grid with matching style
1285
+ ax.grid(True, axis="y", alpha=0.15, linestyle="-", color="gray")
1286
+
1287
+ # Remove tick marks but keep labels
1288
+ ax.tick_params(axis="y", which="both", length=0)
1289
+
1290
+ # Set y-axis limits with some padding
1291
+ ymin = max(int(min(do_temp_data["Dissolved Oxygen"].min(), 4.8) * 0.9) - 1, 0)
1292
+ ymax = do_temp_data["Dissolved Oxygen"].max() * 1.1
1293
+ ax.set_ylim(ymin, ymax)
1294
+ yticks = np.arange(ymin, ymax, 2)
1295
+ ax.set_yticks(yticks)
1296
 
1297
  return g.figure
1298
 
 
1384
 
1385
  # Add DO threshold line
1386
  fig.add_hline(
1387
+ y=4.8,
1388
+ line=dict(color="#FF8C00", width=1, dash="dash"),
1389
  opacity=0.5,
1390
+ annotation_text="4.8 mg/L DO threshold",
1391
  annotation_position="left",
1392
  annotation=dict(
1393
+ font=dict(color="#FF8C00", size=12),
1394
  xanchor="left",
1395
  yanchor="bottom",
1396
+ opacity=0.8,
1397
  ),
1398
  )
1399
 
pages.py CHANGED
@@ -332,16 +332,20 @@ def data_summary_section():
332
  @log_page_visit()
333
  def do_temp_relationship_section():
334
  st.sidebar.toggle("Interactive Plots", key="ENABLE_ALTAIR")
335
- st.title("DO/Temp Relationship")
336
- st.markdown(
337
- "This plot shows the relationship between dissolved oxygen and water temperature for all data."
338
- )
339
- if st.session_state.ENABLE_ALTAIR:
340
- fig = plotly_plot_do_temp_relationship(st.session_state.data["raw_df"])
341
- st.plotly_chart(fig, use_container_width=True) # type: ignore
342
- else:
343
- fig = plot_do_temp_relationship(st.session_state.data["raw_df"])
344
- st.pyplot(fig)
 
 
 
 
345
 
346
 
347
  @log_page_visit()
 
332
  @log_page_visit()
333
  def do_temp_relationship_section():
334
  st.sidebar.toggle("Interactive Plots", key="ENABLE_ALTAIR")
335
+
336
+ container = st.container()
337
+ with container:
338
+ left_spacer, content, right_spacer = st.columns([1, 8, 1])
339
+ with content:
340
+ if st.session_state.ENABLE_ALTAIR:
341
+ fig = plotly_plot_do_temp_relationship(st.session_state.data["raw_df"])
342
+ st.plotly_chart(fig, use_container_width=True) # type: ignore
343
+ else:
344
+ fig = plot_do_temp_relationship(st.session_state.data["raw_df"])
345
+ st.pyplot(fig)
346
+ st.info(
347
+ "This plot shows the relationship between dissolved oxygen and water temperature for all data."
348
+ )
349
 
350
 
351
  @log_page_visit()
ui/pages/dissolved_oxygen.py CHANGED
@@ -20,12 +20,20 @@ def dissolved_oxygen():
20
  return plot_do_timeseries(filtered_df, period=period)
21
 
22
 
23
- st.info(
24
- """
25
- This is a half-baked attempt to replicate the Hudson River Estuary Program's excellent
26
- [Long Term Findings chart for dissolved oxygen](https://www.hudsonriver.org/ccmp/soe/water-quality/do).
27
- The EPA threshold is copied from the reference image and not specific to the water quality standards for our area.
28
- """
29
- )
30
- fig = dissolved_oxygen()
31
- st.pyplot(fig)
 
 
 
 
 
 
 
 
 
20
  return plot_do_timeseries(filtered_df, period=period)
21
 
22
 
23
+ # Create a centered container with custom width
24
+ container = st.container()
25
+ with container:
26
+ # Create three columns with ratios 1:8:1 (10% : 80% : 10%)
27
+ left_spacer, content, right_spacer = st.columns([1, 8, 1])
28
+
29
+ # Put content in middle column
30
+ with content:
31
+ st.info(
32
+ """
33
+ :material/info: This is a half-baked attempt to replicate the Hudson River Estuary Program's excellent
34
+ [Long Term Findings chart](https://www.hudsonriver.org/ccmp/soe/water-quality/do) for dissolved oxygen.
35
+ The EPA threshold is copied from the reference image and not specific to the water quality standards for our area.
36
+ """
37
+ )
38
+ fig = dissolved_oxygen()
39
+ st.pyplot(fig)