import matplotlib.pyplot as plt
[docs]class Plots:
"""
Class that contains all the methods to plot a Phydrus Model.
Parameters
----------
ml: phydrus.Model
Phydrus Model Instance to connect the methods to the model.
Examples
--------
>>> ml.plots.profile()
"""
[docs] def __init__(self, ml):
self.ml = ml
[docs] def profile(self, figsize=(3, 6), title=None, cmap="YlOrBr",
color_by="Ks", show_grid=True, **kwargs):
"""
Method to plot the soil profile.
Parameters
----------
figsize: tuple, optional
Tuple with the size of the figure in inches.
title: str, optional
String with the title of the Figure.
cmap: str, optional
String with a named Matplotlib colormap.
color_by: str, optional
Column from the material properties sed to color the materials.
Default is "Ks".
show_grid: bool, optional
Show the grid in the plot. Default is True.
Returns
-------
ax: matplotlib axes instance
"""
_, ax = plt.subplots(figsize=figsize, **kwargs)
top = self.ml.profile.loc[:, "x"].max()
w = self.ml.profile.loc[:, "h"].max()
w = w + 0.2 * w
# Set colors by color_by
col = self.ml.materials["water"][color_by]
col = (col - col.min()) / (col.max() - col.min())
colors = plt.cm.get_cmap(cmap, 7)(col.values)
if show_grid:
edgecolor = "darkgray"
else:
edgecolor = None
for i in self.ml.profile.index[1:]:
bot = self.ml.profile.loc[i, "x"]
h = bot - top
color = colors[self.ml.profile.loc[i, "Mat"] - 1]
patch = plt.Rectangle(xy=(0, top), width=w, height=h, linewidth=1,
edgecolor=edgecolor, facecolor=color)
ax.add_patch(patch)
top = bot
line = ax.plot(self.ml.profile.loc[:, ["h"]].values,
self.ml.profile.loc[:, ["x"]].values,
label="Initial head")
ax.set_xlim(0, w)
ax.set_ylim(self.ml.profile.loc[:, "x"].min(),
self.ml.profile.loc[:, "x"].max())
ax.set_xlabel(f"h [{self.ml.basic_info['LUnit']}]")
ax.set_ylabel(f"depth [{self.ml.basic_info['LUnit']}]")
if title is not None:
ax.set_title(title)
legend_elements = [line[0]]
for i, color in enumerate(colors):
legend_elements.append(plt.Rectangle((0, 0), 0, 0, color=color,
label=f"material {i}"))
plt.legend(handles=legend_elements, loc="best")
plt.tight_layout()
return ax
[docs] def water_flow(self, data="Potential Surface Flux", figsize=(6, 3),
**kwargs):
"""
Method to plot the water flow information.
Parameters
----------
data: str, optional
String with the variable of the water flow information to plot.
You can choose between: "Potential Surface Flux",
"Potential Root Water Uptake", "Actual Surface Flux",
"Actual Root Water Uptake", "Bottom Flux",
"Pressure head at the soil surface",
"Mean value of the pressure head over the region",
"Pressure head at the Bottom of the soil profile",
"Surface runoff", "Volume of water in the entire flow domain".
Default is "Potential Surface Flux".
figsize: tuple, optional
Returns
-------
ax: matplotlib axes instance
"""
col_names = ("Potential Surface Flux", "Potential Root Water Uptake",
"Actual Surface Flux", "Actual Root Water Uptake",
"Bottom Flux", "Pressure head at the soil surface",
"Mean value of the pressure head over the region",
"Pressure head at the Bottom of the soil profile",
"Surface runoff",
"Volume of water in the entire flow domain")
cols = ("rTop", "rRoot", "vTop", "vRoot", "vBot", "hTop", "hRoot",
"hBot", "RunOff", "Volume")
df = self.ml.read_tlevel()
col = col_names.index(data)
if col < 5:
_, axes = plt.subplots(1, 2, figsize=figsize, **kwargs)
df.plot(y=cols[col], ax=axes[0], use_index=True)
axes[0].set_ylabel(data)
axes[0].set_xlabel(f"Time [{self.ml.basic_info['TUnit']}]")
# Cumulative sum
df.plot(y=f"sum({cols[col]})", ax=axes[1], use_index=True)
axes[1].set_ylabel(f"Cum. {data}")
axes[1].set_xlabel(f"Time [{self.ml.basic_info['TUnit']}]")
else:
_, axes = plt.subplots(1, 1, figsize=figsize, **kwargs)
axes.plot(df.index, df[cols[col]])
axes.set_ylabel(data)
axes.set_xlabel(f"Time [{self.ml.basic_info['TUnit']}]")
plt.tight_layout()
return axes
[docs] def soil_properties(self, data="Water Content", figsize=(6, 3), **kwargs):
"""
Method to plot the soil hydraulic properties.
Parameters
----------
data: str, optional
String with the variable of the water flow information to plot.
You can choose between: "Water Content", "Pressure head",
"log Pressure head", "Hydraulic Capacity", "Hydraulic
Conductivity", "log Hydraulic Conductivity", "Effective Water
Content". Default is "Water Content".
figsize: tuple, optional
Returns
-------
axes: matplotlib axes instance
"""
col_names = ("Water Content", "Pressure head", "log Pressure head",
"Hydraulic Capacity", "Hydraulic Conductivity",
"log Hydraulic Conductivity", "Effective Water Content")
cols = ("theta", "h", "log_h", "C", "K", "log_K", "S", "Kv")
col = col_names.index(data)
dfs = self.ml.read_i_check()
_, axes = plt.subplots(figsize=figsize, nrows=1, ncols=2,
sharey=True, **kwargs)
for i, df in dfs.items():
name = f"Node {i}"
df.plot(x="h", y=cols[col], ax=axes[0], label=name)
df.plot(x="log_h", y=cols[col], ax=axes[1], label=name)
axes[0].set_xlabel(xlabel="h")
axes[1].set_xlabel(xlabel="log_h")
axes[0].set_ylabel(cols[col])
return axes
[docs] def obs_points(self, data="h", figsize=(4, 3), **kwargs):
"""
Method to plot the pressure heads, water contents and water fluxes.
Parameters
----------
data: str, optional
String with the variable of the variable to plot.
You can choose between: "h", "theta", "Temp", "Conc".
figsize: tuple, optional
Returns
-------
axes: matplotlib axes instance
"""
dfs = self.ml.read_obs_node()
_, ax = plt.subplots(figsize=figsize, **kwargs)
for i, df in dfs.items():
df.plot(y=data, ax=ax, label=f"Node {i}", use_index=True)
ax.set_xlabel(f"Time [{self.ml.basic_info['TUnit']}]")
ax.set_ylabel(data)
return ax