Skip to content
Snippets Groups Projects
Commit b8bfc342 authored by Florian Zill's avatar Florian Zill
Browse files

[meshplotlib] moved cmap defaults to presets

parent 5f6e44f8
No related branches found
No related tags found
1 merge request!119Stress Analysis and Refactoring
......@@ -2,6 +2,7 @@
import types
from copy import deepcopy
from math import nextafter
from typing import Literal, Optional, Union
import numpy as np
......@@ -74,31 +75,27 @@ def get_cmap_norm(
) -> tuple[mcolors.Colormap, mcolors.Normalize]:
"""Construct a discrete colormap and norm for the property field."""
vmin, vmax = (levels[0], levels[-1])
bilinear = property.bilinear_cmap and vmin <= 0.0 <= vmax
cmap_str = setup.cmap_str(property)
if property.is_mask():
conti_cmap = mcolors.ListedColormap(cmap_str)
elif isinstance(cmap_str, list):
conti_cmap = [colormaps[c] for c in cmap_str]
else:
conti_cmap = colormaps[cmap_str]
if property.data_name == "temperature":
cool_colors = conti_cmap[0](np.linspace(0, 0.75, 128 * (vmin < 0)))
warm_colors = conti_cmap[1](np.linspace(0, 1, 128 * (vmax >= 0)))
conti_cmap = mcolors.LinearSegmentedColormap.from_list(
"temperature_cmap", np.vstack((cool_colors, warm_colors))
)
if bilinear:
vmin, vmax = np.max(np.abs([vmin, vmax])) * np.array([-1.0, 1.0])
if property.categoric:
vmin += 0.5
vmax += 0.5
conti_norm = mcolors.Normalize(vmin=vmin, vmax=vmax)
if property.bilinear_cmap:
if vmin <= 0.0 <= vmax:
vcenter = 0.0
vmin, vmax = np.max(np.abs([vmin, vmax])) * np.array([-1.0, 1.0])
else:
# only use one half of the diverging colormap
vcenter = nextafter(*sorted([vmin, vmax], reverse=(vmin <= 0.0)))
conti_norm = mcolors.TwoSlopeNorm(vcenter, vmin, vmax)
else:
conti_norm = mcolors.Normalize(vmin, vmax)
if isinstance(property.cmap, str):
continuous_cmap = colormaps[property.cmap]
else:
continuous_cmap = property.cmap
mid_levels = np.append((levels[:-1] + levels[1:]) * 0.5, levels[-1])
colors = [conti_cmap(conti_norm(m_l)) for m_l in mid_levels]
colors = [continuous_cmap(conti_norm(m_l)) for m_l in mid_levels]
cmap = mcolors.ListedColormap(colors, name="custom")
if setup.custom_cmap is not None:
cmap = setup.custom_cmap
boundaries = get_level_boundaries(levels) if property.categoric else levels
norm = mcolors.BoundaryNorm(
boundaries=boundaries, ncolors=len(boundaries), clip=True
......
......@@ -3,9 +3,7 @@
from dataclasses import dataclass
from typing import Union
from matplotlib.colors import Colormap
from ogstools.propertylib.property import Property, Scalar
from ogstools.propertylib.property import Scalar
from .plot_setup_defaults import setup_dict
......@@ -21,16 +19,6 @@ class PlotSetup:
combined_colorbar: bool
"True if all subplots share on colorbar, else each has its own colorbar."
custom_cmap: Colormap
"If provided, this colormap will be used for any plot."
cmap_dict_if_bilinear: dict
"A dictionary that maps bilinear colormaps to properties."
cmap_dict: dict
"A dictionary that maps colormaps to properties."
cmap_if_mask: list
"A list of colors corresponding to [True, False] values of masks."
default_cmap: str
"The default colormap to use."
dpi: int
"The resolution (dots per inch) for the figure."
fig_scale: float
......@@ -80,17 +68,6 @@ class PlotSetup:
embedded_region_names_color: str
"Color of the embedded region names inside the plot."
def cmap_str(self, property: Property) -> Union[str, list]:
"""Get the colormap string for a given property."""
if property.is_mask():
return self.cmap_if_mask
if property.bilinear_cmap:
if property.data_name in self.cmap_dict_if_bilinear:
return self.cmap_dict_if_bilinear[property.data_name]
elif property.data_name in self.cmap_dict:
return self.cmap_dict[property.data_name]
return self.default_cmap
@property
def rcParams_scaled(self) -> dict:
"""Get the scaled rcParams values."""
......@@ -126,11 +103,6 @@ class PlotSetup:
length=Scalar("", obj["length"][0], obj["length"][1], ""),
material_names=obj["material_names"],
combined_colorbar=obj["combined_colorbar"],
custom_cmap=obj["custom_cmap"],
cmap_dict=obj["cmap_dict"],
cmap_dict_if_bilinear=obj["cmap_dict_if_bilinear"],
cmap_if_mask=obj["cmap_if_mask"],
default_cmap=obj["default_cmap"],
rcParams=obj["rcParams"],
)
......
......@@ -31,19 +31,6 @@ setup_dict = {
"y_label": None,
"log_scaled": False,
"combined_colorbar": True,
"custom_cmap": None,
"cmap_dict": {
"displacement": "Greens",
"temperature": "plasma",
"pressure": "Blues",
"velocity": "coolwarm",
"MaterialIDs": "tab20",
},
"cmap_dict_if_bilinear": {
"displacement": "PRGn",
"temperature": ["Blues", "plasma"],
},
"cmap_if_mask": ["lightgrey", "green"],
"rcParams": {
"font.weight": "normal",
"font.family": "sans-serif",
......
"Definitions of custom colormaps."
import numpy as np
from matplotlib import colormaps
from matplotlib.colors import LinearSegmentedColormap as LSC
mask_cmap = LSC.from_list("mask_cmap", ["lightgrey", "g"])
temperature_cmap = LSC.from_list(
"temperature_cmap",
np.r_[
colormaps["Blues"](np.linspace(0, 0.75, 128, endpoint=True)),
colormaps["plasma"](np.linspace(0, 1, 128, endpoint=True)),
],
)
......@@ -6,23 +6,25 @@ from typing import Optional
from . import vector2scalar as v2s
from .property import Matrix, Property, Scalar, Vector
from .custom_colormaps import temperature_cmap
T_mask = "temperature_active"
H_mask = "pressure_active"
M_mask = "displacement_active"
# fmt: off
material_id = Scalar("MaterialIDs", categoric=True)
displacement = Vector("displacement", "m", "m", mask=M_mask)
material_id = Scalar("MaterialIDs", categoric=True, cmap="tab20")
displacement = Vector("displacement", "m", "m", mask=M_mask, cmap="PRGn")
effective_pressure = Scalar("sigma", "Pa", "MPa", "effective_pressure", M_mask, v2s.effective_pressure)
heatflowrate = Scalar("HeatFlowRate", mask=T_mask)
massflowrate = Scalar("MassFlowRate", mask=H_mask)
nodal_forces = Vector("NodalForces", mask=M_mask)
pressure = Scalar("pressure", "Pa", "MPa", "pore_pressure", H_mask)
hydraulic_height = Scalar("pressure", "m", "m", "hydraulic_height", H_mask)
pressure = Scalar("pressure", "Pa", "MPa", "pore_pressure", H_mask, cmap="Blues")
hydraulic_height = Scalar("pressure", "m", "m", "hydraulic_height", H_mask, cmap="Blues")
qp_ratio = Scalar("sigma", "Pa", "percent", "QP_ratio", M_mask, v2s.qp_ratio)
strain = Matrix("epsilon", "", "percent", "strain", M_mask)
stress = Matrix("sigma", "Pa", "MPa", "stress", M_mask)
temperature = Scalar("temperature", "K", "°C", mask=T_mask, bilinear_cmap=True)
temperature = Scalar("temperature", "K", "°C", mask=T_mask, cmap=temperature_cmap, bilinear_cmap=True)
velocity = Vector("velocity", "m/s", "m/s", "darcy_velocity", H_mask)
von_mises_stress = Scalar("sigma", "Pa", "MPa", "von_Mises_stress", M_mask, v2s.von_mises)
# fmt: on
......
......@@ -9,8 +9,10 @@ from dataclasses import dataclass, replace
from typing import Any, Callable, Union
import numpy as np
from matplotlib.colors import Colormap
from pint.facets.plain import PlainQuantity
from .custom_colormaps import mask_cmap
from .unit_registry import u_reg
from .utils import identity, sym_tensor_to_mat
from .vector2scalar import trace
......@@ -39,6 +41,8 @@ class Property:
Callable[[Any], Any],
] = identity
"""The function to be applied on the data."""
cmap: Union[Colormap, str] = "coolwarm"
"""Colormap to use for plotting."""
bilinear_cmap: bool = False
"""Should this property be displayed with a bilinear cmap?"""
categoric: bool = False
......@@ -113,7 +117,9 @@ class Property:
"""
:returns: A property representing this properties mask.
"""
return Property(data_name=self.mask, mask=self.mask, categoric=True)
return Property(
data_name=self.mask, mask=self.mask, categoric=True, cmap=mask_cmap
)
@property
def magnitude(self) -> "Property":
......@@ -149,6 +155,7 @@ class Vector(Property):
output_name=self.output_name + f"_{suffix[0 <= index <= 2]}",
mask=self.mask,
func=lambda x: np.array(x)[..., index],
cmap=self.cmap,
bilinear_cmap=True,
)
......@@ -162,6 +169,7 @@ class Vector(Property):
output_name=self.output_name + "_magnitude",
mask=self.mask,
func=lambda x: np.linalg.norm(x, axis=-1),
cmap=self.cmap,
)
@property
......@@ -172,6 +180,7 @@ class Vector(Property):
output_name=self.output_name + "_log10",
mask=self.mask,
func=lambda x: np.log10(np.linalg.norm(x, axis=-1)),
cmap=self.cmap,
)
......@@ -200,6 +209,7 @@ class Matrix(Property):
mask=self.mask,
func=lambda x: np.array(x)[..., index],
bilinear_cmap=True,
cmap=self.cmap,
)
@property
......@@ -212,6 +222,7 @@ class Matrix(Property):
output_name=self.output_name + "_magnitude",
mask=self.mask,
func=lambda x: np.linalg.norm(sym_tensor_to_mat(x), axis=(-2, -1)),
cmap=self.cmap,
)
@property
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment