Source code for emodpy_hiv.plotting.channel_report
import pandas as pd
import numpy as np
import json
from datetime import datetime
[docs]class ChannelReport:
"""
A class that can be used to convert an EMOD channel report/dictionary
(i.e. InsetChart, DemographicsSummary, PropertyReport, etc) into a
dataframe. A static method is provided to go the other way.
"""
def __init__(self, df: pd.DataFrame = None):
self.json_data = self.convert_df_to_channel_report(df)
[docs] def create_empty_channel_report(self):
"""
Create the dictionary that has the right format for a channel report.
It would be really nice if we could include Start_Time & Simulation_Timestep
from the input files, but these are hardcoded for now.
Args:
Returns:
A dictionary that has the header and an emtpy 'Channels' entry
"""
report = {}
report["Header"] = {}
report["Header"]["DateTime" ] = datetime.today().strftime('%Y-%m-%d') # noqa: E202
report["Header"]["DTK_Version" ] = "unknown" # noqa: E202
report["Header"]["Report_Type" ] = "InsetChart" # noqa: E202
report["Header"]["Report_Version" ] = "3.2" # noqa: E202
report["Header"]["Start_Time" ] = 0 # noqa: E202
report["Header"]["Simulation_Timestep"] = 365 / 12
report["Header"]["Timesteps" ] = 0 # noqa: E202
report["Header"]["Channels" ] = 0 # noqa: E202
report["Channels"] = {}
return report
[docs] def add_channel(self, report, channel_name, values):
"""
Add the values of the channel to the report
Args:
report: a channel report formatted JSON dictionary
channel_name: the name of the channel to Add
values: a list of integers or floats for that channel
Returns:
The 'report' object is modified
"""
report["Channels"][channel_name] = {}
report["Channels"][channel_name]["Units"] = ""
report["Channels"][channel_name]["Data"] = values
report["Header"]["Channels"] += 1
return
[docs] def convert_df_to_channel_report(self, df):
"""
Convert the dataframe to a dictionary of the channel report format.
Args:
df:
a dataframe where the columns are the channels and there
is a row for each time step
Returns:
A dictionary that contains the data from the dataframe and can be
converted to a JSON channel report
"""
report = self.create_empty_channel_report()
for name, values in df.items():
if name != "Time":
self.add_channel(report, name, values.tolist())
return report
[docs] def save(self, filename):
"""
Save this report data to a file.
Args:
filename: The name of the file (including path) to contain the data/JSON.
Returns:
A file should be saved
"""
with open(filename, 'w') as file:
json.dump(self.json_data, file, indent=4)
return
[docs] @staticmethod
def convert_to_df(channel_report_dict, channels_to_extract=None):
"""
Convert the input dictionary into a dataframe
Args:
channel_report_dict:
The name of the file (including path) to contain the data/JSON.
channels_to_extract:
A list of strings that are the channel names to extract from the
JSON and put into the dataframe
Returns:
A dataframe where the columns are the channels of the report.
An extra 'Time' column is added to the dataframe
"""
dt = channel_report_dict["Header"]["Simulation_Timestep"] # noqa: E221
start_time = channel_report_dict["Header"]["Start_Time"] # noqa: E221
num_time_steps = channel_report_dict["Header"]["Timesteps"]
result_dict = {"Time": start_time + (np.arange(num_time_steps) * dt)}
if channels_to_extract is None:
channels_to_extract = channel_report_dict["Channels"].keys()
for channel_name in channels_to_extract:
result_dict[channel_name] = channel_report_dict["Channels"][channel_name]["Data"]
df = pd.DataFrame(result_dict)
return df