Source code for prodimopy.plot_mc

"""
.. module:: plot_mc
   :synopsis: Plotting routines for molecular cloud |prodimo| models (0D chemistry).

.. moduleauthor:: Ch. Rab
"""

import matplotlib.pyplot as plt
import numpy as np
from prodimopy.plot import spnToLatex
from matplotlib.backends.backend_pdf import PdfPages


# That crashes in the bash on Mac OS X.. maybe because of installation
[docs] class PlotMcModel(object): """ Plot routines for a single molecular cloud |prodimo| model (0D chemistry). .. todo:: - Redesign this. it is not very useful to have this dokwargs legend etc. routines copied all the time. """ def __init__( self, pdf: PdfPages | None = None, colors=None, styles=None, markers=None, fs_legend=6, # TODO: init it with the system default legend fontsize ncol_legend=0, ): """ Parameters ---------- pdf : a PdfPages object used to save the plot or None to have output on screen. colors : list a list of matplotlib colors used for different models. (default: None) styles : list a list of matplotlib styles used for different models. (default: None) markers : list a list of matplotlib markers used for different models. (default: None) Attributes ---------- """ self.pdf = pdf if colors is None: self.colors = [ "b", "g", "r", "c", "m", "y", "k", "sienna", "lime", "pink", "DarkOrange", "Olive", ] else: self.colors = colors if styles is None: self.styles = ["-"] * len(self.colors) else: self.styles = styles if markers is None: self.markers = [None] * len(self.colors) else: self.markers = markers self.fs_legend = fs_legend self.ncol_legend = ncol_legend def _dokwargs(self, ax, **kwargs): """ Handles the passed kwargs elements (assumes that defaults are already set) """ if "ylim" in kwargs: ax.set_ylim(kwargs["ylim"]) if "xlim" in kwargs: ax.set_xlim(kwargs["xlim"]) if "xlog" in kwargs: if kwargs["xlog"]: ax.semilogx() if "ylog" in kwargs: if kwargs["ylog"]: ax.semilogy() if "grid" in kwargs: # add a grid ax.grid(kwargs["grid"]) def _legend(self, ax): """ plots the legend, deals with multiple columns """ handles, labels = ax.get_legend_handles_labels() ncol = 1 if self.ncol_legend > 1 and len(labels) > self.ncol_legend: ncol = int(len(labels) / self.ncol_legend) ax.legend( handles, labels, loc="best", fancybox=False, framealpha=0.75, ncol=ncol, fontsize=self.fs_legend, ) def _closefig(self, fig): """ Save and close the plot (Figure). If `self.pdf` is None than nothing is done and the figure is returned #set the transparent attribute (used rcParam savefig.transparent) """ # trans=mpl.rcParams['savefig.transparent'] if self.pdf is not None: self.pdf.savefig(figure=fig, transparent=False) plt.close(fig) return None else: return fig
[docs] def plot_species(self, model, spnames, ax=None, **kwargs): """ Plot the species abundances as function of age (time). One can also pass further arguments such as `xlim (Array)`, `ylim (Array)`, `xlog`, `ylog`, `grid`. Parameters ---------- model : :class:`prodimopy.read_mc.Data_mc` a :class:`prodimopy.read_mc.Data_mc` object used to save the plot. spnames : list or str The names of the species that should be plotted. Can also be a single string. ax : :class:`matplotlib.axes.Axes` The axes object to plot the data on. If None a new figure is created. .. todo:: the x axis (ages) is always plotted in log-scale so the zero age ( initial abundance) is not shown. Needs more flexibility. """ if isinstance(spnames, str): spnames = [spnames] if ax is not None: fig = ax.get_figure() else: fig, ax = plt.subplots(1, 1) i = 0 xmax = 1.0e-99 xmin = 1.0e99 for spname in spnames: if spname in model.species: ax.plot( model.ages, model.abundances[:, model.species.index(spname)], self.styles[i], marker=self.markers[i], color=self.colors[i], label=spname, ) xmax = max([max(model.ages), xmax]) # exclude zero because of log plot # nozeros= xmin = min([min(model.ages[model.ages > 0.0]), xmin]) i = i + 1 else: print("Species " + spname + " not found.") # no data to plot just return if i == 0: return ax.set_xlim(xmin, xmax) ax.semilogx() ax.semilogy() self._dokwargs(ax, **kwargs) ax.set_xlabel(r"years") ax.set_ylabel(r" species abundance") self._legend(ax) if "title" in kwargs and kwargs["title"] is not None: ax.set_title(kwargs["title"]) return self._closefig(fig)
[docs] class PlotMcModels(object): """ Plot routines for a molecular cloud |prodimo| models (0D chemistry). """ def __init__( self, pdf, colors=None, styles=None, markers=None, fs_legend=6, # TODO: init it with the system default legend fontsize ncol_legend=0, ): """ Parameters ---------- name : pdf a :class:`matplotlib.backends.backend_pdf.PdfPages` object used to save the plot. colors : list a list of matplotlib colors used for different models. (default: None) styles : list a list of matplotlib styles used for different models. (default: None) markers : list a list of matplotlib markers used for different models. (default: None) Attributes ---------- """ self.pdf = pdf if colors is None: self.colors = [ "b", "g", "r", "c", "m", "y", "k", "sienna", "lime", "pink", "DarkOrange", "Olive", ] else: self.colors = colors if styles is None: self.styles = ["-"] * len(self.colors) else: self.styles = styles if markers is None: self.markers = [None] * len(self.colors) else: self.markers = markers self.fs_legend = fs_legend self.ncol_legend = ncol_legend def _dokwargs(self, ax, **kwargs): """ Handles the passed kwargs elements (assumes that defaults are already set) """ if "ylim" in kwargs: ax.set_ylim(kwargs["ylim"]) if "xlim" in kwargs: ax.set_xlim(kwargs["xlim"]) if "xlog" in kwargs: if kwargs["xlog"]: ax.semilogx() if "ylog" in kwargs: if kwargs["ylog"]: ax.semilogy() if "grid" in kwargs: # add a grid ax.grid(kwargs["grid"]) def _legend(self, ax): """ plots the legend, deals with multiple columns """ handles, labels = ax.get_legend_handles_labels() ncol = 1 if self.ncol_legend > 1 and len(labels) > self.ncol_legend: ncol = int(len(labels) / self.ncol_legend) ax.legend( handles, labels, loc="best", fancybox=False, framealpha=0.75, ncol=ncol, fontsize=self.fs_legend, ) def _closefig(self, fig): """ Save and close the plot (Figure). If self.pdf is None than nothing is done and the figure is returned #set the transparent attribut (used rcParam savefig.transparent) """ # trans=mpl.rcParams['savefig.transparent'] if self.pdf is not None: self.pdf.savefig(figure=fig, transparent=False) plt.close(fig) return None else: return fig
[docs] def plot_species(self, models, spname, ice=False, ax=None, **kwargs): """ Plot the given species (spname) for all the given models. One can also pass further arguments such as `xlim (Array)`, `ylim (Array)`, `xlog`, `ylog`, `grid`. Parameters ---------- models : array_like(:class:`prodimopy.read_mc.Data_mc`,ndim=1) list of molecular cloud models spname : str The name fo the species to plot """ if ax is not None: fig = ax.get_figure() else: fig, ax = plt.subplots(1, 1) i = 0 xmax = 1.0e-99 xmin = 1.0e99 ymax = 1.0e-99 ymin = 1.0e99 for model in models: if spname in model.species: abun = model.abundances[:, model.species.index(spname)] (line,) = ax.plot( model.ages, abun, self.styles[i], marker=self.markers[i], color=self.colors[i], label=model.name, ) ymax = max([max(abun), ymax]) ymin = min([min(abun[model.ages > 0.0]), ymin]) if ice and (spname + "#" in model.species): abun = model.abundances[:, model.species.index(spname + "#")] (line,) = ax.plot( model.ages, abun, "--", marker=self.markers[i], color=line.get_color() ) ymax = max([max(abun), ymax]) ymin = min([min(abun[model.ages > 0.0]), ymin]) xmax = max([max(model.ages), xmax]) # exclude zero because of log plot # nozeros= xmin = min([min(model.ages[model.ages > 0.0]), xmin]) i = i + 1 # no data to plot just return if i == 0: print("Species " + spname + " not found.") return ax.set_xlim(xmin, xmax) ax.set_ylim(ymin * 0.9, ymax * 1.1) ax.semilogx() ax.semilogy() self._dokwargs(ax, **kwargs) ax.set_xlabel(r"years") ylabel = r" $\mathrm{\epsilon(" + spnToLatex(spname) + ")}$" if ice and (spname + "#" in model.species): ylabel += r", $\mathrm{\epsilon(" + spnToLatex(spname + "#") + ") dashed}$" ax.set_ylabel(ylabel) self._legend(ax) if "title" in kwargs and kwargs["title"] is not None: ax.set_title(kwargs["title"]) return self._closefig(fig)
[docs] def plot_species_diff(self, models, spname, ax=None, **kwargs): """ Plot the difference of the species abundance relative to the last model. The relative diffferencie is definded as abs(modelval/modelrefval-1.0). One can also pass further arguments such as `xlim (Array)`, `ylim (Array)`, `xlog`, `ylog`, `grid`. Parameters ---------- models : array_like(:class:`prodimopy.read_mc.Data_mc`,ndim=1) list of molecular cloud models spname : str The name fo the species to plot """ if ax is not None: fig = ax.get_figure() else: fig, ax = plt.subplots(1, 1) i = 0 xmax = 1.0e-99 xmin = 1.0e99 ymax = 1.0e-99 ymin = 1.0e99 for model in models[:-1]: if spname in model.species: # FIXME: add small number to avoid problems with zero diff = np.absolute( (model.abundances[1:, model.species.index(spname)] + 1.0e-200) / (models[-1].abundances[1:, models[-1].species.index(spname)] + 1.0e-200) - 1.0 ) # print(diff) ax.plot( model.ages[1:], diff, self.styles[i], marker=self.markers[i], color=self.colors[i], label=model.name, ) xmax = max([max(model.ages), xmax]) xmin = min([min(model.ages[1:]), xmin]) ymax = max([max(diff), ymax]) ymin = min([min(diff), ymin]) i = i + 1 # no data to plot just return if i == 0: print("Species " + spname + " not found.") return ax.set_xlim(xmin, xmax) ax.set_ylim(ymin * 0.9, ymax * 1.1) ax.semilogx() ax.semilogy() self._dokwargs(ax, **kwargs) ax.set_xlabel(r"years") ax.set_ylabel(r" rel. diff $\mathrm{\epsilon(" + spnToLatex(spname) + ")}$") self._legend(ax) # if "title" in kwargs and kwargs["title"] != None: # ax.set_title(kwargs["title"]) return self._closefig(fig)
[docs] def plot_abunratio(self, models, spname1, spname2, **kwargs): """ Plots the ratio of species spname1 over species spname2 for all the passed models. One can also pass further arguments such as `xlim (Array)`, `ylim (Array)`, `xlog`, `ylog`, `grid`. Parameters ---------- models : array_like(:class:`prodimopy.read_mc.Data_mc`,ndim=1) list of molecular cloud models spname1 : str The name of the first species used for the ratio. spname2 : str The name of the second species used for the ratio (sp1/sp2) """ fig, ax = plt.subplots(1, 1) i = 0 xmax = 1.0e-99 xmin = 1.0e99 for model in models: if spname1 in model.species and spname2 in model.species: ratio = ( model.abundances[:, model.species.index(spname1)] / model.abundances[:, model.species.index(spname2)] ) ax.plot( model.ages, ratio, self.styles[i], marker=self.markers[i], color=self.colors[i], label=model.name, ) xmax = max([max(model.ages), xmax]) # exclude zero because of log plot # nozeros= xmin = min([min(model.ages[model.ages > 0.0]), xmin]) i = i + 1 if i == 0: print("Species " + spname1 + "and/or " + spname2 + " not found.") return ax.set_xlim(xmin, xmax) ax.semilogx() ax.semilogy() self._dokwargs(ax, **kwargs) ax.set_xlabel(r"years") ax.set_ylabel( r" $\mathrm{\epsilon(" + spnToLatex(spname1) + ")/" + r"\epsilon(" + spnToLatex(spname2) + ")}$" ) self._legend(ax) # if "title" in kwargs and kwargs["title"] != None: # ax.set_title(kwargs["title"]) return self._closefig(fig)