Source code for pytoughreact.plotting.plot_tough_routine

'''
MIT License

Copyright (c) [2022] [Temitope Ajayi]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

'''

import itertools
import math
import os
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from scipy.interpolate import griddata
from pytoughreact.utilities.t2_utilities import T2Utilities
from pytoughreact.results.result_tough_3 import ResultTough3
from pytoughreact.results.result_tough_react import ResultReact
from pytoughreact.results.simple_experiment_data import Experiment
import pytoughreact.constants.generalconstants as gc
import pytoughreact.constants.plotconstants as pc
import pytoughreact.constants.grid_constants as grc
import pandas as pd


[docs] class PlotTough(object):
[docs] def __init__(self, simulator_type, file_location, file_title, **kwargs): """ Class for processing multiple file results Parameters ----------- file_location : str specifies the location of the file on the system file_title : str gives the title of the file e.g 'kdd.conc' or 'OUTPUT.csv'. simulator_type: str can either be toughreact, tmvoc or tough3 **kwargs generation : str generation file location restart_files : str restart file location experiment : str experimental file location Returns -------- """ self.file_location = file_location os.chdir(self.file_location) self.filetitle = file_title self.simulatortype = simulator_type self.modifier = T2Utilities() self.generation = kwargs.get(gc.GENERATION) self.args = kwargs.get(gc.RESTART_FILES) self.expt = kwargs.get(gc.EXPERIMENT)
def _read_file(self): """ Read in the input files """ if (self.simulatortype.lower() == gc.TMVOC or self.simulatortype.lower() == gc.TOUGH3): file_reader = ResultTough3(self.simulatortype, self.file_location, self.filetitle, generation=self.generation) else: file_reader = ResultReact(self.simulatortype, self.file_location, self.filetitle) return file_reader def _plot_raw(self, param, grid_block_number, format_of_date, restart=False): """ Line Plots of a parameter in the results file as a function of time Parameters ----------- param : str The parameter to be plotted on the y-axis grid_block_number : int the grid block in which its parameter evolution is to be observed. format_of_date: str The format of the date; could be minute, hour, day or year restart: boolean If restart was performed in the simulation or not Returns -------- """ parameters = T2Utilities() if restart is True: time_year = self._get_restart_data_time(format_of_date) result_array = self._get_restart_data_element(param, grid_block_number) time_year, result_array = parameters.remove_repetiting(time_year, result_array) else: file_reader = self._read_file() time_year = file_reader.convert_times(format_of_date) if self.generation is True: result_array = file_reader.get_generation_data(param) else: result_array = file_reader.get_timeseries_data( param, grid_block_number) fig, axs = plt.subplots(1, 1) axs.plot(time_year, result_array, marker=pc.CARET_SYMBOL) if format_of_date.lower() == pc.YEAR: axs.set_xlabel(pc.X_LABEL_TIME_YEAR, fontsize=12) elif format_of_date.lower() == pc.DAY: axs.set_xlabel(pc.X_LABEL_TIME_DAY, fontsize=12) elif format_of_date.lower() == pc.HOUR: axs.set_xlabel(pc.X_LABEL_TIME_HOUR, fontsize=12) elif format_of_date.lower() == pc.MINUTE: axs.set_xlabel(pc.X_LABEL_TIME_MIN, fontsize=12) axs.set_ylabel(parameters.param_label_full(param.upper()), fontsize=12) axs.spines[pc.BOTTOM].set_linewidth(1.5) axs.spines[pc.LEFT].set_linewidth(1.5) axs.spines[pc.TOP].set_linewidth(0) axs.spines[pc.RIGHT].set_linewidth(0) plt.setp(axs.get_xticklabels(), fontsize=12) plt.setp(axs.get_yticklabels(), fontsize=12) plt.tight_layout() plt.show() if restart is True: fig.savefig(param + ' ' + pc.VERSUS + ' ' + pc.TIME + ' ' + pc.RESTART + pc.IMAGE_TYPE, bbox_inches=pc.TIGHT_BBOX, dpi=600) else: fig.savefig(param + ' ' + pc.VERSUS + ' ' + pc.TIME + pc.IMAGE_TYPE, bbox_inches=pc.TIGHT_BBOX, dpi=600)
[docs] def plot_param_with_time(self, param, grid_block_number, format_of_date): """ Line Plots of a parameter in the results file as a function of time Parameters ----------- param : str The parameter to be plotted on the y-axis grid_block_number : int the grid block in which its parameter evolution is to be observed. format_of_date: str The format of the date; could be minute, hour, day or year Returns -------- """ if self.expt: try: with plt.style.context(pc.MY_STYLE): self._plot_raw_with_expt(param, grid_block_number, format_of_date) except Exception: with plt.style.context(pc.CLASSIC): self._plot_raw_with_expt(param, grid_block_number, format_of_date) else: try: with plt.style.context(pc.MY_STYLE): self._plot_raw(param, grid_block_number, format_of_date) except Exception: with plt.style.context(pc.CLASSIC): self._plot_raw(param, grid_block_number, format_of_date)
def _get_restart_locations(self): """ Get Restart Locations """ restart_files = list() restart_files.append(self.file_location) restart_files = restart_files + self.args return restart_files def _get_restart_data_time(self, format_of_date): """ Get Restart Time Data Parameters ----------- format_of_date: str The format of the date; could be minute, hour, day or year Returns -------- restart_time : list restart time data in a list """ locations = self._get_restart_locations() restart_time = [] for i in range(0, len(locations)): if (self.simulatortype.lower() == gc.TMVOC or self.simulatortype.lower() == gc.TOUGH3): file_reader = ResultTough3(self.simulatortype, locations[i], self.filetitle) else: file_reader = ResultReact(self.simulatortype, locations[i], self.filetitle) if i == 0: time_year = file_reader.convert_times(format_of_date) restart_time.append(time_year) else: time_year = file_reader.convert_times(format_of_date) time_year = time_year[1:] restart_time.append(time_year) restart_time = list(itertools.chain.from_iterable(restart_time)) return restart_time def _get_restart_data_element(self, param, grid_block_number): """ Get Restart Data Parameters ----------- param : str The parameter to be plotted on the y-axis grid_block_number : int the grid block in which its parameter evolution is to be observed. Returns -------- restart_result : list restart data in a list """ locations = self._get_restart_locations() restart_result = [] for i in range(0, len(locations)): if (self.simulatortype.lower() == gc.TMVOC or self.simulatortype.lower() == gc.TOUGH3): file_reader = ResultTough3(self.simulatortype, locations[i], self.filetitle) else: file_reader = ResultReact(self.simulatortype, locations[i], self.filetitle) if i == 0: result_array = file_reader.get_timeseries_data( param, grid_block_number) restart_result.append(result_array) else: result_array = file_reader.get_timeseries_data( param, grid_block_number) result_array = result_array[1:] restart_result.append(result_array) restart_result = list(itertools.chain.from_iterable(restart_result)) return restart_result def _plot_raw_with_expt(self, param, grid_block_number, format_of_date, restart=False, data_file='data_file.csv'): """ Line Plots of a parameter in the results file as a function of time if restart and experiments was performed in the simulation Parameters ----------- param : str The parameter to be plotted on the y-axis grid_block_number : int the grid block in which its parameter evolution is to be observed. format_of_date: str The format of the date; could be minute, hour, day or year restart: boolean If restart was performed in the simulation or not data_file: str Data containing the experimental result in csv format Returns -------- """ expt_test = Experiment(self.expt[0], data_file) time_year_expt = expt_test.get_times() result_array_expt = expt_test.get_timeseries_data(param) parameters = T2Utilities() if restart is True: time_year = self._get_restart_data_time(format_of_date) result_array = self._get_restart_data_element( param, grid_block_number) time_year, result_array = parameters.remove_repetiting( time_year, result_array) else: file_reader = self._read_file() time_year = file_reader.convert_times(format_of_date) result_array = file_reader.get_timeseries_data( param, grid_block_number) fig, axs = plt.subplots(1, 1) if max(result_array_expt) <= 0: dy = 0.15 * abs(min(result_array_expt)) else: dy = 0.15 * abs(max(result_array_expt)) axs.plot(time_year, result_array, marker=pc.CARET_SYMBOL, label=gc.SIMULATION) axs.errorbar(time_year_expt, result_array_expt, yerr=dy, fmt=pc.COLOR_FORMAT, color=pc.RED_SYMBOL, label=gc.EXPERIMENT) if format_of_date.lower() == pc.YEAR: axs.set_xlabel(pc.X_LABEL_TIME_YEAR, fontsize=12) elif format_of_date.lower() == pc.DAY: axs.set_xlabel(pc.X_LABEL_TIME_DAY, fontsize=12) elif format_of_date.lower() == pc.HOUR: axs.set_xlabel(pc.X_LABEL_TIME_HOUR, fontsize=12) elif format_of_date.lower() == pc.MINUTE: axs.set_xlabel(pc.X_LABEL_TIME_MIN, fontsize=12) axs.set_ylabel(parameters.param_label_full(param.upper()), fontsize=12) axs.spines[pc.BOTTOM].set_linewidth(1.5) axs.spines[pc.LEFT].set_linewidth(1.5) axs.spines[pc.TOP].set_linewidth(0) axs.spines[pc.RIGHT].set_linewidth(0) plt.legend(loc=pc.LOC_BEST) plt.setp(axs.get_xticklabels(), fontsize=12) plt.setp(axs.get_yticklabels(), fontsize=12) plt.tight_layout() plt.show() if restart is True: os.chdir(self.file_location) fig.savefig(param + ' ' + pc.VERSUS + ' ' + pc.TIME + ' ' + pc.RESTART + ' ' + pc.EXPERIMENT + pc.IMAGE_TYPE, bbox_inches=pc.TIGHT_BBOX, dpi=600) else: os.chdir(self.file_location) fig.savefig(param + ' ' + pc.VERSUS + ' ' + pc.TIME + ' ' + pc.EXPERIMENT + pc.IMAGE_TYPE, bbox_inches=pc.TIGHT_BBOX, dpi=600)
[docs] def plot_param_with_time_restart(self, param, grid_block_number, format_of_date): """ Line Plots of a parameter in the results file as a function of time if restart was performed in the simulation Parameters ----------- param : str The parameter to be plotted on the y-axis grid_block_number : int the grid block in which its parameter evolution is to be observed. format_of_date: str The format of the date; could be minute, hour, day or year Returns -------- """ if self.expt: try: with plt.style.context(pc.MY_STYLE): self._plot_raw_with_expt(param, grid_block_number, format_of_date, restart=True) except Exception: with plt.style.context(pc.CLASSIC): self._plot_raw_with_expt(param, grid_block_number, format_of_date, restart=True) else: try: with plt.style.context(pc.MY_STYLE): self._plot_raw(param, grid_block_number, format_of_date, restart=True) except Exception: with plt.style.context(pc.CLASSIC): self._plot_raw(param, grid_block_number, format_of_date, restart=True)
def _plot_raw_layer(self, direction_x_axis, direction_y_axis, param, layer_num, time): """ Line Plots to show the evolution of a particular parameter across a layer at a particular time Parameters ----------- direction_x_axis : str The direction to be plotted on the x axis direction_y_axis : str The direction to be plotted on the y axis param : list[str] List of parameters layer_num : int The layer in the model to be plotted time : int the time at which the plot is to be made Returns -------- """ file_reader = self._read_file() if len(param) == 1: y_data = file_reader.get_layer_data(direction_y_axis, layer_num, time, param[0]) x_data = file_reader.get_unique_coord_data(direction_x_axis, time) fig, axs = plt.subplots(1, 1) axs.plot(x_data, y_data, marker=pc.CARET_SYMBOL) axs.set_xlabel(pc.DISTANCE_MSG + ' ' + direction_x_axis + ' ' + pc.DIRECTION + ' ' + pc.OPEN_BRACKET + pc.METER + pc.CLOSE_BRACKET) axs.set_ylabel(self.modifier.param_label_full(param[0].upper())) plt.tight_layout() plt.show() os.chdir(self.file_location) fig.savefig(param[0] + ' ' + pc.LAYER_FOR_LAYER + ' ' + str(layer_num) + pc.IMAGE_TYPE, bbox_inches=pc.TIGHT_BBOX, dpi=600) else: fig = plt.figure(figsize=(10, 8)) plot_counter = 1 start_point = 0 x_data = file_reader.get_unique_coord_data(direction_x_axis, time) for _ in range(1, len(param) + 1): axs = plt.subplot(math.ceil(len(param) / 2) + 1, 2, plot_counter) y_data = file_reader.get_layer_data(direction_y_axis, layer_num, time, param[start_point]) axs.plot(x_data, y_data) axs.set_xlabel(pc.DISTANCE_MSG + ' ' + direction_x_axis + ' ' + pc.DIRECTION + ' ' + pc.OPEN_BRACKET + pc.METER + pc.CLOSE_BRACKET, fontsize=14) axs.set_ylabel(self.modifier.param_label_full( param[start_point].upper()), fontsize=14) plot_counter = plot_counter + 1 start_point = start_point + 1 plt.setp(axs.get_xticklabels(), fontsize=14) plt.setp(axs.get_yticklabels(), fontsize=14) fig.tight_layout() plt.show()
[docs] def plot_param_with_param(self, param1, param2, grid_block_number): """ Line Plot of two parameters in the results file Parameters ----------- param1 : str The parameter to be plotted on the x-axis param2 : str The parameter to be plotted on the y-axis grid_block_number : int the grid block in which its parameter evolution is to be observed. Returns -------- """ try: with plt.style.context(pc.MY_STYLE): file_reader = self._read_file() result_array_x = file_reader.get_timeseries_data( param1, grid_block_number) result_array_y = file_reader.get_timeseries_data( param2, grid_block_number) fig, axs = plt.subplots(1, 1) axs.plot(result_array_x, result_array_y, marker=pc.CARET_SYMBOL) axs.set_xlabel(self.modifier.param_label_full(param1.upper())) axs.set_ylabel(self.modifier.param_label_full(param2.upper())) plt.tight_layout() plt.show() fig.savefig(param2 + ' ' + pc.VERSUS + ' ' + param1 + pc.IMAGE_TYPE, bbox_inches=pc.TIGHT_BBOX, dpi=600) except Exception: with plt.style.context(pc.CLASSIC): file_reader = self._read_file() result_array_x = file_reader.get_timeseries_data( param1, grid_block_number) result_array_y = file_reader.get_timeseries_data( param2, grid_block_number) fig, axs = plt.subplots(1, 1) axs.plot(result_array_x, result_array_y, marker=pc.CARET_SYMBOL) axs.set_xlabel(self.modifier.param_label_full(param1.upper())) axs.set_ylabel(self.modifier.param_label_full(param2.upper())) plt.tight_layout() plt.show() fig.savefig(param2 + ' ' + pc.VERSUS + ' ' + param1 + pc.IMAGE_TYPE, bbox_inches=pc.TIGHT_BBOX, dpi=600)
[docs] def plot_param_with_layer(self, direction_x_axis, direction_y_axis, param, layer_num, time): """ Line Plots to show the evolution of a particular parameter across a layer at a particular time Parameters ----------- direction_x_axis : str The direction to be plotted on the x axis direction_y_axis : str The direction to be plotted on the y axis param : list[str] List of parameters layer_num : int The layer in the model to be plotted time : int the time at which the plot is to be made Returns -------- """ try: with plt.style.context(pc.MY_STYLE): self._plot_raw_layer(direction_x_axis, direction_y_axis, param, layer_num, time) except Exception: with plt.style.context(pc.CLASSIC): self._plot_raw_layer(direction_x_axis, direction_y_axis, param, layer_num, time)
[docs] def plot_2d_one(self, direction_y_axis, direction_x_axis, param, timer): """ 2D mesh plot (ungridded) to show the evolution of a particular parameter across a the entire domain at a particular time Parameters ----------- direction_x_axis : str The direction to be plotted on the x axis direction_y_axis : str The direction to be plotted on the y axis param : str parameter to be plotted time : int the time at which the plot is to be made Returns -------- """ file_reader = self._read_file() fig, ax = plt.subplots(1, 1) x = file_reader.get_coord_data(direction_y_axis, timer) z = file_reader.get_coord_data(direction_x_axis, timer) data = file_reader.get_element_data(timer, param) xi, yi = np.meshgrid(x, z) data1 = griddata((x, z), data, (xi, yi), method=pc.METHOD) cs2 = plt.contourf(xi, yi, data1, 800, cmap=pc.CMAP_COLOR, vmin=min(data), vmax=max(data)) vmin = min(data) if vmin < 1 or vmin > 1000: cbar = fig.colorbar(cs2, pad=0.01, format=ticker.FuncFormatter(self.modifier.fmt)) else: cbar = fig.colorbar(cs2, pad=0.01) cbar.ax.set_ylabel(self.modifier.param_label_full(param.upper()), fontsize=12) ticklabs = cbar.ax.get_yticklabels() try: cbar.ax.set_yticklabels(ticklabs, fontsize=12) except ValueError: pass plt.xlabel(pc.HORIZONTAL_ADDED.capitalize() + ' ' + pc.DISTANCE.capitalize() + pc.OPEN_BRACKET + pc.METER + pc.CLOSE_BRACKET, fontsize=12) plt.ylabel(pc.VERTICAL_ADDED.capitalize() + ' ' + pc.DEPTH.capitalize() + pc.OPEN_BRACKET + pc.METER + pc.CLOSE_BRACKET, fontsize=12) plt.tick_params(axis=pc.X, labelsize=12) plt.tick_params(axis=pc.Y, labelsize=12) plt.tight_layout() plt.show() fig.savefig('2D plain' + str(timer) + param + pc.IMAGE_TYPE, bbox_inches=pc.TIGHT_BBOX, dpi=600)
[docs] def plot_2d_with_grid(self, direction_y_axis, direction_x_axis, param, timer): """ 2D mesh plot (gridded) to show the evolution of a particular parameter across a the entire domain at a particular time Parameters ----------- direction_x_axis : str The direction to be plotted on the x axis direction_y_axis : str The direction to be plotted on the y axis param : str parameter to be plotted time : int the time at which the plot is to be made Returns -------- """ file_reader = self._read_file() x = file_reader.get_coord_data(direction_y_axis, timer) z = file_reader.get_coord_data(direction_x_axis, timer) df = pd.DataFrame(index=range(len(x))) df[pc.X_CAPS] = x df[pc.Z_CAPS] = z z_values, z_total = self.modifier.get_grid_number(df, pc.Z_CAPS) x_values, x_total = self.modifier.get_grid_number(df, pc.X_CAPS) xi, yi = np.meshgrid(x, z) orig_data = file_reader.get_element_data(timer, param) data = np.asarray(orig_data) data = data.reshape(z_total, x_total) if z_total > 5: height = 10 else: height = 4 fig, ax = plt.subplots(1, 1, figsize=(10, height)) # data1 = griddata((X, Z), orig_data, (xi, yi), method=pc.METHOD) # extent = [min(X), max(X), min(Z), max(Z)] cs2 = plt.imshow(np.reshape(data, newshape=(z_total, x_total)), cmap=pc.CMAP_COLOR, interpolation=pc.INTERPOLATION, aspect=pc.ASPECT) ax = plt.gca() slicer_x = len(x_values) slicer_z = len(z_values) if slicer_z < 10: slicer_z = 1 if slicer_x <= 10: slicer_x = 1 while slicer_x > 10 or slicer_z > 10: if slicer_x > 10: slicer_x = np.round(slicer_x / 2) if slicer_z > 10: slicer_z = np.round(slicer_z / 2) x_tick = np.arange(0, x_total, slicer_x) z_tick = np.arange(0, z_total, slicer_z) z_array = np.asarray(z) z_array = np.abs(z_array) ax.set_xticks(x_tick) num_tick_x = len(x_tick) num_tick_z = len(z_tick) ax.set_yticks(z_tick) # Labels for major ticks tick_x = max(x) - min(x) tick_z = max(z) - min(z) x_tick = x_tick.astype(int) if max(x) < 1 or max(z) < 1: magoosh = [x_values[i] for i in x_tick] magoosh = np.asarray(magoosh) ax.set_xticklabels(magoosh, fontsize=12) ax.set_yticklabels(np.round(self.modifier.crange(min(z_array), max(z_array), tick_z / ( num_tick_z - 1)), 4), fontsize=12) else: ax.set_xticklabels(np.round(self.modifier.crange( min(x), max(x), tick_x / (num_tick_x - 1)), 2), fontsize=12) ax.set_yticklabels(np.round(self.modifier.crange( min(z_array), max(z_array), tick_z / (num_tick_z - 1)), 2), fontsize=12) # Minor ticks ax.set_xticks(np.arange(-.5, x_total, 1), minor=True) ax.set_yticks(np.arange(-.5, z_total, 1), minor=True) # Gridlines based on minor ticks ax.grid(which='minor', color='k', linestyle='-', linewidth=1) cbar = fig.colorbar(cs2, ax=ax, pad=0.3, orientation=pc.HORIZONTAL) cbar.ax.set_title(param, fontsize=12) cbar.ax.tick_params(labelsize=12) cbar.ax.locator_params(nbins=5) cbar.ax.ticklabel_format(useOffset=False, style=pc.PLAIN_STYLE) plt.xticks(rotation=90) plt.xlabel(pc.HORIZONTAL_ADDED.capitalize() + ' ' + pc.DISTANCE.capitalize() + ' ' + pc.OPEN_BRACKET + pc.METER + pc.CLOSE_BRACKET, fontsize=12) plt.ylabel(pc.VERTICAL_ADDED.capitalize() + ' ' + pc.DEPTH.capitalize() + ' ' + pc.OPEN_BRACKET + pc.METER + pc.CLOSE_BRACKET, fontsize=12) plt.tight_layout() plt.show() fig.savefig(grc.GRID_NAME.capitalize() + str(timer) + param + pc.IMAGE_TYPE, bbox_inches=pc.TIGHT_BBOX, dpi=600)