Skip to content

Commit 3c75678

Browse files
Add Python3 port and example plotting script
Add a Python 3 port of the CREST model as pyCREST_Py_3.py and an example script Example_Py_3.py that generates profiles and provides helper plotting functions (plot_powerfile, plot_occupancy_file, plot_app_profiles). Rename the original pyCREST.py to pyCREST_Py_2.py to preserve the prior copy. The example uses pyCREST_Py_3.create_profiles to produce Pfile_/Qfile_/Occfile_/AppProfiles files and attempts to display or save plots (matplotlib + numpy).
1 parent 584ebf6 commit 3c75678

File tree

3 files changed

+851
-0
lines changed

3 files changed

+851
-0
lines changed

Example_Py_3.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import pyCREST_Py_3 as cr
2+
import numpy as np
3+
import matplotlib.pyplot as plt
4+
5+
def plot_powerfile(filename):
6+
"""Read a power output file created by create_profiles and plot it.
7+
8+
The files generated by :func:`create_profiles` are named ``Pfile_<idstring>.dat``
9+
where each row corresponds to one dwelling and contains 1440 minute values.
10+
This helper loads the file and displays the first profile as a simple line plot.
11+
"""
12+
# load the data (assumes integer or float values separated by whitespace)
13+
data = np.loadtxt(filename)
14+
if data.ndim == 1:
15+
profile = data
16+
else:
17+
profile = data[0]
18+
19+
times = np.arange(len(profile)) / 60.0 # hours
20+
plt.figure()
21+
plt.plot(times, profile)
22+
plt.xlabel('Time (hours)')
23+
plt.ylabel('Active power demand')
24+
plt.title(f'Profile from {filename}')
25+
plt.grid(True)
26+
plt.show()
27+
28+
29+
30+
def plot_occupancy_file(filename):
31+
"""Plot an occupancy profile generated by :func:`create_profiles`.
32+
33+
The occupancy files are created as ``Occfile_<idstring>.dat`` and contain
34+
144 ten-minute values for each dwelling representing the occupancy state.
35+
"""
36+
data = np.loadtxt(filename)
37+
# there may be a single row (1D) or multiple rows; use first profile
38+
if data.ndim == 1:
39+
profile = data
40+
else:
41+
profile = data[0]
42+
times = np.arange(len(profile)) * 10.0 / 60.0 # hours
43+
plt.figure()
44+
plt.plot(times, profile)
45+
plt.xlabel('Time (hours)')
46+
plt.ylabel('Occupancy state')
47+
plt.title(f'Occupancy from {filename}')
48+
plt.grid(True)
49+
plt.show()
50+
51+
52+
def plot_app_profiles(filename, appliance=None):
53+
"""Plot one appliance's power profile from an AppProfiles file.
54+
55+
Each line of ``AppProfiles<idstring>.dat`` normally contains:
56+
``<index> <P/Q> <name> <1440 values>``. The parser looks for the named
57+
appliance token and then interprets subsequent tokens as floats. If no
58+
*appliance* is specified, the first numeric profile encountered is used.
59+
"""
60+
lines = open(filename).read().strip().splitlines()
61+
selected = None
62+
for line in lines:
63+
tokens = line.split()
64+
if not tokens:
65+
continue
66+
# find the token that equals the requested appliance (or just the first name)
67+
if appliance is not None and appliance in tokens:
68+
idx = tokens.index(appliance)
69+
elif appliance is None and len(tokens) >= 3:
70+
# assume third token is name
71+
idx = 2
72+
else:
73+
continue
74+
# collect floats after the name token
75+
vals = []
76+
for tok in tokens[idx+1:]:
77+
try:
78+
vals.append(float(tok))
79+
except ValueError:
80+
# stop at first non‑numeric (there may not be any)
81+
break
82+
if vals:
83+
name = tokens[idx]
84+
selected = (name, np.array(vals))
85+
break
86+
if selected is None:
87+
print(f'no appliance profile found in {filename}')
88+
return
89+
name, profile = selected
90+
times = np.arange(len(profile)) / 60.0 # hours
91+
plt.figure()
92+
plt.plot(times, profile)
93+
plt.xlabel('Time (hours)')
94+
plt.ylabel(f'{name} power')
95+
plt.title(f'{name} profile from {filename}')
96+
plt.grid(True)
97+
plt.show()
98+
99+
100+
if __name__ == "__main__":
101+
# generate profiles and plot the active power demand
102+
n=1
103+
month=1
104+
daytype="weekday"
105+
cr.create_profiles(n=n,daytype=daytype,month=month)
106+
107+
# construct filename matching create_profiles output and show it
108+
idstring = f"{n}x_month-{month}_daytype-{daytype}"
109+
power_filename = f"Pfile_{idstring}.dat"
110+
print(f"generated {power_filename}")
111+
# display the plot automatically (will open a window or save a PNG)
112+
try:
113+
plot_powerfile(power_filename)
114+
except Exception as e:
115+
print(f"plot failed: {e}, saving figure instead")
116+
# regenerate profile data and save to file
117+
import matplotlib.pyplot as _plt
118+
data = np.loadtxt(power_filename)
119+
times = np.arange(len(data)) / 60.0
120+
_plt.figure()
121+
_plt.plot(times, data if data.ndim==1 else data[0])
122+
_plt.savefig(power_filename.replace('.dat', '.png'))
123+
print(f"saved plot to {power_filename.replace('.dat', '.png')}")
124+
125+
# also plot occupancy and one appliance profile
126+
occ_filename = f"Occfile_{idstring}.dat"
127+
try:
128+
plot_occupancy_file(occ_filename)
129+
except Exception as e:
130+
print(f"occupancy plot failed: {e}")
131+
app_filename = f"AppProfiles{idstring}.dat"
132+
try:
133+
plot_app_profiles(app_filename, appliance='LIGHTING')
134+
except Exception as e:
135+
print(f"appliance plot failed: {e}")
136+
File renamed without changes.

0 commit comments

Comments
 (0)