Skip to content

Commit 7d01bff

Browse files
committed
DSM2-1032 Add configuration for DSM2 EC analysis
1 parent 3c51824 commit 7d01bff

File tree

3 files changed

+316
-23
lines changed

3 files changed

+316
-23
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
output_locations: "info/DSM2_ec_loc_stds.csv"
2+
scenarios:
3+
- name: "1ex_2020"
4+
fpath: "scenarios/1ex_2020_EC_p.dss"
5+
- name: "7pp_2020"
6+
fpath: "scenarios/7pp_2020_EC_p.dss"
7+
variable: "EC-MEAN"
8+
interval: "1DAY"
9+
calsim_file: "scenarios/calsim.dss"
10+
delta_standards:
11+
- name: "D1641 AG WI"
12+
fpath: "info/D1641_AG_wiDelta.csv"
13+
variable: "EC-MEAN-14DAY"
14+
- name: "D1641 AG South"
15+
fpath: "info/D1641_AG_sDelta.csv"
16+
variable: "EC-MEAN-30DAY"
17+
- name: "D1641 AG Export"
18+
fpath: "info/D1641_AG_export.csv"
19+
variable: "EC-MEAN-30DAY"
20+
- name: "D1641 FWS SJR"
21+
fpath: "info/D1641_FWS_SJR.csv"
22+
variable: "EC-MEAN-14DAY"
23+
- name: "D1641 FWS Suisun"
24+
fpath: "info/D1641_FWS_Suisun.csv"
25+
variable: "EC-MAX-MEAN"
26+
- name: "D1641 MI 250"
27+
fpath: "info/D1641_MI_250.csv"
28+
variable: "Chloride-MEAN"
29+
- name: "D1641 MI 150"
30+
fpath: "info/D1641_MI_150.csv"
31+
variable: "Chloride-MEAN"
32+
#- name: "D1641 FWS Suisun1"
33+
# fpath: "info/D1641_FWS_Suisun1.csv"
34+
# variable: "EC-HT-MEAN"
35+
# interval: "1DAY"
36+
period:
37+
- "1921-01-01"
38+
- "2021-09-30"
39+
plots:
40+
- type: "plot_step_w_regulation"
41+
options:
42+
yaxis_name: "14-day running average EC - standard (mmhos/cm)"
43+
title: "EC 14-Day Mean for D1641_AG West&Interior Delta Timelines"
44+
delta_standard: "D1641 AG WI"
45+
- type: "plot_exceedance_w_regulation"
46+
options:
47+
yaxis_name: "14-day running average EC - standard (mmhos/cm)"
48+
title: "EC 14-Day Mean for D1641_AG West&Interior Delta Exceedances"
49+
delta_standard: "D1641 AG WI"
50+
- type: "plot_step_w_regulation"
51+
options:
52+
yaxis_name: "30-day running average EC - standard (mmhos/cm)"
53+
title: "EC 30-Day Mean for D1641_AG South Delta Timelines"
54+
delta_standard: "D1641 AG South"
55+
- type: "plot_exceedance_w_regulation"
56+
options:
57+
yaxis_name: "30-day running average EC - standard (mmhos/cm)"
58+
title: "EC 30-Day Mean for D1641_AG South Delta Exceedances"
59+
delta_standard: "D1641 AG South"
60+
- type: "plot_step_w_regulation"
61+
options:
62+
yaxis_name: "30-day running average EC - standard (mmhos/cm)"
63+
title: "EC 30-Day Mean for D1641_AG Export Timelines"
64+
delta_standard: "D1641 AG Export"
65+
- type: "plot_exceedance_w_regulation"
66+
options:
67+
yaxis_name: "30-day running average EC - standard (mmhos/cm)"
68+
title: "EC 30-Day Mean for D1641_AG Export Exceedances"
69+
delta_standard: "D1641 AG Export"
70+
- type: "plot_step_w_regulation"
71+
options:
72+
yaxis_name: "14-day running average EC - standard (mmhos/cm)"
73+
title: "EC 14-Day Mean for D1641_FWS San Joaquin River Timelines"
74+
delta_standard: "D1641 FWS SJR"
75+
- type: "plot_exceedance_w_regulation"
76+
options:
77+
yaxis_name: "14-day running average EC - standard (mmhos/cm)"
78+
title: "EC 14-Day Mean for D1641_FWS San Joaquin River Exceedances"
79+
delta_standard: "D1641 FWS SJR"
80+
- type: "plot_step_w_regulation"
81+
options:
82+
yaxis_name: "EC Monthly Mean of Daily Max (mmhos/cm)"
83+
title: "EC Monthly Mean of Daily Max for D1641_FWS Suisun Timelines"
84+
delta_standard: "D1641 FWS Suisun"
85+
- type: "plot_exceedance_w_regulation"
86+
options:
87+
yaxis_name: "Diff in EC scenario-standard (mmhos/cm)"
88+
title: "EC Monthly Mean of Daily Max for D1641_FWS Suisun Exceedances"
89+
delta_standard: "D1641 FWS Suisun"
90+
- type: "plot_step_w_regulation"
91+
options:
92+
yaxis_name: "Chloride Daily (mg/L)"
93+
title: "Chloride Daily for D1641 MI 250 Timelines"
94+
delta_standard: "D1641 MI 250"
95+
- type: "plot_exceedance_w_regulation"
96+
options:
97+
yaxis_name: "Chloride Daily -standard (mg/L)"
98+
title: "Chloride Daily for D1641 MI 250 Exceedances"
99+
delta_standard: "D1641 MI 250"
100+
- type: "plot_step_w_regulation"
101+
options:
102+
yaxis_name: "Number of days in year under regulation (day)"
103+
title: "Yearly number of days for D1641 MI 150 Timelines"
104+
delta_standard: "D1641 MI 150"
105+
- type: "plot_exceedance_w_regulation"
106+
options:
107+
yaxis_name: "Number of days under regulation - standard (day)"
108+
title: "Yearly number of days for D1641 MI 150 Exceedances"
109+
delta_standard: "D1641 MI 150"
110+
- type: "plot_step_w_variable_station_filters"
111+
options:
112+
yaxis_name: "Daily Mean EC (mmhos/cm)"
113+
title: "EC Daily Mean Timelines"
114+
- type: "plot_bar_monthly_w_controls"
115+
options:
116+
yaxis_name: "Daily Mean EC (mmhos/cm)"
117+
title: "EC Monthly Barcharts of Daily Mean"
118+
- type: "plot_exceedance_w_variable_station_filters"
119+
options:
120+
yaxis_name: "Daily Mean EC (mmhos/cm)"
121+
title: "EC Daily Mean Exceedances"
122+
- type: "plot_box_w_variable_station_filters"
123+
options:
124+
yaxis_name: "Daily Mean EC (mmhos/cm)"
125+
title: "EC Daily Mean Box-Whiskers"

pydelmod/nbplot/calsim_dsm2_analysis.py

Lines changed: 109 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@
44
import pydelmod.nbplot as pdmn
55
import yaml
66
import pathlib
7+
import logging
8+
9+
# Display the plots
10+
import panel as pn
11+
12+
pn.extension("plotly", "tabulator")
13+
14+
# Configure logger
15+
logging.basicConfig(level=logging.INFO)
16+
logger = logging.getLogger(__name__)
717

818

919
def load_config(config_file):
@@ -31,13 +41,50 @@ def read_output_locations(fpath):
3141
return df_stations
3242

3343

44+
def milli_to_micro(df):
45+
df["value"] = df["value"] * 1000.0
46+
return df
47+
48+
49+
def rsl_ec_to_cl(df):
50+
return df.apply(
51+
lambda x: max(x["value"] * 0.15 - 12.0, x["value"] * 0.285 - 50), axis=1
52+
)
53+
54+
55+
def read_regulations(fpath, df_wyt):
56+
df_reg = pd.read_csv(fpath)
57+
df_reg = pdmu.read_regulations(fpath, df_wyt)
58+
return df_reg
59+
60+
61+
def get_common_stations(df_stations, df_reg):
62+
reg_loc = df_reg.location.unique()
63+
return df_stations[df_stations["ID"].isin(reg_loc)]
64+
65+
66+
def generate_regulations(df_reg, df, freq="D"):
67+
df_reg_ag = pdmu.generate_regulation_timeseries(df_reg, df, freq)
68+
return df_reg_ag
69+
70+
3471
def read_scenarios(scenarios):
3572
return [
3673
{"name": scenario["name"], "fpath": scenario["fpath"]} for scenario in scenarios
3774
]
3875

3976

4077
def main(config_file):
78+
mainPanel = pn.Tabs()
79+
80+
def serve_main_panel():
81+
return mainPanel.show(title=f"DSM2 Analysis: {config_file}")
82+
83+
import threading
84+
85+
thread = threading.Thread(target=serve_main_panel, daemon=True)
86+
thread.start()
87+
4188
config = load_config(config_file)
4289

4390
df_stations = read_output_locations(config["output_locations"])
@@ -48,25 +95,70 @@ def main(config_file):
4895
df_wyt = pdmu.read_calsim3_wateryear_types(calsim_file)
4996

5097
period = config["period"]
51-
df_flow = pdmu.prep_df(
52-
scenarios,
53-
stations_to_read,
54-
[config["variable"]],
55-
[config["interval"]],
56-
df_wyt,
57-
period,
58-
)
59-
98+
delta_standards = {}
99+
if "delta_standards" in config:
100+
for standard in config["delta_standards"]:
101+
delta_standards[standard["name"]] = {
102+
"name": standard["name"],
103+
"fpath": standard["fpath"],
104+
"variable": standard["variable"],
105+
}
106+
#
60107
# Dynamically call plotting functions based on config
61108
plots = []
62109
for plot_config in config["plots"]:
110+
logger.info(f"Plotting: {plot_config}")
63111
plot_type = plot_config["type"]
64112
options = plot_config["options"]
65-
plot_func = getattr(pdmn, plot_type)
66-
plot = plot_func(df_flow, df_stations, options)
67-
plots.append((options["title"], plot))
68-
69-
# Display the plots
70-
import panel as pn
71-
72-
pn.Tabs(*plots).show(title=f"DSM2 Analysis: {config_file}")
113+
try:
114+
plot_func = getattr(pdmn, plot_type)
115+
if "regulation" in plot_type:
116+
if "delta_standard" in options:
117+
standard = delta_standards[options["delta_standard"]]
118+
df_standards = read_regulations(
119+
standard["fpath"],
120+
df_wyt,
121+
)
122+
if "EC" in standard["variable"]:
123+
df_standards = milli_to_micro(df_standards)
124+
df_standard_stations = get_common_stations(
125+
df_stations, df_standards
126+
)
127+
df = pdmu.prep_df(
128+
scenarios,
129+
list(df_standard_stations["ID"].unique()),
130+
[config["variable"]],
131+
[config["interval"]],
132+
df_wyt,
133+
period,
134+
)
135+
df_regulations = generate_regulations(df_standards, df, freq="D")
136+
df_regulations["variable"] = standard["variable"]
137+
df_regulations["scenario_name"] = standard["name"]
138+
if "MI" in options["delta_standard"]:
139+
df_cl = rsl_ec_to_cl(df.copy())
140+
if options["delta_standard"] == "D1641 MI 150":
141+
df_cl = pdmu.calculate_days_standard_met(df_cl, 150)
142+
args = (df_cl, df_regulations, df_standard_stations, options)
143+
else:
144+
args = (df, df_regulations, df_standard_stations, options)
145+
else:
146+
df = pdmu.prep_df(
147+
scenarios,
148+
list(df_stations["ID"].unique()),
149+
[config["variable"]],
150+
[config["interval"]],
151+
df_wyt,
152+
period,
153+
)
154+
args = (df, df_stations, options)
155+
plot = plot_func(*args)
156+
mainPanel.append((options["title"], plot))
157+
except Exception as e:
158+
import traceback
159+
160+
# create str representation of error with stack trace
161+
message = f"{e}\n{traceback.format_exc()}"
162+
mainPanel.append((options["title"], pn.pane.Str(message)))
163+
continue
164+
thread.join() # wait for the thread to finish

0 commit comments

Comments
 (0)