|
@@ -6,38 +6,143 @@ import datetime as dt
|
6
|
6
|
import pickle
|
7
|
7
|
from pymodels import thirtyoffset, predweather, harmonic
|
8
|
8
|
from pprint import pprint
|
|
9
|
+from util import datevalid
|
|
10
|
+from signal import signal, SIGPIPE, SIG_DFL
|
|
11
|
+
|
|
12
|
+def preddemand(model, weather, harmonics):
|
|
13
|
+ harmstart = thirtyoffset(weather.index.min())
|
|
14
|
+ utv = weather.index
|
|
15
|
+ harmlen = len(utv)
|
|
16
|
+
|
|
17
|
+ yharm = harmonic(harmlen, period=365.25 * 48, start=harmstart,
|
|
18
|
+ harmonics=harmonics[0], prefix="y")
|
|
19
|
+ yharm.index = utv
|
|
20
|
+
|
|
21
|
+ wharm = harmonic(harmlen, period=7 * 48, start=harmstart,
|
|
22
|
+ harmonics=harmonics[1], prefix="w")
|
|
23
|
+ wharm.index = utv
|
|
24
|
+
|
|
25
|
+ dharm = harmonic(harmlen, period=48, start=harmstart,
|
|
26
|
+ harmonics=harmonics[2], prefix="d")
|
|
27
|
+ dharm.index = utv
|
|
28
|
+
|
|
29
|
+ df = p.concat([yharm, wharm, dharm, weather], axis = 1)
|
|
30
|
+ return model.predict(df)
|
9
|
31
|
|
10
|
32
|
def main():
|
11
|
33
|
parser = ArgumentParser(description=
|
12
|
34
|
'Predict from harmonic model of cluster')
|
13
|
35
|
parser.add_argument("-m", "--model-file", dest="model_file",
|
14
|
36
|
help="filename for models",
|
15
|
|
- default="../models/testmod.pkl",
|
|
37
|
+ required = True,
|
|
38
|
+ type=FileType('rb'))
|
|
39
|
+ parser.add_argument("-w", "--weather", dest="weather_file",
|
|
40
|
+ help="input weather pickle path",
|
|
41
|
+ required=False,
|
16
|
42
|
type=FileType('rb'))
|
17
|
|
- # parser.add_argument("-w", "--weather", dest="weather",
|
18
|
|
- # help="input weather pickle path",
|
19
|
|
- # metavar="PATH", required=True,
|
20
|
|
- # type=FileType('rb'))
|
21
|
|
- parser.add_argument("--weather-harmonics", dest="weather_harmonics",
|
22
|
|
- help="number of harmonics for weather; default: 2",
|
23
|
|
- type=int, default=2, metavar="NUM")
|
24
|
|
- parser.add_argument("--icp-harmonics", dest="icp_harmonics", nargs=3,
|
25
|
|
- help="harmonics for icp fitting, default 2 3 3",
|
26
|
|
- default=[2, 3, 3], type=int,
|
27
|
|
- metavar="NUM")
|
|
43
|
+ parser.add_argument("-o", "--output", dest="output_file",
|
|
44
|
+ help="file to save result",
|
|
45
|
+ required=True, type=FileType('w'))
|
|
46
|
+ parser.add_argument("-t", "--temperature", dest="temp",
|
|
47
|
+ help = "min and max temperature, if not using "
|
|
48
|
+ "weather dataset, e.g. 2.0 10.5",
|
|
49
|
+ required=False,
|
|
50
|
+ type=float, nargs=2)
|
|
51
|
+ parser.add_argument("-s", "--start-date",
|
|
52
|
+ dest = "startdate",
|
|
53
|
+ help = "start date for prediction; format: YYYY-MM-DD; default: 2018-01-01",
|
|
54
|
+ metavar="START_DATE",
|
|
55
|
+ required = True,
|
|
56
|
+ type = datevalid)
|
|
57
|
+ parser.add_argument("-e", "--end-date",
|
|
58
|
+ dest = "enddate",
|
|
59
|
+ help = "end date for prediction; format: YYYY-MM-DD; default: 2018-02-01",
|
|
60
|
+ metavar="END_DATE",
|
|
61
|
+ required = True,
|
|
62
|
+ type = datevalid)
|
|
63
|
+ parser.add_argument("-c", "--cluster",
|
|
64
|
+ dest = "cluster",
|
|
65
|
+ help = "cluster to predict for",
|
|
66
|
+ type = int,
|
|
67
|
+ required = True)
|
|
68
|
+ parser.add_argument("--csv",
|
|
69
|
+ help="output as csv",
|
|
70
|
+ action="store_true")
|
28
|
71
|
args = parser.parse_args()
|
29
|
72
|
|
30
|
|
- print(args)
|
|
73
|
+ if args.temp is None and args.weather_file is None:
|
|
74
|
+ parser.error("Either the temperature range or a weather "
|
|
75
|
+ "dataset must be specified")
|
31
|
76
|
|
32
|
77
|
mods = pickle.load(args.model_file)
|
33
|
78
|
|
34
|
|
- pprint(mods)
|
|
79
|
+ if args.cluster not in mods["clusters"]:
|
|
80
|
+ parser.error(f"cluster ('{args.cluster}') not in model")
|
|
81
|
+
|
|
82
|
+ wdat = []
|
35
|
83
|
|
36
|
|
- print(mods["max_temp"].predict())
|
|
84
|
+ if args.weather_file is not None:
|
|
85
|
+ weather = p.read_pickle(args.weather_file)
|
|
86
|
+ if (args.startdate < weather['temp_timestamp'].min() or
|
|
87
|
+ args.enddate > weather['temp_timestamp'].max()):
|
|
88
|
+ parser.error("Start and or end date not in supplied weather dataset")
|
|
89
|
+
|
|
90
|
+ wantedtimes = p.date_range(args.startdate,
|
|
91
|
+ args.enddate, freq="30 min")
|
|
92
|
+ wantedtimes = p.Series(wantedtimes.round(freq="30 min"))
|
|
93
|
+ wanteddf = p.DataFrame(index=wantedtimes)
|
|
94
|
+ weather = wanteddf.join(weather.set_index(['temp_timestamp']),
|
|
95
|
+ how='left').drop('temp_date', axis=1)
|
|
96
|
+ weather.index.name = "read_time"
|
|
97
|
+ weather = weather.fillna(method='ffill', axis=0)
|
|
98
|
+
|
|
99
|
+ # Add rolling columns
|
|
100
|
+ weather['min_rolling'] = weather['tmin_c'].rolling("1D").min()
|
|
101
|
+ weather['max_rolling'] = weather['tmax_c'].rolling("1D").max()
|
|
102
|
+
|
|
103
|
+ wharmstart = thirtyoffset(weather.index.min())
|
|
104
|
+ wharm = harmonic(weather.shape[0], period=365.25 * 48, start=wharmstart,
|
|
105
|
+ harmonics=mods["weather_harmonics"])
|
|
106
|
+ wharm.index = wantedtimes
|
|
107
|
+ pred_max = weather['max_rolling'] - mods["max_temp"].predict(wharm)
|
|
108
|
+ pred_min = weather['min_rolling'] - mods["min_temp"].predict(wharm)
|
|
109
|
+ wdat = p.DataFrame({
|
|
110
|
+ "max_resid": pred_max,
|
|
111
|
+ "min_resid": pred_min
|
|
112
|
+ })
|
|
113
|
+
|
|
114
|
+ else:
|
|
115
|
+ mint = min(args.temp)
|
|
116
|
+ maxt = max(args.temp)
|
|
117
|
+ pred_max = maxt - predweather(mods["max_temp"],
|
|
118
|
+ args.startdate,
|
|
119
|
+ args.enddate,
|
|
120
|
+ harmonics = mods["weather_harmonics"])
|
|
121
|
+ pred_min = mint - predweather(mods["min_temp"],
|
|
122
|
+ args.startdate,
|
|
123
|
+ args.enddate,
|
|
124
|
+ harmonics = mods["weather_harmonics"])
|
|
125
|
+ wdat = p.DataFrame({
|
|
126
|
+ "max_resid": pred_max,
|
|
127
|
+ "min_resid": pred_min
|
|
128
|
+ })
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+ dpred = p.DataFrame(
|
|
132
|
+ {
|
|
133
|
+ "predicted": preddemand(mods["icp"][args.cluster], wdat, mods["icp_harmonics"])
|
|
134
|
+ })
|
|
135
|
+
|
|
136
|
+ if args.csv:
|
|
137
|
+ signal(SIGPIPE, SIG_DFL) # Prevent broken pipe errors when piping to less or head
|
|
138
|
+ dpred.to_csv(args.output_file)
|
|
139
|
+ else:
|
|
140
|
+ dpred.to_pickle(args.output_file)
|
37
|
141
|
|
38
|
|
- print(predweather(mods["max_temp"], "2019-01-01", "2019-02-01", harmonics = mods["weather_harmonics"]))
|
39
|
142
|
|
40
|
143
|
args.model_file.close()
|
|
144
|
+ if args.weather_file is not None:
|
|
145
|
+ args.weather_file.close()
|
41
|
146
|
|
42
|
147
|
|
43
|
148
|
if __name__ == "__main__":
|