Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 49 additions & 47 deletions constrain/checklib.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,26 +285,27 @@ def day_plot_aio(self, plt_pts, fig_size):
plotday_filtered = plotday[plotday != "Untested"]

# flag
ax1 = plt.subplot(2, 1, 1)
sns.scatterplot(x=plotday_filtered.index, y=plotday_filtered)
plt.xlim([plotday.index[0], plotday.index[-1]])
plt.ylim([-0.2, 1.2])
plt.title(f"Example day Pass / Fail flag - {self.__class__.__name__}")

# datapoints
ax2 = plt.subplot(2, 1, 2)
plotdaydf[plt_pts].plot(ax=ax2)
pt_nan = plotdaydf.isnull().any().to_dict()
for i, line in enumerate(ax2.get_lines()):
line_label = line.get_label()
if pt_nan[line_label]:
line.set_marker(".")
ax2.ticklabel_format(useOffset=False, axis="y")

plt.title(f"Example day data points plot - {self.__class__.__name__}")
plt.tight_layout()
plt.savefig(f"{self.results_folder}/Day_plot_aio.png")
print()
if plotday_filtered.size != 0:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leijerry888 The reason why I added this condition is to prevent an error when the size of the plotday_filtered is 0,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the discussion, we decided not to make updates for plotting in this PR (Interactive plot PR will handle the issue).

ax1 = plt.subplot(2, 1, 1)
sns.scatterplot(x=plotday_filtered.index, y=plotday_filtered)
plt.xlim([plotday.index[0], plotday.index[-1]])
plt.ylim([-0.2, 1.2])
plt.title(f"Example day Pass / Fail flag - {self.__class__.__name__}")

# datapoints
ax2 = plt.subplot(2, 1, 2)
plotdaydf[plt_pts].plot(ax=ax2)
pt_nan = plotdaydf.isnull().any().to_dict()
for i, line in enumerate(ax2.get_lines()):
line_label = line.get_label()
if pt_nan[line_label]:
line.set_marker(".")
ax2.ticklabel_format(useOffset=False, axis="y")

plt.title(f"Example day data points plot - {self.__class__.__name__}")
plt.tight_layout()
plt.savefig(f"{self.results_folder}/Day_plot_aio.png")
print()

def day_plot_obo(self, plt_pts, fig_size):
"""One by one plot of all samples"""
Expand All @@ -314,33 +315,34 @@ def day_plot_obo(self, plt_pts, fig_size):
plotday, plotdaydf = self.calculate_plot_day()
plotday_filtered = plotday[plotday != "Untested"]
# flag
ax1 = plt.subplot(num_plots, 1, 1)
sns.scatterplot(x=plotday_filtered.index, y=plotday_filtered)
plt.xlim([plotday.index[0], plotday.index[-1]])
plt.ylim([-0.2, 1.2])
plt.title(f"Example day Pass / Fail flag plot - {self.__class__.__name__}")

# datapoints
pt_nan = plotdaydf.isnull().any().to_dict()
i = 2
for pt in plt_pts:
try:
axx = plt.subplot(num_plots, 1, i)
if pt_nan[pt]:
plotdaydf[pt].plot(ax=axx, marker=".")
else:
# check if values in the series are boolean
if self.df[pt].apply(lambda x: isinstance(x, bool)).all():
self.df[pt] = self.df[pt].astype(int)
plotdaydf[pt].plot(ax=axx)
plt.title(f"Example day - {pt} - {self.__class__.__name__}")
i += 1
axx.ticklabel_format(useOffset=False, axis="y")
except:
print(f"{pt} cannot be plotted by itself, ignored in the plot.")
plt.tight_layout()
plt.savefig(f"{self.results_folder}/Day_plot_obo.png")
print()
if plotday_filtered.size != 0:
ax1 = plt.subplot(num_plots, 1, 1)
sns.scatterplot(x=plotday_filtered.index, y=plotday_filtered)
plt.xlim([plotday.index[0], plotday.index[-1]])
plt.ylim([-0.2, 1.2])
plt.title(f"Example day Pass / Fail flag plot - {self.__class__.__name__}")

# datapoints
pt_nan = plotdaydf.isnull().any().to_dict()
i = 2
for pt in plt_pts:
try:
axx = plt.subplot(num_plots, 1, i)
if pt_nan[pt]:
plotdaydf[pt].plot(ax=axx, marker=".")
else:
# check if values in the series are boolean
if self.df[pt].apply(lambda x: isinstance(x, bool)).all():
self.df[pt] = self.df[pt].astype(int)
plotdaydf[pt].plot(ax=axx)
plt.title(f"Example day - {pt} - {self.__class__.__name__}")
i += 1
axx.ticklabel_format(useOffset=False, axis="y")
except:
print(f"{pt} cannot be plotted by itself, ignored in the plot.")
plt.tight_layout()
plt.savefig(f"{self.results_folder}/Day_plot_obo.png")
print()

def daterange(self, start_date, end_date):
for n in range(int((end_date - start_date).days)):
Expand Down
14 changes: 7 additions & 7 deletions constrain/library/vav_turndown_during_reheat.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

"""

import logging

from constrain.checklib import RuleCheckBase


Expand All @@ -44,13 +46,11 @@ class VAVTurndownDuringReheat(RuleCheckBase):
]

def verify(self):
# Make sure every value in `V_dot_VAV_max` is greater than 0
assert (
self.df["V_dot_VAV_max"] > 0
).all(), "Not all `V_dot_VAV_max` values are greater than 0"

# Check if the `reheat_coil_flag` column has only False values
if (self.df["reheat_coil_flag"] == False).all():
# Check if the `reheat_coil_flag` column has only True/False value
if self.df["reheat_coil_flag"].nunique() == 1:
Comment thread
leijerry888 marked this conversation as resolved.
self.df["result"] = "Untested"
elif (self.df["V_dot_VAV_max"] == 0).any():
logging.error("Any `V_dot_VAV_max` value shouldn't be zero.")
Comment thread
leijerry888 marked this conversation as resolved.
self.df["result"] = "Untested"
else:
self.df["V_dot_VAV_ratio"] = self.df["V_dot_VAV"] / self.df["V_dot_VAV_max"]
Expand Down
2 changes: 1 addition & 1 deletion schema/library.json
Original file line number Diff line number Diff line change
Expand Up @@ -1601,7 +1601,7 @@
"description_verification_type": "procedure-based",
"assertions_type": "pass",
"description_assertions": [
"if (reheat_coil_flag == False).all():",
"if reheat_coil_flag.nunique() == 1:",
" Untested",
"else: ",
" V_dot_VAV_ratio = V_dot_VAV/V_dot_VAV_max",
Expand Down
76 changes: 75 additions & 1 deletion tests/test_vav_turndown_during_reheat.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def test_vav_turndown_during_reheat_fail(self):
binary_result = verification_obj.check_bool()
self.assertFalse(binary_result)

def test_vav_turndown_during_reheat_untested(self):
def test_vav_turndown_during_reheat_no_reheat_untested(self):
points = [
"reheat_coil_flag",
"V_dot_VAV",
Expand Down Expand Up @@ -127,3 +127,77 @@ def test_vav_turndown_during_reheat_untested(self):

self.assertEqual(results, expected_results)
self.assertEqual(verification_obj.check_bool(), "Untested")

def test_vav_turndown_during_reheat_all_reheat_untested(self):
points = [
"reheat_coil_flag",
"V_dot_VAV",
"V_dot_VAV_max",
]

timestamp = [
datetime(2024, 8, 1, 12, 0, 0),
datetime(2024, 8, 1, 13, 0, 0),
datetime(2024, 8, 1, 14, 0, 0),
datetime(2024, 8, 1, 15, 0, 0),
]

data = [
[True, 350, 620],
[True, 370, 620],
[True, 360, 620],
[True, 380, 620],
]

df = pd.DataFrame(data, columns=points, index=timestamp)

verification_obj = run_test_verification_with_data(
"VAVTurndownDuringReheat", df
)
results = list(verification_obj.result)
expected_results = [
"Untested",
"Untested",
"Untested",
"Untested",
]

self.assertEqual(results, expected_results)
self.assertEqual(verification_obj.check_bool(), "Untested")

def test_vav_turndown_during_reheat_zero_V_dot_VAV_max_untested(self):
points = [
"reheat_coil_flag",
"V_dot_VAV",
"V_dot_VAV_max",
]

timestamp = [
datetime(2024, 8, 1, 12, 0, 0),
datetime(2024, 8, 1, 13, 0, 0),
datetime(2024, 8, 1, 14, 0, 0),
datetime(2024, 8, 1, 15, 0, 0),
]

data = [
[True, 350, 0],
[True, 370, 0],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like this is the only difference from the previous test. Should the error log being asserted in the test?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

One thing I don't understand is that when I added the following code at the end of the unit test (line 284), the logobs is empty, which I don't understand. I'll keep this PR for now to take more time to find the reason. This shouldn't impact the testing.

with self.assertLogs() as logobs:
    self.assertEqual(
        "ERROR:root:Any `V_dot_VAV_max` value shouldn't be zero.",
        logobs.output[0],
    )

[True, 360, 620],
[True, 380, 620],
]

df = pd.DataFrame(data, columns=points, index=timestamp)

verification_obj = run_test_verification_with_data(
"VAVTurndownDuringReheat", df
)
results = list(verification_obj.result)
expected_results = [
"Untested",
"Untested",
"Untested",
"Untested",
]

self.assertEqual(results, expected_results)
self.assertEqual(verification_obj.check_bool(), "Untested")