Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue626 store results #629

Merged
merged 5 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Released on xx/xx/xxxx.
- Correct typo in documentation for ``multizone_office_simple_air``, cooling setback temperature changed from 12 to 30. This is for [#605](https://github.com/ibpsa/project1-boptest/issues/605).
- Modify unit tests for test case scenarios to only simulate two days after warmup instead of the whole two-week scenario. This is for [#576](https://github.com/ibpsa/project1-boptest/issues/576).
- Fix unit tests for possible false passes in certain test cases. This is for [#620](https://github.com/ibpsa/project1-boptest/issues/620).

- Add storing of scenario results to simulation directory. This is for [#626](https://github.com/ibpsa/project1-boptest/issues/626).

## BOPTEST v0.5.0

Expand Down
81 changes: 62 additions & 19 deletions testcase.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import os
import json
import array as a
import pandas as pd

class TestCase(object):
'''Class that implements the test case.
Expand Down Expand Up @@ -359,6 +360,8 @@ def advance(self, u):
# Check if scenario is over
if self.start_time >= self.end_time:
self.scenario_end = True
# store results
self.store_results()
# Log and return
logging.info(message)
return status, message, payload
Expand Down Expand Up @@ -1142,27 +1145,16 @@ def post_results_to_dashboard(self, api_key, tags, unit_test=False):
dash_server = os.environ['BOPTEST_DASHBOARD_SERVER']
# Create payload
uid = str(uuid.uuid4())
payload = {
"results": [
{
"uid": uid,
"dateRun": str(datetime.now(tz=pytz.UTC)),
"boptestVersion": self.version,
"isShared": True,
"controlStep": str(self.get_step()[2]),
"account": {
test_results = self._get_test_results()
api_parameters = {
"uid": uid,
"isShared": True,
"account": {
"apiKey": api_key
},
"forecastParameters":{},
"tags": tags,
"kpis": self.get_kpis()[2],
"scenario": self.add_forecast_uncertainty(self.keys_to_camel_case(self.get_scenario()[2])),
"buildingType": {
"uid": self.get_name()[2]['name']
}
}
]
},
"tags": tags,
}
payload = {"results":[{**test_results, **api_parameters}]}
dash_url = "%s/api/results" % dash_server
# Post to dashboard
if not unit_test:
Expand Down Expand Up @@ -1326,6 +1318,57 @@ def _get_full_current_state(self):
z.update(self.u)

return z

def _get_test_results(self):
'''Collect test results.

Returns
-------
results: dict
Dictionary of test specific results.
'''
results = {
"dateRun": str(datetime.now(tz=pytz.UTC)),
"boptestVersion": self.version,
"controlStep": str(self.get_step()[2]),
"forecastParameters": {}, # for future use to store used parameters?
"measurementParameters": {}, # for future use to store used parameters?
"kpis": self.get_kpis()[2],
"scenario": self.add_forecast_uncertainty(self.keys_to_camel_case(self.get_scenario()[2])),
"buildingType": {
"uid": self.get_name()[2]['name'],
}
}
return results

def store_results(self):
'''Stores results from scenario in working directory.
When ran with service, the result will be packed in the result tarball and
be retrieveable with the test_id


Returns
-------
None.

'''

file_name = "results"
# get results_json
Copy link
Collaborator

Choose a reason for hiding this comment

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

To reduce code duplication, I suggest abstracting the creation of a results.json structure in a separate function for all fields that are common with what is submitted to dashboard, defined here https://github.com/ibpsa/project1-boptest/blob/master/testcase.py#L1143. Then, post_results_to_dashboard and store_results can share use of that function to build an initial json and add additional fields as-needed (if any) for submission to dashboard or writing to file, respectively.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I proposed a solution. However, I had some trouble with submitting results to the dashboard, with both previous and updated solution, so I have not checked that it works properly.

Copy link
Collaborator

@dhblum dhblum Mar 11, 2024

Choose a reason for hiding this comment

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

@HWalnum I'll take a look, but looks like you got a couple results submitted for BESTEST Hydronic Heat Pump under the account "hwaln" on 3/8/2024 at https://dashboard.dev.boptest.net/.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @dhblum. I think those are from some extra tests I did with the service.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok actually I'm having some trouble submitting to the dashboard too.

Copy link
Collaborator

Choose a reason for hiding this comment

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

And Ok I see. I'm meeting with Kyle tomorrow morning for a few things and he can help work out what's going on.

results_json = self._get_test_results()

# store results_json
with open(file_name + ".json", "w") as outfile:
json.dump(results_json, outfile)

# get list of results, need to use output metadata because duplicate inputs are removed
result_list = self.input_names + list(self.outputs_metadata.keys())
# get results trajectories
results = self.get_results(result_list, self.initial_time, self.end_time)[2]
# convert to dataframe
results_df = pd.DataFrame.from_dict(results)
# store
results_df.to_csv(file_name + ".csv")

def to_camel_case(self, snake_str):
components = snake_str.split('_')
Expand Down