Skip to main content

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()

png

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()

png

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}

png

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.")

png

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()

png

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()

png

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 label

 If sharex or sharey is True, 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
)

png

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
)

png

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
)

png

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
)

png

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
)

png

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()

png

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()

png

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)))
  • marker cyclers
    • all predefined markers by abbreviation (o,s,^,v,and so on)
    • every custom marker by a marker reference

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()

png

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()

png

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()

png

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)

png

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)

png

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

iciw_plots-1.0.40.tar.gz (27.2 kB view details)

Uploaded Source

Built Distribution

ICIW_Plots-1.0.40-py3-none-any.whl (29.8 kB view details)

Uploaded Python 3

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

Hashes for iciw_plots-1.0.40.tar.gz
Algorithm Hash digest
SHA256 6711f395d71afcccd3b18ad6185b04b0c22a344029127d2022cf72c24d96431f
MD5 de3671e592c343df5a1265044f0701b3
BLAKE2b-256 c24a691f10f1d85aeb1070228336cbf70a61514e4dff7193b44648824ad62a96

See more details on using hashes here.

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

Hashes for ICIW_Plots-1.0.40-py3-none-any.whl
Algorithm Hash digest
SHA256 890c065cc0b0150825180a8c32063090d10dc3433609d01643d629e31a214f77
MD5 902b471b831903ae1caaee8ae62441db
BLAKE2b-256 1876307951f725ea4b0c518cce85063682afd8c53aa80aa870ee960f121fafb6

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page