Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,34 @@
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also export our Monte Carlo results into .csv and .json files using the method `MonteCarlo.export_results()`.\n",
"\n",
"Choose a name for the output file and select a format to output."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Results saved to monte_carlo_analysis_outputs/monte_carlo_csv_output_example as .csv file\n",
"Results saved to monte_carlo_analysis_outputs/monte_carlo_json_output_example as .json file\n"
]
}
],
"source": [
"test_dispersion.export_results(\"monte_carlo_analysis_outputs/monte_carlo_csv_output_example\", \"csv\")\n",
"test_dispersion.export_results(\"monte_carlo_analysis_outputs/monte_carlo_json_output_example\", \"json\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
Expand Down
36 changes: 36 additions & 0 deletions rocketpy/simulation/monte_carlo.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"""

import json
import csv
import os
import traceback
import warnings
Expand Down Expand Up @@ -588,6 +589,41 @@ def __evaluate_flight_outputs(self, flight, sim_idx):
json.dumps(outputs_dict, cls=RocketPyEncoder, **self._export_config) + "\n"
)

def export_results(self, output_filename, output_format):
"""Converts the default Monte Carlo .txt output to .cvs or .json file
depending on the user's choice

Parameters
----------
output_filename : str
Name of the file in which the converted data will be saved
output_format : str
Format of the output file

Returns
-------
None
"""
txt_data = []
with open(f"{self.filename}.outputs.txt", "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
data = json.loads(line)
txt_data.append(data)

output_format = output_format.strip().lower()
if output_format == "json":
with open(f"{output_filename}.json", "w", encoding="utf-8") as f:
json.dump(txt_data, f, indent=4)
_SimMonitor.reprint(f"Results saved to {Path(output_filename)} as .json file")
elif output_format == "csv":
output_csv_header = txt_data[0].keys()
with open(f"{output_filename}.csv", "w", newline= "") as f:
output_writer = csv.DictWriter(f, fieldnames=output_csv_header)
output_writer.writeheader()
output_writer.writerows(txt_data)
_SimMonitor.reprint(f"Results saved to {Path(output_filename)} as .csv file")

Comment on lines +592 to +626
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also I think having this be two different functions export_results_to_csv and export_results_to_json would be cleaner

def __terminate_simulation(self):
"""
Terminates the simulation, closes the files and prints the results.
Expand Down
46 changes: 46 additions & 0 deletions tests/unit/simulation/test_monte_carlo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import matplotlib as plt
import numpy as np
import pytest
import json
import csv
import os

from rocketpy.simulation import MonteCarlo

Expand Down Expand Up @@ -185,3 +188,46 @@ def test_estimate_confidence_interval_raises_type_error_for_invalid_statistic():

with pytest.raises(TypeError):
mc.estimate_confidence_interval("apogee", statistic="not_a_function")


def test_export_results_creates_csv_and_json_files(monte_carlo_calisto, tmp_path):
"""Checks that the export_results create .csv and .json files

Parameters
----------
monte_carlo_calisto : MonteCarlo
Fixture that has the .txt files necessary for the export_results
"""
try:
mc = monte_carlo_calisto
mc.filename = tmp_path / "mock_output"
mock_data = {"apogee": 100, "max_velocity": 255}
with open(tmp_path / "mock_output.outputs.txt", "w") as f:
f.write(json.dumps(mock_data) + "\n")

mc.export_results(tmp_path / "mock_outputs_in_csv", "csv")
expected_file_in_csv = tmp_path / f"{"mock_outputs_in_csv"}.csv"
assert expected_file_in_csv.exists()
with open(expected_file_in_csv, "r") as f:
reader = csv.DictReader(f)
rows = list(reader)
assert len(rows) == 1
assert rows[0]["apogee"] == "100"
assert rows[0]["max_velocity"] == "255"

mc.export_results(tmp_path / "mock_output_in_json", "json")
expected_file_in_json = tmp_path / "mock_output_in_json.json"
assert expected_file_in_json.exists()
with open(expected_file_in_json, "r") as f:
data = json.load(f)
assert len(data) == 1
assert data[0]["apogee"] == 100
assert data[0]["max_velocity"] == 255
finally:
for filepath in [
"monte_carlo_test.errors.txt",
"monte_carlo_test.inputs.txt",
"monte_carlo_test.outputs.txt",
]:
if os.path.exists(filepath):
os.remove(filepath)