Skip to content

Commit 2ec47ca

Browse files
eli@water.ca.goveli@water.ca.gov
authored andcommitted
Fixed bugs in hotstart_inventory.py
1 parent d13f959 commit 2ec47ca

2 files changed

Lines changed: 152 additions & 88 deletions

File tree

schimpy/hotstart_inventory.py

Lines changed: 151 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -8,136 +8,200 @@
88
import os
99
import pandas as pd
1010
from schimpy.param import *
11-
from vtools import days
11+
from vtools import days,seconds
1212

1313

1414

15+
def expected_hotstarts(run_start, dt, nday, hot_freq):
16+
"""
17+
Generate expected hotstarts based on run parameters.
18+
Parameters
19+
----------
20+
run_start : datetime
21+
The start time of the simulation run.
22+
dt : int
23+
The time step in seconds.
24+
nday : int
25+
The number of days for the simulation run.
26+
hot_freq : pandas.tseries.offsets.DateOffset
27+
The frequency at which hotstarts are generated.
28+
Returns
29+
-------
30+
pandas.DataFrame
31+
A DataFrame with a DatetimeIndex representing the expected hotstart times
32+
and a column "iteration" indicating the corresponding iteration numbers.
33+
Notes
34+
-----
35+
This function calculates the expected hotstart times and their corresponding
36+
iteration numbers based on the provided simulation parameters. It does not
37+
perform any file inventory or check for existing hotstart files.
38+
"""
39+
"""Generate expected hotstarts based on run parameters."""
40+
41+
end = run_start + days(nday)
42+
t = run_start
43+
iters = []
44+
times = []
45+
dt_freq = pd.tseries.offsets.Second(dt)
46+
iters_per_hot = hot_freq / dt_freq
47+
itr = 0
48+
print("Projected hotstarts (not inventory of files)")
49+
while t < end:
50+
times.append(t)
51+
iters.append(itr)
52+
t = t + hot_freq
53+
itr = itr + int(iters_per_hot)
54+
print(f"t={t}, itr={itr}")
55+
ndx = pd.DatetimeIndex(times)
56+
df = pd.DataFrame(index=ndx, data=iters)
57+
df.columns = ["iteration"]
58+
df.index.name = "datetime"
59+
return df
60+
61+
1562
def hotstart_inventory(run_start=None,
1663
dt=None,
1764
nday=None,
1865
workdir='.',
1966
paramfile=None,
20-
hot_freq=None
21-
):
22-
""" Create an inventory of existing hotstarts or expected hotstarts
67+
hot_freq=None,
68+
expected=False):
69+
"""
70+
Create an inventory of existing hotstarts or expected hotstarts.
71+
72+
Whether the inventory is for existing or expected hotstarts depends on
73+
whether the workdir is an outputs directory or a study directory.
2374
24-
Existing vs expected depends on whether workdir is an outputs or study dir.
25-
2675
Parameters
2776
----------
77+
run_start : str or pandas.Timestamp, optional
78+
The start time of the simulation run in ISO-like format (e.g., '2013-12-03').
79+
dt : int, optional
80+
The time step in seconds of the model. Default is None.
81+
nday : int, optional
82+
The number of days in the simulation run or the maximum to catalog. Default is None.
83+
workdir : str, optional
84+
The working directory, which may be a launch or outputs directory. Default is '.'.
85+
paramfile : str, optional
86+
The name of the param.nml file if it is used to infer runtime. Default is None.
87+
hot_freq : str or pandas.tseries.offsets.DateOffset, optional
88+
The hotstart frequency in pandas frequency terms (e.g., '5D'). Default is None.
89+
expected : bool, optional
90+
Flag to generate expected hotstarts instead of an inventory of existing files. Default is False.
2891
29-
start : Convertible to Datetime
30-
Start date of run. If None inferred from paramfile. Error if
31-
32-
dt : float
33-
dt in seconds, for instance perhaps 90s for clinic or 120s for tropic. This
34-
is needed to intepret the so-called iteration number in the hotstart labels
35-
which are really time step numbers.
36-
37-
workdir : str
38-
Directory to inventory. If it is an outputs directory, the inventory
39-
comprise existing hotstarts.
40-
41-
paramfile : str
42-
Name of param.nml file, expected in workdir or workdir/.. If None, then
43-
both start and dt must be supplied. If all three are None, the name "param.nml" will
44-
be attempted
45-
46-
4792
Returns
4893
-------
49-
Dataframe, if programatic, listing hotstarts. Should look like "Date, Iteration" pairs. CLI should print it out.
50-
51-
Notes
52-
-----
53-
If the listing is done in the run dir, this will be the expected hotstarts. If
54-
it is in the outputs dir, it will be an inventory of existing hotstarts.
55-
94+
pandas.DataFrame or None
95+
A DataFrame containing the inventory of hotstarts with a DatetimeIndex and a column "iteration".
96+
If no hotstarts are found and `expected` is False, returns None.
5697
"""
98+
5799
run_start = pd.to_datetime(run_start)
58100
if type(hot_freq) == str:
59101
hot_freq = pd.tseries.frequencies.to_offset(hot_freq)
60-
print(run_start,dt,paramfile,workdir,hot_freq)
61-
hots = glob.glob(os.path.join(workdir,"hotstart_000000_*.nc"))
62-
is_existing = (len(hots) > 0)
63-
print("is_existing",is_existing)
64-
param_needed = (dt is None) or (run_start is None) or (hot_freq is None and not is_existing )
65102

103+
hots = glob.glob(os.path.join(workdir, "hotstart_000000_*.nc"))
104+
is_existing = (len(hots) > 0)
105+
print(workdir)
106+
param_needed = (dt is None) or (run_start is None) or (hot_freq is None and not is_existing) or pd.isnull(run_start)
107+
print("Existing hotstarts found:", is_existing, " params read from file: " + str(param_needed))
66108
if param_needed:
67-
if paramfile is None:
109+
if paramfile is None or paramfile == "":
68110
paramfile = 'param.nml'
69-
if is_existing or not os.path.exists(paramfile):
70-
paramfile = os.path.join(workdir,'..',paramfile)
71-
111+
print("got here", paramfile, workdir)
112+
if os.path.exists(os.path.join(workdir, "..", paramfile)):
113+
paramfile = os.path.join(workdir, "..", paramfile)
72114
params = read_params(paramfile)
73115
dt_param = params['dt']
74116
run_start_param = params.run_start
75117
run_len_param = params['rnday']
76118
hot_freq_param = params.hotstart_freq
77-
print("run_start",run_start,run_start_param)
78-
if run_start is None or pd.isnull(run_start) :
79-
print("yo",run_start_param)
119+
print(f"dt={dt_param}, run_start={run_start_param}, run_len={run_len_param}, hot_freq={hot_freq_param}")
120+
if run_start is None or pd.isnull(run_start):
80121
run_start = run_start_param
81-
if dt is None: dt = dt_param
82-
if nday is None or nday == 0: nday = run_len_param
83-
if hot_freq is None: hot_freq=hot_freq_param
84-
if not is_existing:
85-
print("hello",run_start,dt,paramfile,workdir,hot_freq)
86-
end = run_start + days(nday)
87-
t = run_start
88-
iters = []
89-
times = []
90-
dt_freq = pd.tseries.offsets.Second(dt)
91-
iters_per_hot = hot_freq/dt_freq
92-
itr = 0
93-
print(hot_freq,dt_freq,t,end,nday)
94-
while (t<end):
95-
times.append(t)
96-
iters.append(itr)
97-
t = t + hot_freq
98-
itr = itr + int(iters_per_hot)
99-
print(f"t={t},itr={itr}")
100-
ndx = pd.DatetimeIndex(times)
101-
df = pd.DataFrame(index=ndx,data=iters)
102-
df.columns=["iteration"]
103-
df.index.name="datetime"
104-
print(df)
105-
106-
107-
def hotstart_inventory2(start,dt=90):
108-
# convert start time string input to datetime
109-
if isinstance(start,str):
110-
start = dtm.date.fromisoformat(start)
111-
#start=list(map(int, re.split('[^\d]', start)))
122+
if dt is None:
123+
dt = dt_param
124+
if nday is None or nday == 0:
125+
nday = run_len_param
126+
if hot_freq is None:
127+
hot_freq = hot_freq_param
128+
129+
if expected:
130+
expected_df = expected_hotstarts(run_start, dt, nday, hot_freq)
131+
print(expected_df)
132+
return expected_df
133+
134+
if is_existing:
135+
return hotstart_inventory_exist(run_start, dt, workdir)
136+
else:
137+
return None
138+
139+
140+
141+
def hotstart_inventory_exist(start,dt=90,workdir='.',do_print=True):
142+
"""
143+
Check for the existence of hotstart inventory files and generate a DataFrame
144+
mapping iterations to corresponding datetime values.
145+
Parameters
146+
----------
147+
start : str or pandas.Timestamp
148+
The start time as a string or pandas.Timestamp object.
149+
dt : int, optional
150+
Time step in seconds between iterations (default is 90).
151+
workdir : str, optional
152+
Directory to search for hotstart files (default is '.').
153+
do_print : bool, optional
154+
Whether to print the iterations and corresponding times (default is True).
155+
Returns
156+
-------
157+
pandas.DataFrame
158+
A DataFrame with datetime as the index and iteration numbers as the column.
159+
Notes
160+
-----
161+
- The function searches for hotstart files in the specified `workdir` directory.
162+
- If no files are found in `workdir`, it searches in the current directory.
163+
- The function assumes hotstart files follow the naming pattern
164+
"hotstart_000000_<iteration>.nc".
165+
"""
112166

113-
hots = glob.glob("hotstart_000000_*.nc")
167+
print("Hotstart Inventory")
168+
if isinstance(start,str):
169+
start = pd.Timestamp(start)
170+
hots = glob.glob(os.path.join(workdir,"hotstart_000000_*.nc"))
114171
if len(hots) == 0:
115-
hots = glob.glob("hotstart_0000_*.nc")
172+
hots = glob.glob(os.path.join("hotstart_0000_*.nc"))
116173
hots.sort()
117174
iters = [int(x.split("_")[2].replace(".nc","")) for x in hots]
118175

119176
iters.sort()
120-
times = [start + dtm.timedelta(seconds=x*dt) for x in iters]
177+
times = [start + seconds(x*dt) for x in iters]
178+
df = pd.DataFrame(index=times,data=iters)
179+
df.columns=["iteration"]
180+
df.index.name="datetime"
181+
182+
if do_print:
183+
for it,t in zip(iters,times):
184+
print("{}: {}".format(it,t))
121185

122-
for it,t in zip(iters,times):
123-
print("{}: {}".format(it,t))
186+
return df
124187

125188
def create_arg_parser():
126189
parser = argparse.ArgumentParser("Lookup station metadata by partial string match on id or name")
127-
parser.add_argument('--dt',default=90,type=int,help="Time step in seconds of model")
128-
parser.add_argument('--run_start',default="",help = 'Start time in iso-like format, e.g. 2013-12-03')
129-
parser.add_argument('--nday',default=0,type=int,help = 'Number of days in simulation (rnday) or maximum to catalog')
130-
parser.add_argument('--workdir',default='.',type=str,help="working directory, which may be a launch or outputs dir")
131-
parser.add_argument('--paramfile',default="",type=str,help = 'Name of param.nml file if file is used to infer runtime')
132-
parser.add_argument('--hot_freq',default=None,help = "`Hotstart frequency in pandas freq terms (e.g. '5D')")
133-
return parser
190+
parser.add_argument('--dt', default=90, type=int, help="Time step in seconds of model")
191+
parser.add_argument('--run_start', default="", help='Start time in iso-like format, e.g. 2013-12-03')
192+
parser.add_argument('--nday', default=0, type=int, help='Number of days in simulation (rnday) or maximum to catalog')
193+
parser.add_argument('--workdir', default='.', type=str, help="Working directory, which is the outputs dir")
194+
parser.add_argument('--paramfile', default="", type=str, help='Name of param.nml file if file is used to infer runtime. If neither params nor paramfile provided, ./param.nmo or ../param.nml will be tried. ')
195+
parser.add_argument('--hot_freq', default=None, help="Hotstart frequency in pandas freq terms (e.g. '5D')")
196+
parser.add_argument('--expected', action='store_true', help="Flag to generate expected hotstarts instead of inventory of existing files")
197+
return parser
134198

135199

136200

137201
def main():
138202
parser = create_arg_parser()
139203
args = parser.parse_args()
140-
hotstart_inventory(args.run_start,args.dt,args.nday,args.workdir,args.paramfile,args.hot_freq)
204+
hotstart_inventory(args.run_start,args.dt,args.nday,args.workdir,args.paramfile,args.hot_freq,args.expected)
141205

142206

143207
if __name__ == "__main__":

schimpy/param.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def get_run_start(self):
4646
def get_interval(self,name):
4747
dt = self['dt']
4848
sec=self[name]*dt
49-
freq = pd.Timedelta(sec,unit='S')
49+
freq = pd.Timedelta(sec,unit='s')
5050

5151
return pd.tseries.frequencies.to_offset(freq)
5252

0 commit comments

Comments
 (0)