A collection of tools for use in the Institute of Chemical Engineering at Ulm University.
Project description
Installation
Install the package by running the following command:
pip install iciw-plots
or
pip install iciw-plots -U
Usage
Although I show the usage of the package in the context of a Jupyter notebook, the package can be used in any Python environment. Also, the style has to be used only once, at the beginning of the plotting file or notebook. In this document I write it in nearly every box just to show th use. This is not necessary!
Use of the default style
The default style defines convenient presets for the following settings:
- Font size
- Font family
- Line width
- Marker size
- Color palette
- Grid style
- Legend style
import matplotlib.pyplot as plt
import numpy as np
plt.style.use("ICIWstyle")
x = np.linspace(0, 2 * np.pi, 100)
for i in range(7):
plt.plot(x, np.sin(x + (i * (4 * np.pi / 7))), label=f"Line {i}")
plt.legend()
plt.show()
In addition to the default style, the package also provides different styles to be loaded additionally. These can be used to
- enable rendering of texts in LaTeX format by using
ICIWlatex
- disable the background when exporting the plot by using
ICIWnobg
The latex style automatically imports the LaTex packages amsmath
, amssymb
, siunitx
and mchem
enabling the use of all latex math commands, SI unit rendering and chemical formulas.
Note, How I use the style only temporarily with the contextmanager.
import matplotlib.pyplot as plt
plt.style.use("ICIWstyle")
x = np.linspace(0, 2 * np.pi, 100)
with plt.style.context(
"ICIWlatex", after_reset=False
): # use the latex style only for this plot
for i in range(7):
plt.plot(x, np.sin(x + (i * (4 * np.pi / 7))))
plt.xlabel(r"$t$ / \unit{\second}") # use latex formulae and a unit
plt.ylabel(r"$c$ / \unit{\mole\per\metre\cubed}")
plt.legend(
[
r"\ce{A}", # use chemistry symbols
r"\ce{B}",
r"\ce{AB}",
r"\ce{AB2}",
r"\ce{A2B}",
r"\ce{C2+}",
]
)
plt.show()
Sizes
The package provides default size options for the following publishers:
- ACS
- Elsevier
To make conversion between default matplotlib units (inches) and european units (cm) easier, the package provides the following conversion factors:
cm2inch
mm2inch
from ICIW_Plots.figures import Elsevier_Sizes, ACS_Sizes
from ICIW_Plots import cm2inch
print(
f"Width for Elsevier default single column wide plots:\n{Elsevier_Sizes.single_column}"
)
print(
f"Width for Elsevier default double column wide plots:\n{Elsevier_Sizes.double_column}"
)
print(
f"width for Elsevier defaultone and a half column wide plots:\n{Elsevier_Sizes.threehalf_column}"
)
print(f"Width for ACS default single column wide plots:\n{ACS_Sizes.single_column}")
print(f"Width for ACS default double column wide plots:\n{ACS_Sizes.double_column}")
fig = plt.figure(figsize=(Elsevier_Sizes.single_column["in"], 5 * cm2inch))
ax = fig.add_axes([0, 0, 1, 1])
plt.show()
Width for Elsevier default single column wide plots:
{'mm': 90, 'in': 3.54, 'cm': 9}
Width for Elsevier default double column wide plots:
{'mm': 190, 'in': 7.48, 'cm': 19}
width for Elsevier defaultone and a half column wide plots:
{'mm': 140, 'in': 5.51, 'cm': 14}
Width for ACS default single column wide plots:
{'mm': 82.55, 'in': 3.25, 'cm': 8.255}
Width for ACS default double column wide plots:
{'mm': 177.8, 'in': 7, 'cm': 17.78}
More Sizes and Axes
Oftentimes, I like to create square axis with a fixed width in the middle of a figure with fixed width. matplotlib
makes this hard for the user. ICIW-Plots
provides functions make_square_ax
, make_rect_ax
and make_square_subplots
that do this for you.
plt.style.use("ICIWstyle")
from ICIW_Plots.figures import Elsevier_Sizes
from ICIW_Plots import make_square_ax
fig = plt.figure(figsize=(Elsevier_Sizes.single_column["in"], 7 * cm2inch))
ax = make_square_ax(
fig,
ax_width=5 * cm2inch,
)
ax.plot(x, np.sin(x))
plt.show()
c:\ProgramData\Anaconda3\envs\ML3\Lib\site-packages\ICIW_Plots\layout.py:77: UserWarning: Unscientific behavior. No xlabel provided.
warnings.warn("Unscientific behavior. No xlabel provided.")
c:\ProgramData\Anaconda3\envs\ML3\Lib\site-packages\ICIW_Plots\layout.py:82: UserWarning: Unscientific behavior. No ylabel provided.
warnings.warn("Unscientific behavior. No ylabel provided.")
As you can see, you even get a warning when you misbehave. Both functions take some arguments you can inspect via the mouseover in your IDE. Note, that the kwargs
argument takes any argument, a normal plt.add_axes
function would take. Here is just an example of what you can do although it is unreasonable to do so:
from ICIW_Plots.figures import Elsevier_Sizes
from ICIW_Plots import make_square_ax
plt.style.use("ICIWstyle")
fig = plt.figure(figsize=(Elsevier_Sizes.single_column["in"], 7 * cm2inch))
ax = make_square_ax(
fig,
ax_width=5 * cm2inch,
# left_h=0.2, # These arguments control the spacing of the axis
# bottom_v=0.2, # not supplying them wil place the axes in the middle of the figure
xlabel=r"$t$ / s",
ylabel=r"$U$ / V",
title="This is a title",
xscale="log",
)
ax.plot(x, np.sin(x))
plt.show()
import matplotlib.pyplot as plt
from ICIW_Plots import make_rect_ax
plt.style.use("ICIWstyle")
fig = plt.figure()
ax = make_rect_ax(
fig,
ax_width=7.3 * cm2inch,
ax_height=5 * cm2inch,
# left_h=0.2, # These arguments control the spacing of the axis
# bottom_v=0.2, # not supplying them wil place the axes in the middle of the figure
xlabel=r"$t$ / s",
ylabel=r"$U$ / V",
title="This is a title",
xscale="log",
)
ax.plot(x, np.sin(x))
plt.show()
The make_square_subplot
command behaves slightly different whether you want the x- or y- axes to be shared and which labels you provide. The docstring sys there are the following options:
sharex, sharey : bool, optional
whether axes on top of or next to eachother share one x or y axes, by default
False
sharelabel : bool, optional
whether to share the labels of the shared axes, by default
False
xlabel, ylabel : Optional[str | npt.ArrayLike], optional
label or labels for the axes. Can be one of the following:
None
- no label- a single
str
- every subplot will get the same x/y label- a 1D
npt.ArrayLike
- every column/row will get the same x/y label- a 2D
npt.ArrayLike
- every subplot will get its own x/y labelIf
sharex
orsharey
isTrue
, only the last row/column (the shared axis) will get the label. By default None
import matplotlib.pyplot as plt
from ICIW_Plots import make_square_subplots
plt.style.use("ICIWstyle")
fig = plt.figure()
axs = make_square_subplots(
fig=fig,
ax_width=3 * cm2inch,
ax_layout=(2, 3),
h_sep=1.5 * cm2inch,
v_sep=1 * cm2inch,
sharex=True, # share the axis
sharey=True, # share the axis
sharelabel=False,
xlabel="$x$", # every x axis has the same label
ylabel=["$y_1$", "$y_2$"], # every y axis along the rows has the same label
)
fig = plt.figure()
axs = make_square_subplots(
fig=fig,
ax_width=3 * cm2inch,
ax_layout=(2, 3),
h_sep=1.5 * cm2inch,
v_sep=1 * cm2inch,
sharex=True, # share the axis
sharey=True, # share the axis
sharelabel=True, # ticklabels are not repeated for shared axis
xlabel="$x$", # every x axis has the same label
ylabel=["$y_1$", "$y_2$"], # every y axis along the rows has the same label
)
fig = plt.figure()
axs = make_square_subplots(
fig=fig,
ax_width=3 * cm2inch,
ax_layout=(2, 3),
h_sep=1.5 * cm2inch,
v_sep=1 * cm2inch,
sharex=False, # because we do not share the axis, every axis is labeled
sharey=False, # because we do not share the axis, every axis is labeled
xlabel="x", # every x axis has the same label
ylabel=["$y_1$", "$y_2$"], # every y axis along the rows has the same label
)
fig = plt.figure()
axs = make_square_subplots(
fig=fig,
ax_width=3 * cm2inch,
ax_layout=(2, 3),
h_sep=1.5 * cm2inch,
v_sep=1 * cm2inch,
sharex=True,
sharey=False,
xlabel=[
"$x_1$",
"$x_2$",
"$x_3$",
], # every x axis along one column has the same label. Because it is shared, they do not repeat.
ylabel=[
["$y_1$", "$y_2$", "$y_3$"],
["$y_4$", "$y_5$", "$y_6$"],
], # every y axis was given its own label. Only recommended for non-shared axes
)
fig = plt.figure()
axs = make_square_subplots(
fig=fig,
ax_width=3 * cm2inch,
ax_layout=(2, 3),
h_sep=1.5 * cm2inch,
v_sep=1 * cm2inch,
sharex=False, # because we do not share the axis, every axis is labeled
sharey=False, # because we do not share the axis, every axis is labeled
xlabel="x", # every x axis has the same label
ylabel=["$y_1$", "$y_2$"], # every y axis along the rows has the same label
)
In jupyter notebooks the output appears cut to the "appropriate" size. In a python script, you will see the full figure with all the sizes and positions spaced correctly.
Colors
ICIW-Plots
defines the university colors.
import matplotlib.pyplot as plt
import ICIW_Plots.colors as ICIWcolors
plt.style.use("ICIWstyle")
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), color=ICIWcolors.CRIMSON)
ax.plot(x, np.cos(x), color=ICIWcolors.CERULEAN)
ax.plot(x, np.log(x + 0.1), color=ICIWcolors.KELLYGREEN)
ax.plot(x, np.tanh(x), color=ICIWcolors.FLAME)
ax.plot(x, np.arcsinh(x), color=ICIWcolors.DRAB)
plt.legend(["crimson", "cerulean", "kellygreen", "flame", "drab"])
plt.show()
Colormaps
All university colors are available as colormaps as well. Here is just an example for the cerulean colormap:
import matplotlib.pyplot as plt
import ICIW_Plots.colors as ICIWcolors
plt.style.use("ICIWstyle")
N = 100
x = np.linspace(-3.0, 3.0, N)
y = np.linspace(-2.0, 2.0, N)
X, Y = np.meshgrid(x, y)
Z1 = -(X**2) - Y**2
Z2 = -((X * 10) ** 2) - (Y * 10) ** 2
z = Z1 + 50 * Z2
fig, ax = plt.subplots()
cs = ax.contourf(X, Y, z, cmap=ICIWcolors.cerulean_cm, levels=10)
cbar = fig.colorbar(cs)
plt.show()
Additionally, ICIW-Plots
provides a way to define "nice looking" colorschemes based on the theory of adjacent or analogous colors. You can use any color as a base and generate an appealing color scheme this way.
This works great for plots where line show an increase in, e.g. temperature.
You can either create a list of these colors or use them as a cycler via the functions adjacent_colors
or adjacent_cycler
respectively. For cyclers see the later section.
import matplotlib.pyplot as plt
import ICIW_Plots.colors as ICIWcolors
colors = ICIWcolors.adjacent_colors(
ICIWcolors.FLAME, # any valid color as an array of three values [R,G,B], here, one of our own university colors
n=5, # the number of adjacent colors you want. Must be odd.
phi=15, # the "distance" of two adjacent colors. The smaller, the more similar.
)
print(colors)
[(0.91015625, 0.02734375, 0.07031249999999899), (0.91015625, 0.20507812500000003, 0.02734375), (0.91015625, 0.42578125, 0.02734375), (0.91015625, 0.646484375, 0.02734375), (0.91015625, 0.8671875, 0.02734375)]
Cyclers
The package defines some functionality to do your own cyclers. Supported are:
- color cyclers from colormaps
- all default matplotlib colormaps by name
- all custom colormaps from
ICIW-Plots
by reference
- line style cyclers
- all default linestyles by abbreviation (
-
,--
,.-
,:
) - every custom linestyle by a dash tuple (e.g.,
(0,(3,10,1,15))
)
- all default linestyles by abbreviation (
- marker cyclers
- all predefined markers by abbreviation (
o
,s
,^
,v
,and so on) - every custom marker by a marker reference
- all predefined markers by abbreviation (
Custom color cyclers take a colormap and sample num_plots
points from them equidistantly spaced. start
and stop
are used to prevent very light or very dark colors from being used. The cycler
is then added as the axes prop_cycle
.
import matplotlib.pyplot as plt
import ICIW_Plots.cyclers as ICIW_cyclers
fig, ax = plt.subplots()
x = np.linspace(-2 * np.pi, 2 * np.pi)
my_green_cycler = ICIW_cyclers.ICIW_colormap_cycler(
"Greens",
7,
start=0.2,
)
ax.set_prop_cycle(my_green_cycler)
for i in range(7):
ax.plot(x, np.sin(x + (i * (4 * np.pi / 7))))
plt.show()
import matplotlib.pyplot as plt
import ICIW_Plots.cyclers as ICIW_cyclers
fig, ax = plt.subplots()
my_blue_cycler = ICIW_cyclers.ICIW_colormap_cycler(
ICIWcolors.cerulean_cm,
7,
start=0.1,
)
ax.set_prop_cycle(my_blue_cycler)
for i in range(7):
ax.plot(x, np.sin(x + (i * (4 * np.pi / 7))))
plt.show()
import matplotlib.pyplot as plt
import ICIW_Plots.colors as ICIWcolors
adjacent_cyc = ICIWcolors.adjacent_cycler(
np.array([224, 58, 91])
/ 256, # any valid color as an array of three values [R,G,B], here, an arbitrary color.
n=5,
phi=25,
)
fig, ax = plt.subplots()
ax.set_prop_cycle(adjacent_cyc)
T = np.linspace(400, 500, 100)
E_As = np.linspace(60000, 70000, 5)
for E_A in E_As:
ax.plot(T, 1e7 * np.exp(-E_A / 8.314 / T), label=f"$E_A$= {E_A}")
ax.set(xlabel="$T$", ylabel="$r$")
plt.legend()
plt.show()
Linestyle cyclers
Custom linestyle cyclers take a list of linestyles and a number of plots to cycle through. The cycler
is then added as the axes prop_cycle
.
my_linestyle_cycler = ICIW_cyclers.ICIW_linestyle_cycler(3)
fig, ax = plt.subplots()
ax.set_prop_cycle(my_linestyle_cycler)
for j in range(3):
ax.plot(x, x + j * 5)
Note, that all lines have the same color, since matplotlib by default cycles through its default cycler containing the colors. By overwriting the default cycler by our linestyle cycler, all lines will have the same color.
We can combine different cyclers together by either
- inner product (pairwise combinations)
- outer product (unique combinations)
fig, axs = plt.subplots(1, 2)
custom_c_cycler = ICIW_cyclers.ICIW_colormap_cycler("Greens", 3, start=0.5)
custom_l_cycler = ICIW_cyclers.ICIW_linestyle_cycler(3)
axs[0].set_title("Inner Product")
# this combination gives 3 different combinations of color and line style
# linestyle 1 and color 1, linestyle 2 and color 2, linestyle 3 and color 3
axs[0].set_prop_cycle(custom_c_cycler + custom_l_cycler)
for i in range(3):
axs[0].plot(x, np.sin(x + (i * (4 * np.pi / 5))))
axs[1].set_title("Outer Product")
# this combination gives 9 different combinations of color and line style
# linestyle 1 and color 1, linestyle 2 and color 1, linestyle 3 and color 1 and so on
axs[1].set_prop_cycle(custom_c_cycler * custom_l_cycler)
for i in range(3):
for j in range(3):
axs[1].plot(x, i * x + j * 5)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file iciw_plots-1.0.40.tar.gz
.
File metadata
- Download URL: iciw_plots-1.0.40.tar.gz
- Upload date:
- Size: 27.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.7.1 importlib_metadata/7.0.1 pkginfo/1.9.6 requests/2.31.0 requests-toolbelt/1.0.0 tqdm/4.66.2 CPython/3.10.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6711f395d71afcccd3b18ad6185b04b0c22a344029127d2022cf72c24d96431f |
|
MD5 | de3671e592c343df5a1265044f0701b3 |
|
BLAKE2b-256 | c24a691f10f1d85aeb1070228336cbf70a61514e4dff7193b44648824ad62a96 |
File details
Details for the file ICIW_Plots-1.0.40-py3-none-any.whl
.
File metadata
- Download URL: ICIW_Plots-1.0.40-py3-none-any.whl
- Upload date:
- Size: 29.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.7.1 importlib_metadata/7.0.1 pkginfo/1.9.6 requests/2.31.0 requests-toolbelt/1.0.0 tqdm/4.66.2 CPython/3.10.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 890c065cc0b0150825180a8c32063090d10dc3433609d01643d629e31a214f77 |
|
MD5 | 902b471b831903ae1caaee8ae62441db |
|
BLAKE2b-256 | 1876307951f725ea4b0c518cce85063682afd8c53aa80aa870ee960f121fafb6 |