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 #632

Merged
merged 13 commits into from
Mar 14, 2024
1 change: 1 addition & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Released on xx/xx/xxxx.
- 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 ``activate`` control inputs to all test case documentation and update ``get_html_IO.py`` to print one file with all inputs, outputs, and forecasts. This is for [#555](https://github.com/ibpsa/project1-boptest/issues/555).
- Add storing of scenario result trajectories, kpis, and test information to simulation directory within test case docker container. This is for [#626](https://github.com/ibpsa/project1-boptest/issues/626).


## BOPTEST v0.5.0
Expand Down
83 changes: 64 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,17 @@ 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,
}
test_results.update(api_parameters)
payload = {"results":[test_results]}
dash_url = "%s/api/results" % dash_server
# Post to dashboard
if not unit_test:
Expand Down Expand Up @@ -1327,6 +1320,58 @@ def _get_full_current_state(self):

return z

def _get_test_results(self):
'''Collect test results and information into a dictionary.

Returns
-------
results: dict
Dictionary of test specific results and information.

'''

results = {
"dateRun": str(datetime.now(tz=pytz.UTC)),
"boptestVersion": self.version,
"controlStep": str(self.get_step()[2]),
"forecastParameters":{},
"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 as json and csv.

When run 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
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 so 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 with time as index
results_df = pd.DataFrame.from_dict(results)
results_df.index = results_df['time']
# store results csv
results_df.to_csv(file_name + ".csv")

def to_camel_case(self, snake_str):
components = snake_str.split('_')
# We capitalize the first letter of each component except the first one
Expand Down