Module abstochkin.graphing
Graphing for AbStochKin simulations.
Expand source code
""" Graphing for AbStochKin simulations. """
# Copyright (c) 2023, Alex Plakantonakis.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from pathlib import Path
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
class Graph:
"""
Graphing class for displaying the results of AbStochKin simulations.
Notes
-----
To successfully use the LaTeX engine for rendering text on Linux,
run the following command in a terminal: `sudo apt install cm-super`.
"""
# First, set some global matplotlib settings
plt.rcParams['figure.autolayout'] = True # tight layout
plt.rcParams["figure.facecolor"] = 'lightgray'
plt.rcParams['text.usetex'] = True
plt.rcParams['axes.titlesize'] = 9
plt.rcParams['axes.labelsize'] = 7
plt.rcParams['xtick.labelsize'] = 6
plt.rcParams['ytick.labelsize'] = 6
plt.rcParams["legend.fontsize"] = 7
plt.rcParams["legend.framealpha"] = 0.65
def __init__(self, /, nrows=1, ncols=1, figsize=(5, 5), dpi=300, **kwargs):
self.fig, self.ax = plt.subplots(nrows=nrows, ncols=ncols,
figsize=figsize, dpi=dpi,
**kwargs)
def setup_spines_ticks(self, ax_loc):
"""
Make only the left and bottom spines/axes visible on the graph
and place major ticks on them. Also set the minor ticks.
"""
axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc]
axs.spines[['left']].set_position('zero')
axs.spines[['top', 'right']].set_visible(False)
axs.xaxis.set_ticks_position('bottom')
axs.yaxis.set_ticks_position('left')
axs.xaxis.set_minor_locator(ticker.AutoMinorLocator())
axs.yaxis.set_minor_locator(ticker.AutoMinorLocator())
def plot_ODEs(self, de_data,
*,
num_pts: int = 1000,
species: list[str] | tuple[str] = (),
ax_loc: tuple = ()):
"""
Plot the deterministic trajectories of all species obtained
by obtaining the solution to a system of ODEs.
Parameters
----------
de_data : DEcalcs object
Data structure containing all the data related to
solving the system of ODEs.
num_pts : int, default: 1000, optional
Number of points used to calculate DE curves at.
Used to approximate a smooth/continuous curve.
species : sequence of strings, default: (), optional
An iterable sequence of strings specifying the species
names to plot. If no species are specified (the default),
then all species trajectories are plotted.
ax_loc : tuple, optional
If the figure is made up of subplots, specify the location
of the axis to draw the data at.
Ex: for two subplots, the possible values of `ax_loc`
are (0, ) and (1, ). That's because the `self.ax` object is
a 1-D array. For figures with multiple rows and columns of
subplots, a 2-D tuple is needed.
"""
species = list(de_data.odes.keys()) if len(species) == 0 else species
self.setup_spines_ticks(ax_loc)
axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc]
axs.set(xlim=(0, de_data.odes_sol.t[-1]))
# t, y = ode_sol.t, ode_sol.y.T # values at precomputed time pts
t = np.linspace(de_data.odes_sol.t[0], de_data.odes_sol.t[-1],
num_pts) # time points for obtaining...
y = de_data.odes_sol.sol(t).T # an approximately continuous solution
for i, sp in enumerate(list(de_data.odes.keys())):
if sp in species:
axs.plot(t, y[:, i], label=f"${sp}_{{DE}}$",
linestyle='--', linewidth=0.75, alpha=0.75)
# axs.set(title="Deterministic trajectories")
axs.set(xlabel=f"${de_data.time_unit}$", ylabel="$N$")
axs.legend(loc='upper right')
self.fig.tight_layout()
def plot_trajectories(self, time, data,
*,
species: list[str] | tuple[str] = (),
ax_loc: tuple = ()):
""" Graph simulation time trajectories. """
self.setup_spines_ticks(ax_loc)
axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc]
axs.set(xlim=(0, time[-1]))
species = list(data.keys()) if len(species) == 0 else species
for sp, sp_data in data.items():
if sp in species:
trajs = sp_data['N'].T
for traj in trajs:
axs.plot(time, traj, linewidth=0.25)
axs.set(title="ABK trajectories")
axs.set(xlabel=f"$t$ (sec)", ylabel="$N$")
# axs.legend(loc='best')
def plot_avg_std(self, time, data,
*,
species: list[str] | tuple[str] = (),
ax_loc: tuple = ()):
"""
Graph simulation average trajectories and
1-standard-deviation envelopes.
"""
self.setup_spines_ticks(ax_loc)
axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc]
axs.set(xlim=(0, time[-1]))
species = list(data.keys()) if len(species) == 0 else species
for sp, sp_data in data.items():
if sp in species:
axs.plot(time, sp_data['N_avg'],
linewidth=1.5, label=f"${sp}$", alpha=0.5)
axs.fill_between(time,
sp_data['N_avg'] - sp_data['N_std'],
sp_data['N_avg'] + sp_data['N_std'],
alpha=0.5, linewidth=0)
axs.set(xlabel="$t$ (sec)", ylabel="$<N>$")
axs.legend(loc='upper right')
self.fig.tight_layout()
def plot_eta(self, time, data, *, species: list[str] | tuple[str] = (),
ax_loc: tuple = ()):
""" Graph the coefficient of variation. """
self.setup_spines_ticks(ax_loc)
axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc]
axs.set(xlim=(0, time[-1]))
species = list(data.keys()) if len(species) == 0 else species
for sp, sp_data in data.items():
if sp in species:
axs.plot(time, sp_data['eta'], linewidth=1.5, label=f"${sp}$")
axs.plot(time, sp_data['eta_p'], linewidth=1, linestyle='--',
label=f"${sp}_{{Poisson}}$", color=(0.5, 0.5, 0.5))
axs.set(title="Coefficient of Variation, $\\eta$")
axs.set(xlabel=f"$t$ (sec)", ylabel="$\\eta$")
axs.legend(loc='upper right')
def plot_het_metrics(self, time,
proc_str: tuple[str, str],
proc_data: dict,
*, het_attr='k', ax_loc: tuple = ()):
"""
Graph species- and process-specific metrics of population heterogeneity.
"""
self.setup_spines_ticks(ax_loc)
axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc]
axs.set(xlim=(0, time[-1]))
axs.set(xlim=(0, time[-1]),
ylim=(0, 1.5 * np.max(proc_data[f"<{het_attr}_avg>"] + proc_data[
f"<{het_attr}_std>"])))
axs.plot(time, proc_data[f'<{het_attr}_avg>'],
linewidth=1.5, label=f"$<{het_attr}>$", alpha=0.5)
axs.fill_between(time,
proc_data[f"<{het_attr}_avg>"] - proc_data[f"<{het_attr}_std>"],
proc_data[f"<{het_attr}_avg>"] + proc_data[f"<{het_attr}_std>"],
alpha=0.5, linewidth=0)
axs.tick_params(axis='y', labelcolor='blue')
title = f"${proc_str[0].split(';')[0].replace(' ,' , chr(92) + 'hspace{10pt} ,').replace('->', chr(92) + 'rightarrow')}$"
axs.set(title=title + (f"$, {proc_str[1]}$" if proc_str[1] != "" else ""),
xlabel=f"$t$ (sec)")
if het_attr == 'Km':
axs.set_ylabel(f"$K_m$", color='blue')
elif het_attr == 'K50':
axs.set_ylabel("$K_{50}$", color='blue')
else:
axs.set_ylabel(f"${het_attr}$", color='blue')
axs2 = axs.twinx()
axs2.spines[['bottom']].set_position('zero') # x axis
axs2.spines[['right']].set_position(('axes', 1)) # y axis
axs2.spines[['top', 'left', 'bottom']].set_visible(False)
# axs2.spines['right'].set_color('red')
axs2.set(ylim=(0, 1))
axs2.tick_params(axis='y', labelcolor='red')
axs2.yaxis.set_ticks_position('right')
axs2.set_yticks([i for i in np.arange(0, 1.1, 0.1)])
axs2.yaxis.set_minor_locator(ticker.AutoMinorLocator())
axs2.grid(which='major', axis='y', color='r',
linestyle='--', linewidth=0.25, alpha=0.25)
axs2.plot(time, proc_data['psi_avg'],
linewidth=1.5, label='$<\\psi>$', color='red', alpha=0.5)
axs2.fill_between(time,
proc_data['psi_avg'] - proc_data['psi_std'],
proc_data['psi_avg'] + proc_data['psi_std'],
color='red', alpha=0.5, linewidth=0)
axs2.set_ylabel("$\\psi$", color='red')
def savefig(self, filename, **kwargs):
""" Save the figure as a file. """
graph_path = Path('.') / 'output'
graph_path.mkdir(exist_ok=True)
graph_path_svg = graph_path / filename
self.fig.savefig(graph_path_svg, **kwargs)
plt.close(self.fig)
Classes
class Graph (nrows=1, ncols=1, figsize=(5, 5), dpi=300, **kwargs)
-
Graphing class for displaying the results of AbStochKin simulations.
Notes
To successfully use the LaTeX engine for rendering text on Linux, run the following command in a terminal:
sudo apt install cm-super
.Expand source code
class Graph: """ Graphing class for displaying the results of AbStochKin simulations. Notes ----- To successfully use the LaTeX engine for rendering text on Linux, run the following command in a terminal: `sudo apt install cm-super`. """ # First, set some global matplotlib settings plt.rcParams['figure.autolayout'] = True # tight layout plt.rcParams["figure.facecolor"] = 'lightgray' plt.rcParams['text.usetex'] = True plt.rcParams['axes.titlesize'] = 9 plt.rcParams['axes.labelsize'] = 7 plt.rcParams['xtick.labelsize'] = 6 plt.rcParams['ytick.labelsize'] = 6 plt.rcParams["legend.fontsize"] = 7 plt.rcParams["legend.framealpha"] = 0.65 def __init__(self, /, nrows=1, ncols=1, figsize=(5, 5), dpi=300, **kwargs): self.fig, self.ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=figsize, dpi=dpi, **kwargs) def setup_spines_ticks(self, ax_loc): """ Make only the left and bottom spines/axes visible on the graph and place major ticks on them. Also set the minor ticks. """ axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.spines[['left']].set_position('zero') axs.spines[['top', 'right']].set_visible(False) axs.xaxis.set_ticks_position('bottom') axs.yaxis.set_ticks_position('left') axs.xaxis.set_minor_locator(ticker.AutoMinorLocator()) axs.yaxis.set_minor_locator(ticker.AutoMinorLocator()) def plot_ODEs(self, de_data, *, num_pts: int = 1000, species: list[str] | tuple[str] = (), ax_loc: tuple = ()): """ Plot the deterministic trajectories of all species obtained by obtaining the solution to a system of ODEs. Parameters ---------- de_data : DEcalcs object Data structure containing all the data related to solving the system of ODEs. num_pts : int, default: 1000, optional Number of points used to calculate DE curves at. Used to approximate a smooth/continuous curve. species : sequence of strings, default: (), optional An iterable sequence of strings specifying the species names to plot. If no species are specified (the default), then all species trajectories are plotted. ax_loc : tuple, optional If the figure is made up of subplots, specify the location of the axis to draw the data at. Ex: for two subplots, the possible values of `ax_loc` are (0, ) and (1, ). That's because the `self.ax` object is a 1-D array. For figures with multiple rows and columns of subplots, a 2-D tuple is needed. """ species = list(de_data.odes.keys()) if len(species) == 0 else species self.setup_spines_ticks(ax_loc) axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.set(xlim=(0, de_data.odes_sol.t[-1])) # t, y = ode_sol.t, ode_sol.y.T # values at precomputed time pts t = np.linspace(de_data.odes_sol.t[0], de_data.odes_sol.t[-1], num_pts) # time points for obtaining... y = de_data.odes_sol.sol(t).T # an approximately continuous solution for i, sp in enumerate(list(de_data.odes.keys())): if sp in species: axs.plot(t, y[:, i], label=f"${sp}_{{DE}}$", linestyle='--', linewidth=0.75, alpha=0.75) # axs.set(title="Deterministic trajectories") axs.set(xlabel=f"${de_data.time_unit}$", ylabel="$N$") axs.legend(loc='upper right') self.fig.tight_layout() def plot_trajectories(self, time, data, *, species: list[str] | tuple[str] = (), ax_loc: tuple = ()): """ Graph simulation time trajectories. """ self.setup_spines_ticks(ax_loc) axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.set(xlim=(0, time[-1])) species = list(data.keys()) if len(species) == 0 else species for sp, sp_data in data.items(): if sp in species: trajs = sp_data['N'].T for traj in trajs: axs.plot(time, traj, linewidth=0.25) axs.set(title="ABK trajectories") axs.set(xlabel=f"$t$ (sec)", ylabel="$N$") # axs.legend(loc='best') def plot_avg_std(self, time, data, *, species: list[str] | tuple[str] = (), ax_loc: tuple = ()): """ Graph simulation average trajectories and 1-standard-deviation envelopes. """ self.setup_spines_ticks(ax_loc) axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.set(xlim=(0, time[-1])) species = list(data.keys()) if len(species) == 0 else species for sp, sp_data in data.items(): if sp in species: axs.plot(time, sp_data['N_avg'], linewidth=1.5, label=f"${sp}$", alpha=0.5) axs.fill_between(time, sp_data['N_avg'] - sp_data['N_std'], sp_data['N_avg'] + sp_data['N_std'], alpha=0.5, linewidth=0) axs.set(xlabel="$t$ (sec)", ylabel="$<N>$") axs.legend(loc='upper right') self.fig.tight_layout() def plot_eta(self, time, data, *, species: list[str] | tuple[str] = (), ax_loc: tuple = ()): """ Graph the coefficient of variation. """ self.setup_spines_ticks(ax_loc) axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.set(xlim=(0, time[-1])) species = list(data.keys()) if len(species) == 0 else species for sp, sp_data in data.items(): if sp in species: axs.plot(time, sp_data['eta'], linewidth=1.5, label=f"${sp}$") axs.plot(time, sp_data['eta_p'], linewidth=1, linestyle='--', label=f"${sp}_{{Poisson}}$", color=(0.5, 0.5, 0.5)) axs.set(title="Coefficient of Variation, $\\eta$") axs.set(xlabel=f"$t$ (sec)", ylabel="$\\eta$") axs.legend(loc='upper right') def plot_het_metrics(self, time, proc_str: tuple[str, str], proc_data: dict, *, het_attr='k', ax_loc: tuple = ()): """ Graph species- and process-specific metrics of population heterogeneity. """ self.setup_spines_ticks(ax_loc) axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.set(xlim=(0, time[-1])) axs.set(xlim=(0, time[-1]), ylim=(0, 1.5 * np.max(proc_data[f"<{het_attr}_avg>"] + proc_data[ f"<{het_attr}_std>"]))) axs.plot(time, proc_data[f'<{het_attr}_avg>'], linewidth=1.5, label=f"$<{het_attr}>$", alpha=0.5) axs.fill_between(time, proc_data[f"<{het_attr}_avg>"] - proc_data[f"<{het_attr}_std>"], proc_data[f"<{het_attr}_avg>"] + proc_data[f"<{het_attr}_std>"], alpha=0.5, linewidth=0) axs.tick_params(axis='y', labelcolor='blue') title = f"${proc_str[0].split(';')[0].replace(' ,' , chr(92) + 'hspace{10pt} ,').replace('->', chr(92) + 'rightarrow')}$" axs.set(title=title + (f"$, {proc_str[1]}$" if proc_str[1] != "" else ""), xlabel=f"$t$ (sec)") if het_attr == 'Km': axs.set_ylabel(f"$K_m$", color='blue') elif het_attr == 'K50': axs.set_ylabel("$K_{50}$", color='blue') else: axs.set_ylabel(f"${het_attr}$", color='blue') axs2 = axs.twinx() axs2.spines[['bottom']].set_position('zero') # x axis axs2.spines[['right']].set_position(('axes', 1)) # y axis axs2.spines[['top', 'left', 'bottom']].set_visible(False) # axs2.spines['right'].set_color('red') axs2.set(ylim=(0, 1)) axs2.tick_params(axis='y', labelcolor='red') axs2.yaxis.set_ticks_position('right') axs2.set_yticks([i for i in np.arange(0, 1.1, 0.1)]) axs2.yaxis.set_minor_locator(ticker.AutoMinorLocator()) axs2.grid(which='major', axis='y', color='r', linestyle='--', linewidth=0.25, alpha=0.25) axs2.plot(time, proc_data['psi_avg'], linewidth=1.5, label='$<\\psi>$', color='red', alpha=0.5) axs2.fill_between(time, proc_data['psi_avg'] - proc_data['psi_std'], proc_data['psi_avg'] + proc_data['psi_std'], color='red', alpha=0.5, linewidth=0) axs2.set_ylabel("$\\psi$", color='red') def savefig(self, filename, **kwargs): """ Save the figure as a file. """ graph_path = Path('.') / 'output' graph_path.mkdir(exist_ok=True) graph_path_svg = graph_path / filename self.fig.savefig(graph_path_svg, **kwargs) plt.close(self.fig)
Methods
def plot_ODEs(self, de_data, *, num_pts: int = 1000, species: list[str] | tuple[str] = (), ax_loc: tuple = ())
-
Plot the deterministic trajectories of all species obtained by obtaining the solution to a system of ODEs.
Parameters
de_data
:DEcalcs object
- Data structure containing all the data related to solving the system of ODEs.
num_pts
:int
, default: 1000
, optional- Number of points used to calculate DE curves at. Used to approximate a smooth/continuous curve.
species
:sequence
ofstrings
, default: ()
, optional- An iterable sequence of strings specifying the species names to plot. If no species are specified (the default), then all species trajectories are plotted.
ax_loc
:tuple
, optional- If the figure is made up of subplots, specify the location
of the axis to draw the data at.
Ex: for two subplots, the possible values of
ax_loc
are (0, ) and (1, ). That's because theself.ax
object is a 1-D array. For figures with multiple rows and columns of subplots, a 2-D tuple is needed.
Expand source code
def plot_ODEs(self, de_data, *, num_pts: int = 1000, species: list[str] | tuple[str] = (), ax_loc: tuple = ()): """ Plot the deterministic trajectories of all species obtained by obtaining the solution to a system of ODEs. Parameters ---------- de_data : DEcalcs object Data structure containing all the data related to solving the system of ODEs. num_pts : int, default: 1000, optional Number of points used to calculate DE curves at. Used to approximate a smooth/continuous curve. species : sequence of strings, default: (), optional An iterable sequence of strings specifying the species names to plot. If no species are specified (the default), then all species trajectories are plotted. ax_loc : tuple, optional If the figure is made up of subplots, specify the location of the axis to draw the data at. Ex: for two subplots, the possible values of `ax_loc` are (0, ) and (1, ). That's because the `self.ax` object is a 1-D array. For figures with multiple rows and columns of subplots, a 2-D tuple is needed. """ species = list(de_data.odes.keys()) if len(species) == 0 else species self.setup_spines_ticks(ax_loc) axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.set(xlim=(0, de_data.odes_sol.t[-1])) # t, y = ode_sol.t, ode_sol.y.T # values at precomputed time pts t = np.linspace(de_data.odes_sol.t[0], de_data.odes_sol.t[-1], num_pts) # time points for obtaining... y = de_data.odes_sol.sol(t).T # an approximately continuous solution for i, sp in enumerate(list(de_data.odes.keys())): if sp in species: axs.plot(t, y[:, i], label=f"${sp}_{{DE}}$", linestyle='--', linewidth=0.75, alpha=0.75) # axs.set(title="Deterministic trajectories") axs.set(xlabel=f"${de_data.time_unit}$", ylabel="$N$") axs.legend(loc='upper right') self.fig.tight_layout()
def plot_avg_std(self, time, data, *, species: list[str] | tuple[str] = (), ax_loc: tuple = ())
-
Graph simulation average trajectories and 1-standard-deviation envelopes.
Expand source code
def plot_avg_std(self, time, data, *, species: list[str] | tuple[str] = (), ax_loc: tuple = ()): """ Graph simulation average trajectories and 1-standard-deviation envelopes. """ self.setup_spines_ticks(ax_loc) axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.set(xlim=(0, time[-1])) species = list(data.keys()) if len(species) == 0 else species for sp, sp_data in data.items(): if sp in species: axs.plot(time, sp_data['N_avg'], linewidth=1.5, label=f"${sp}$", alpha=0.5) axs.fill_between(time, sp_data['N_avg'] - sp_data['N_std'], sp_data['N_avg'] + sp_data['N_std'], alpha=0.5, linewidth=0) axs.set(xlabel="$t$ (sec)", ylabel="$<N>$") axs.legend(loc='upper right') self.fig.tight_layout()
def plot_eta(self, time, data, *, species: list[str] | tuple[str] = (), ax_loc: tuple = ())
-
Graph the coefficient of variation.
Expand source code
def plot_eta(self, time, data, *, species: list[str] | tuple[str] = (), ax_loc: tuple = ()): """ Graph the coefficient of variation. """ self.setup_spines_ticks(ax_loc) axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.set(xlim=(0, time[-1])) species = list(data.keys()) if len(species) == 0 else species for sp, sp_data in data.items(): if sp in species: axs.plot(time, sp_data['eta'], linewidth=1.5, label=f"${sp}$") axs.plot(time, sp_data['eta_p'], linewidth=1, linestyle='--', label=f"${sp}_{{Poisson}}$", color=(0.5, 0.5, 0.5)) axs.set(title="Coefficient of Variation, $\\eta$") axs.set(xlabel=f"$t$ (sec)", ylabel="$\\eta$") axs.legend(loc='upper right')
def plot_het_metrics(self, time, proc_str: tuple[str, str], proc_data: dict, *, het_attr='k', ax_loc: tuple = ())
-
Graph species- and process-specific metrics of population heterogeneity.
Expand source code
def plot_het_metrics(self, time, proc_str: tuple[str, str], proc_data: dict, *, het_attr='k', ax_loc: tuple = ()): """ Graph species- and process-specific metrics of population heterogeneity. """ self.setup_spines_ticks(ax_loc) axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.set(xlim=(0, time[-1])) axs.set(xlim=(0, time[-1]), ylim=(0, 1.5 * np.max(proc_data[f"<{het_attr}_avg>"] + proc_data[ f"<{het_attr}_std>"]))) axs.plot(time, proc_data[f'<{het_attr}_avg>'], linewidth=1.5, label=f"$<{het_attr}>$", alpha=0.5) axs.fill_between(time, proc_data[f"<{het_attr}_avg>"] - proc_data[f"<{het_attr}_std>"], proc_data[f"<{het_attr}_avg>"] + proc_data[f"<{het_attr}_std>"], alpha=0.5, linewidth=0) axs.tick_params(axis='y', labelcolor='blue') title = f"${proc_str[0].split(';')[0].replace(' ,' , chr(92) + 'hspace{10pt} ,').replace('->', chr(92) + 'rightarrow')}$" axs.set(title=title + (f"$, {proc_str[1]}$" if proc_str[1] != "" else ""), xlabel=f"$t$ (sec)") if het_attr == 'Km': axs.set_ylabel(f"$K_m$", color='blue') elif het_attr == 'K50': axs.set_ylabel("$K_{50}$", color='blue') else: axs.set_ylabel(f"${het_attr}$", color='blue') axs2 = axs.twinx() axs2.spines[['bottom']].set_position('zero') # x axis axs2.spines[['right']].set_position(('axes', 1)) # y axis axs2.spines[['top', 'left', 'bottom']].set_visible(False) # axs2.spines['right'].set_color('red') axs2.set(ylim=(0, 1)) axs2.tick_params(axis='y', labelcolor='red') axs2.yaxis.set_ticks_position('right') axs2.set_yticks([i for i in np.arange(0, 1.1, 0.1)]) axs2.yaxis.set_minor_locator(ticker.AutoMinorLocator()) axs2.grid(which='major', axis='y', color='r', linestyle='--', linewidth=0.25, alpha=0.25) axs2.plot(time, proc_data['psi_avg'], linewidth=1.5, label='$<\\psi>$', color='red', alpha=0.5) axs2.fill_between(time, proc_data['psi_avg'] - proc_data['psi_std'], proc_data['psi_avg'] + proc_data['psi_std'], color='red', alpha=0.5, linewidth=0) axs2.set_ylabel("$\\psi$", color='red')
def plot_trajectories(self, time, data, *, species: list[str] | tuple[str] = (), ax_loc: tuple = ())
-
Graph simulation time trajectories.
Expand source code
def plot_trajectories(self, time, data, *, species: list[str] | tuple[str] = (), ax_loc: tuple = ()): """ Graph simulation time trajectories. """ self.setup_spines_ticks(ax_loc) axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.set(xlim=(0, time[-1])) species = list(data.keys()) if len(species) == 0 else species for sp, sp_data in data.items(): if sp in species: trajs = sp_data['N'].T for traj in trajs: axs.plot(time, traj, linewidth=0.25) axs.set(title="ABK trajectories") axs.set(xlabel=f"$t$ (sec)", ylabel="$N$") # axs.legend(loc='best')
def savefig(self, filename, **kwargs)
-
Save the figure as a file.
Expand source code
def savefig(self, filename, **kwargs): """ Save the figure as a file. """ graph_path = Path('.') / 'output' graph_path.mkdir(exist_ok=True) graph_path_svg = graph_path / filename self.fig.savefig(graph_path_svg, **kwargs) plt.close(self.fig)
def setup_spines_ticks(self, ax_loc)
-
Make only the left and bottom spines/axes visible on the graph and place major ticks on them. Also set the minor ticks.
Expand source code
def setup_spines_ticks(self, ax_loc): """ Make only the left and bottom spines/axes visible on the graph and place major ticks on them. Also set the minor ticks. """ axs = self.ax if len(ax_loc) == 0 else self.ax[ax_loc] axs.spines[['left']].set_position('zero') axs.spines[['top', 'right']].set_visible(False) axs.xaxis.set_ticks_position('bottom') axs.yaxis.set_ticks_position('left') axs.xaxis.set_minor_locator(ticker.AutoMinorLocator()) axs.yaxis.set_minor_locator(ticker.AutoMinorLocator())