Skip to content

Commit d523157

Browse files
eli@water.ca.goveli@water.ca.gov
authored andcommitted
Fixed typing bug and changed/accelerated indexing behavior for suisun tests
1 parent d518ca7 commit d523157

1 file changed

Lines changed: 60 additions & 35 deletions

File tree

test_suite/test_smscg.py

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,35 @@
1616

1717

1818
def read_smscg_dfs(file_dir, time_basis=None):
19+
"""Reads the three time history files for the boat lock, flashboards, and radial gates into pandas DataFrames."""
1920
boat = read_th(
2021
os.path.join(file_dir, "montezuma_boat_lock.th"), time_basis=time_basis
2122
)
23+
boatcol = ["install", "ndup", "op_down", "op_up", "elev","width"]
24+
if boat.shape[1] == 7:
25+
boatcol = boatcol + ["__comment__"]
26+
boat.columns = boatcol
27+
2228
flash = read_th(os.path.join(file_dir, "montezuma_flash.th"), time_basis=time_basis)
29+
flashcol = ["install", "ndup", "op_down", "op_up", "elev","width"]
30+
if flash.shape[1] == 7:
31+
flashcol = flashcol + ["__comment__"]
32+
flash.columns = flashcol
33+
2334
radial = read_th(
2435
os.path.join(file_dir, "montezuma_radial.th"), time_basis=time_basis
2536
)
37+
radialcol = ["install", "ndup", "op_down", "op_up", "elev","width","height"]
38+
if radial.shape[1] == 8:
39+
radialcol = radialcol + ["__comment__"]
40+
radial.columns = radialcol
41+
42+
for df in [boat, flash, radial]:
43+
for col in ("install", "ndup"):
44+
if col in df.columns:
45+
df[col] = df[col].astype("Int64")
46+
if "__comment__" in df.columns:
47+
df["__comment__"] = df["__comment__"].astype("string")
2648

2749
return boat, flash, radial
2850

@@ -42,36 +64,39 @@ def elapse_smscg_dfs(smscg_dfs, params):
4264

4365

4466
def align_dfs(boat, flash, radial):
45-
"""Ensures alignment of the three dataframes and fills to radial index"""
46-
org_indices = sorted(set(pd.concat([boat, flash, radial]).index))
47-
boat = extend_idx(boat, org_indices[0], org_indices[-1])
48-
flash = extend_idx(flash, org_indices[0], org_indices[-1])
49-
radial = extend_idx(radial, org_indices[0], org_indices[-1])
50-
51-
boat = boat.resample("1min").asfreq().ffill()
52-
flash = flash.resample("1min").asfreq().ffill()
53-
radial = radial.resample("1min").asfreq().ffill()
54-
55-
# Get rid of unecessary (unchanged) timestamps
56-
boat = boat.loc[org_indices]
57-
flash = flash.loc[org_indices]
58-
radial = radial.loc[org_indices]
67+
"""
68+
Align three step-function-like time series on the union of their timestamps,
69+
using forward-fill semantics (no regular resampling grid).
70+
71+
Assumptions:
72+
- DatetimeIndex, sorted, unique (duplicates handled elsewhere).
73+
- Values represent state that persists until the next timestamp.
74+
- You want values defined over the full union span, so we pad each series
75+
to the global start/end using extend_idx().
76+
77+
Returns
78+
-------
79+
list[pd.DataFrame]
80+
[boat_aligned, flash_aligned, radial_aligned], each indexed by the union
81+
of original timestamps across all three inputs.
82+
"""
83+
# Union of all original timestamps (these are the only times we will keep)
84+
idx = pd.Index(pd.concat([boat, flash, radial]).index).unique().sort_values()
85+
86+
dfs = [boat, flash, radial]
87+
start = max(df.index.min() for df in dfs)
88+
end = min(df.index.max() for df in dfs)
89+
90+
idx = idx[(idx >= start) & (idx <= end)]
91+
92+
# Reindex to the union timestamps and forward-fill within each dataframe.
93+
# (ffill fills NaNs introduced by reindexing; start is guaranteed by extend_idx)
94+
boat = boat.reindex(idx).ffill()
95+
flash = flash.reindex(idx).ffill()
96+
radial = radial.reindex(idx).ffill()
5997
return [boat, flash, radial]
6098

6199

62-
def extend_idx(df, start, end):
63-
start_row = df.iloc[0].to_frame().T
64-
if start_row.index[0] > start:
65-
start_row.index = [start]
66-
df = pd.concat([start_row, df])
67-
end_row = df.iloc[-1].to_frame().T
68-
if end_row.index[0] < end:
69-
end_row.index = [end]
70-
df = pd.concat([df, end_row])
71-
72-
return df
73-
74-
75100
def compare_matches(matches, matches_hist):
76101
"""Compares two boolean series and returns a series that is True only where matches is True and matches_hist is False."""
77102

@@ -89,10 +114,10 @@ def compare_matches(matches, matches_hist):
89114

90115

91116
@pytest.mark.prerun
92-
def test_smscg_boatlock(sim_dir, params, elapse_smscg_dfs, historical_gates):
117+
def test_smscg_boatlock(sim_dir, params, smscg_dfs, historical_gates):
93118
"""Checks that the boatlock is open whenever the radial gates are operated tidally (op_up=0)"""
94119

95-
boat, flash, radial = elapse_smscg_dfs
120+
boat, flash, radial = smscg_dfs
96121

97122
# Compare the 4th column (op_up) of `boat` with `radial`
98123
matches = (radial.iloc[:, 3] == 0) & (boat.iloc[:, 3] == 0)
@@ -125,10 +150,10 @@ def test_smscg_boatlock(sim_dir, params, elapse_smscg_dfs, historical_gates):
125150

126151

127152
@pytest.mark.prerun
128-
def test_smscg_flash(sim_dir, params, elapse_smscg_dfs, historical_gates):
153+
def test_smscg_flash(sim_dir, params, smscg_dfs, historical_gates):
129154
"""Checks that the flashboards are closed when the radial gates are operated tidally (op_up=0)"""
130155

131-
boat, flash, radial = elapse_smscg_dfs
156+
boat, flash, radial = smscg_dfs
132157

133158
# Compare the 4th column (op_up) of `flash` with `radial`, ensuring that when radial gates are tidally operated, the flashboards are closed
134159
matches = (radial.iloc[:, 3] == 0) & (flash.iloc[:, 3] != 0)
@@ -160,10 +185,10 @@ def test_smscg_flash(sim_dir, params, elapse_smscg_dfs, historical_gates):
160185

161186

162187
@pytest.mark.prerun
163-
def test_smscg_radial_tides(sim_dir, params, elapse_smscg_dfs, historical_gates):
188+
def test_smscg_radial_tides(sim_dir, params, smscg_dfs, historical_gates):
164189
"""Checks that the tidal radial operations make sense"""
165190

166-
boat, flash, radial = elapse_smscg_dfs
191+
boat, flash, radial = smscg_dfs
167192

168193
# Compare the 3rd and 4th columns (op_down and op_up) of radial, ensuring tidal operation
169194
matches = (radial.iloc[:, 3] == 0) & (radial.iloc[:, 2] == 0)
@@ -196,10 +221,10 @@ def test_smscg_radial_tides(sim_dir, params, elapse_smscg_dfs, historical_gates)
196221

197222

198223
@pytest.mark.prerun
199-
def test_smscg_radial_open(sim_dir, params, elapse_smscg_dfs, historical_gates):
224+
def test_smscg_radial_open(sim_dir, params, smscg_dfs, historical_gates):
200225
"""Checks that the radial operations make sense"""
201226

202-
boat, flash, radial = elapse_smscg_dfs
227+
boat, flash, radial = smscg_dfs
203228

204229
# Compare the 3rd and 4th columns (op_down and op_up) of radial, ensuring tidal operation
205230
matches = (radial.iloc[:, 3] == 1) & (radial.iloc[:, 2] != 1)

0 commit comments

Comments
 (0)