RUFAS.graph_generator module#

class RUFAS.graph_generator.GraphGenerator(metadata_prefix: str = '', time=None)#

Bases: object

Graph Generator is used to generate graphs from the simulation results. NOTE: This class is not multi-thread safe!!!

Attributes#

metadata_prefixstr

A string to prefix the metadata of the graph.

timeRufasTime

A RufasTime object used to track the simulation time

__init__(metadata_prefix: str = '', time=None) None#
generate_graph(filtered_pool: dict[str, dict[str, list[Any]]], graph_details: dict[str, str | list[str]], filter_file_name: str, graphics_dir: Path, produce_graphics: bool) list[dict[str, str | dict[str, str]]]#

Generate a graph based on filtered data and graph details.

Parameters#

filtered_pooldict[str, dict[str, list[Any]]]

The result pool after filtering with the provided RegEx filters.

graph_details: dict[str, str]

A dictionary containing details/metadata about the graph.

save_path: Path

The base folder path to save the output.

filter_file_name: str

The name of the filter file.

graphics_dirPath

The directory for saving graphics.

produce_graphics: bool

Flag for whether or not the user wants to produce graphs at after the simulation.

Returns#

log_poollist[dict[str, str | dict[str, str]]] | list[dict[str, str | dict[str, str]]]

A list of log, warning, and error dictionaries containing all the components needed to log the information to the appropriate pool.

Raises#

Exception

Generic exception raised by utility functions.

_set_graph_legend(graph_details: dict[str, str | list[str]], prepared_data: dict[str, list[Any]]) dict[str, str | list[str]]#

Sets the graph legend if there is no legend present in the graph details.

Parameters#

graph_detailsdict[str, str]

A dictionary containing details/metadata about the graph.

prepared_data: dict[str, list[Any]]

The data to be graphed that’s been prepared for graphing.

Returns#

dict[str, str]

A dictionary containing details/metadata about the graph with the legend field populated.

_add_var_units(filtered_pool: dict[str, dict[str, list[Any]]], graph_title: str | list[str]) tuple[dict[str, dict[str, list[Any]]], list[dict[str, str | dict[str, str]]]]#

Adds variable units to variable name for graphing.

Parameters#

filtered_pooldict[str, list[Any]]

The data to be graphed.

Returns#

list[dict[str, list[Any]], list[dict[str, str | dict[str, str]]]]

The updated data with units added and logs if info_maps aren’t found to get units.

_generate_legend_keys(combined_var_name: str, omit_legend_prefix: str | list[str] | bool = False, omit_legend_suffix: str | list[str] | bool = False) str#

Strip out the prefix and suffix (if exists) in the combined variable name, and return the variable name.

Parameters#

combined_var_name: str

The combined variable name to be processed.

Returns#

str

The stripped variable name.

Notes#

This function identifies prefix and suffix according to the following logic:
prefix:
All combined variable names are guaranteed to have a prefix of the following types:
  • a custom defined prefix (e.g. Accumulated_ManureTreatmentDailyOutput_Pen_0_CALF)

  • default-pattern prefix (class.method e.g. AnimalModuleReporter.report_pen_manure_properties)

  • special cases => variables from the RufasTime and Weather classes (e.g. RufasTime.day,

    Weather.rainfall)

For the special cases of variables from the RufasTime and Weather classes, they do not have any suffixes, resulting in len(combined_var_name_list) == 2. Therefore, we can just return the second element after splitting the combined variable name by “.”.

We distinguish whether the prefix is a custom defined prefix or following the default pattern by string parsing: The class name in the default pattern prefixes follow the camel case pattern, a way to separate the words in a phrase by making the first letter of each word capitalized and not using spaces e.g. CamelCase. While the custom defined prefixes follow the snake case pattern, where each word is separated by underscores. Therefore, by checking if combined_var_name_list[0] follows the camel case pattern (“([A-Z][a-z0-9]+)+”), we are able to find out if the variable is using the default pattern.

  • if len(combined_var_name_list) == 1 this check is here just for error proofing, this condition

is unlikely to appear.

suffix:

Currently, only the Crop and Soil module is utilizing the suffix feature while reporting variables. After some investigation, we found that all suffixes from the Crop and Soil module follows the pattern of field=’*’, for example:

  • FieldDataReporter.send_annual_variables.annual_runoff_ammonium_total.field=’field’

  • FieldDataReporter.send_annual_variables.annual_carbon_CO2_lost.field=’field’,layer=’2’

Therefore, by checking if hte last element in combined_var_name_list contains “=”, we are able to check if the variable name has suffix.

_log_non_numerical_data(filtered_pool: dict[str, dict[str, list[Any]]], graph_details: dict[str, str | list[str]]) list[dict[str, str | dict[str, str]]]#

Identifies and logs entries in a filtered data pool that contain non-numeric data which cannot be used for plotting in a graph.

Parameters#

filtered_pooldict[str, pool_element_type]

The filtered pool of variables that the user wants to graph.

graph_details: dict[str, str]

A dictionary containing details/metadata about the graph.

Returns#

list[dict[str, str | dict[str, str]]]

A list of logs, warnings, and errors to be reported to OutputManager.

_draw_graph(graph_type: str, data: dict[str, list[int | float]], selected_variables: list[str], ax: Axes, mask_values: bool = False, use_calendar_dates: bool = False, date_format: str | None = None, slice_start: int | None = None, slice_end: int | None = None) None#

Draw the graph based on the provided graph type and data.

Parameters#

graph_typestr

The type of graph to draw.

datadict[str, list[int | float]]

The data to use for plotting.

selected_variableslist[str]

The variables selected to be plotted.

mask_valuesbool, default False

Whether data that will be plotted with non-tuple based functions should be masked to remove None or NaN values.

axAxes

The matplotlib Axes object to plot the graph on.

use_calendar_datesbool, default False

Whether to use calendar dates on the x-axis.

date_formatstr, default None

The user-requested format to use for the date on the x-axis.

slice_startint, default None

The starting index of the data to plot.

slice_endint, default None

The ending index of the data to plot.

Raises#

ValueError

if graph_type is not found in MATPLOTLIB_PLOT_FUNCTIONS.

_mask_values(values: list[Any]) tuple[ndarray[tuple[int, ...], dtype[Any]], ndarray[tuple[int, ...], dtype[float32]]]#

Masks values to remove None and NaN values.

Parameters#

valueslist[Any]

list of data to be masked.

Returns#

tuple[NDArray[Any], NDArray[np.float32]]

list of NumPy arrays, the first containing the indices of the masked data and the second containing the actual masked data.

_customize_graph(fig: Figure, customization_details: dict[str, Any]) None#

Apply customizations to the graph.

Parameters#

figFigure

The matplotlib Figure object to customize.

customization_detailsdict[str, Any]

A dictionary of customization details.

_save_graph(graph_details: dict[str, str | list[str]], filter_file_name: str, graphics_dir: Path) Path#

Save the generated graph to a file.

Parameters#

graph_detailsdict[str, str]

A dictionary containing details/metadata about the graph.

filter_file_namestr

The name of the filter file.

save_pathPath

The base folder path to save the output.

graphics_dirPath

The directory for saving graphics.

Returns#

str

The path to the saved graph.

Raises#

Exception

Generic exception raised if saving the graph fails.

_generate_graph_path(graph_details: dict[str, str], filter_file_name: str, graphics_dir: Path) Path#

Generate the full path for the output graph and create parent folders if necessary.

Parameters#

graph_detailsdict[str, str]

A dictionary containing details/metadata about the graph.

filter_file_namestr

The name of the filter file.

graphics_dirPath

The directory for saving graphics.

Returns#

Path

The full path to the output graph file.