Themes¶
This section showcases the existing themes found in the datachart.themes module.
Let's start by importing the necessary functions to help us work with the datachart.themes module.
import random
import numpy as np
from datachart.charts import (
BarChart,
BoxPlot,
Heatmap,
Histogram,
LineChart,
ParallelCoords,
ScatterChart,
)
from datachart.constants import VALFMT, FIG_SIZE, LINE_STYLE, SHOW_GRID
from datachart.config import config
To get the supported themes, you have to load them from the datachart.themes module.
from datachart.constants import THEME
The datachart.constants.THEME module contains all the predefined themes.
Default Theme¶
The THEME.DEFAULT is the theme, that the user will by default see when using the datachart package. To use it, no additional configuration is required.
In case if the user uses a different theme, or if they change it by hand using the config module, the default theme will be reset in the following way:
# reset the config to the default theme
config.reset_config()
# explicity set the default theme
config.set_theme(THEME.DEFAULT)
Bar Chart
_ = BarChart(
data=[
{"label": f"xx{id}", "y": 100 * (id + 1) * random.random()}
for id in range(10)
],
vlines=[{"x": 2 * i} for i in range(1, 4)],
hlines={"y": 400},
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
xmin=-0.5,
xmax=9.5,
)
Box Plot
_ = BoxPlot(
data=[
{"label": f"Group {chr(65 + cat_id)}", "value": random.gauss(50 + cat_id * 10, 15)}
for cat_id in range(5)
for _ in range(50)
],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_REGULAR,
)
Heatmap
_ = Heatmap(
data=[[x + y for x in range(8)] for y in range(8)],
valfmt=VALFMT.DECIMAL,
xticks=[idx for idx in range(8)],
xticklabels=[f"xxx{idx}" for idx in range(8)],
xtickrotate=45,
yticks=[idx for idx in range(8)],
yticklabels=[f"xxx{idx}" for idx in range(8)],
ytickrotate=0,
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.SQUARE_SMALL,
show_heatmap_values=True,
show_colorbars=True,
)
Histogram
_ = Histogram(
data=[
[{"x": 100 * idx * random.random()} for idx in range(100)]
for _ in range(2)
],
subtitle=[f"Histogram {id}" for id in range(2)],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.Y,
show_legend=True,
num_bins=40,
)
Line Chart
_ = LineChart(
data=[
[{"x": x / 10, "y": np.cos(x / 2)} for x in range(21)],
[{"x": x / 10, "y": np.sin(x / 2)} for x in range(21)],
],
subtitle=["cosine", "sine"],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
show_legend=True,
)
Parallel Coordinate Plot
# Simulate Iris-like data with three species
iris_data = []
# Setosa: smaller petals, medium sepals
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(5.0, 0.35),
"sepal_width": random.gauss(3.4, 0.38),
"petal_length": random.gauss(1.5, 0.17),
"petal_width": random.gauss(0.2, 0.1),
"species": "setosa"
})
# Versicolor: medium everything
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(5.9, 0.52),
"sepal_width": random.gauss(2.8, 0.31),
"petal_length": random.gauss(4.3, 0.47),
"petal_width": random.gauss(1.3, 0.2),
"species": "versicolor"
})
# Virginica: larger everything
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(6.6, 0.64),
"sepal_width": random.gauss(3.0, 0.32),
"petal_length": random.gauss(5.5, 0.55),
"petal_width": random.gauss(2.0, 0.27),
"species": "virginica"
})
_ = ParallelCoords(
data=iris_data,
hue="species",
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_REGULAR,
show_legend=True,
)
Scatter Chart
chart_data_bubble_hue = [
{
"x": random.uniform(0, 10),
"y": random.uniform(0, 10),
"population": random.uniform(100, 1000),
"region": random.choice(["North", "South", "East", "West"])
}
for _ in range(50)
]
_ = ScatterChart(
data=chart_data_bubble_hue,
size="population",
hue="region",
size_range=(30, 250),
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
show_legend=True,
)
Greyscale Theme¶
The THEME.GREYSCALE is designed to be monochrome and is suitable for printing. It is also used for some journals, which require a monochrome theme.
To use the theme, simply run the following code:
config.set_theme(THEME.GREYSCALE)
What follows is a showcase of charts in the greyscale theme.
Bar Chart
_ = BarChart(
data=[
{"label": f"xx{id}", "y": 100 * (id + 1) * random.random()}
for id in range(10)
],
vlines=[{"x": 2 * i} for i in range(1, 4)],
hlines={"y": 400},
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
xmin=-0.5,
xmax=9.5,
)
Box Plot
_ = BoxPlot(
data=[
{"label": f"Group {chr(65 + cat_id)}", "value": random.gauss(50 + cat_id * 10, 15)}
for cat_id in range(5)
for _ in range(50)
],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_REGULAR,
)
Heatmap
_ = Heatmap(
data=[[x + y for x in range(8)] for y in range(8)],
valfmt=VALFMT.DECIMAL,
xticks=[idx for idx in range(8)],
xticklabels=[f"xxx{idx}" for idx in range(8)],
xtickrotate=45,
yticks=[idx for idx in range(8)],
yticklabels=[f"xxx{idx}" for idx in range(8)],
ytickrotate=0,
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.SQUARE_SMALL,
show_heatmap_values=True,
show_colorbars=True,
)
Histogram
_ = Histogram(
data=[
[{"x": 100 * idx * random.random()} for idx in range(100)]
for _ in range(2)
],
subtitle=[f"Histogram {id}" for id in range(2)],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.Y,
show_legend=True,
num_bins=40,
)
Line Chart
_ = LineChart(
data=[
[{"x": x / 10, "y": np.cos(x / 2)} for x in range(21)],
[{"x": x / 10, "y": np.sin(x / 2)} for x in range(21)],
],
subtitle=["cosine", "sine"],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
show_legend=True,
)
Parallel Coordinate Plot
# Simulate Iris-like data with three species
iris_data = []
# Setosa: smaller petals, medium sepals
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(5.0, 0.35),
"sepal_width": random.gauss(3.4, 0.38),
"petal_length": random.gauss(1.5, 0.17),
"petal_width": random.gauss(0.2, 0.1),
"species": "setosa"
})
# Versicolor: medium everything
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(5.9, 0.52),
"sepal_width": random.gauss(2.8, 0.31),
"petal_length": random.gauss(4.3, 0.47),
"petal_width": random.gauss(1.3, 0.2),
"species": "versicolor"
})
# Virginica: larger everything
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(6.6, 0.64),
"sepal_width": random.gauss(3.0, 0.32),
"petal_length": random.gauss(5.5, 0.55),
"petal_width": random.gauss(2.0, 0.27),
"species": "virginica"
})
_ = ParallelCoords(
data=iris_data,
hue="species",
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_REGULAR,
show_legend=True,
)
Scatter Chart
chart_data_bubble_hue = [
{
"x": random.uniform(0, 10),
"y": random.uniform(0, 10),
"population": random.uniform(100, 1000),
"region": random.choice(["North", "South", "East", "West"])
}
for _ in range(50)
]
_ = ScatterChart(
data=chart_data_bubble_hue,
size="population",
hue="region",
size_range=(30, 250),
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
show_legend=True,
)
Publication Theme¶
The THEME.PUBLICATION is the theme, that the user might want to use when creating charts for publication to a paper.
# explicity set the default theme
config.set_theme(THEME.PUBLICATION)
What follows is a showcase of charts in the publication theme.
Bar Chart
_ = BarChart(
data=[
{"label": f"xx{id}", "y": 100 * (id + 1) * random.random()}
for id in range(10)
],
vlines=[{"x": 2 * i} for i in range(1, 4)],
hlines={"y": 400},
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
xmin=-0.5,
xmax=9.5,
)
Box Plot
_ = BoxPlot(
data=[
{"label": f"Group {chr(65 + cat_id)}", "value": random.gauss(50 + cat_id * 10, 15)}
for cat_id in range(5)
for _ in range(50)
],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_REGULAR,
)
Heatmap
_ = Heatmap(
data=[[x + y for x in range(8)] for y in range(8)],
valfmt=VALFMT.DECIMAL,
xticks=[idx for idx in range(8)],
xticklabels=[f"xxx{idx}" for idx in range(8)],
xtickrotate=45,
yticks=[idx for idx in range(8)],
yticklabels=[f"xxx{idx}" for idx in range(8)],
ytickrotate=0,
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.SQUARE_SMALL,
show_heatmap_values=True,
show_colorbars=True,
)
Histogram
_ = Histogram(
data=[
[{"x": 100 * idx * random.random()} for idx in range(100)]
for _ in range(2)
],
subtitle=[f"Histogram {id}" for id in range(2)],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.Y,
show_legend=True,
num_bins=40,
)
Line Chart
_ = LineChart(
data=[
[{"x": x / 10, "y": np.cos(x / 2)} for x in range(21)],
[{"x": x / 10, "y": np.sin(x / 2)} for x in range(21)],
],
subtitle=["cosine", "sine"],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
show_legend=True,
)
Parallel Coordinate Plot
# Simulate Iris-like data with three species
iris_data = []
# Setosa: smaller petals, medium sepals
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(5.0, 0.35),
"sepal_width": random.gauss(3.4, 0.38),
"petal_length": random.gauss(1.5, 0.17),
"petal_width": random.gauss(0.2, 0.1),
"species": "setosa"
})
# Versicolor: medium everything
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(5.9, 0.52),
"sepal_width": random.gauss(2.8, 0.31),
"petal_length": random.gauss(4.3, 0.47),
"petal_width": random.gauss(1.3, 0.2),
"species": "versicolor"
})
# Virginica: larger everything
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(6.6, 0.64),
"sepal_width": random.gauss(3.0, 0.32),
"petal_length": random.gauss(5.5, 0.55),
"petal_width": random.gauss(2.0, 0.27),
"species": "virginica"
})
_ = ParallelCoords(
data=iris_data,
hue="species",
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_REGULAR,
show_legend=True,
)
Scatter Chart
chart_data_bubble_hue = [
{
"x": random.uniform(0, 10),
"y": random.uniform(0, 10),
"population": random.uniform(100, 1000),
"region": random.choice(["North", "South", "East", "West"])
}
for _ in range(50)
]
_ = ScatterChart(
data=chart_data_bubble_hue,
size="population",
hue="region",
size_range=(30, 250),
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
show_legend=True,
)
Creating Your Own Theme¶
Adding the theme to the datachart package
If you think the theme would be useful and would like it to be added to the datachart package, please create a pull request to add it.
The user can create their own theme by defining a new dictionary that has the same structure as the StyleAttrs type.
For instance, one can copy the bellow definition of the default theme and modify the values to customize the theme.
from datachart.typings import StyleAttrs
from datachart.constants import COLORS, FONT_STYLE, FONT_WEIGHT, LINE_DRAW_STYLE
CUSTOM_THEME: StyleAttrs = {
"color_general_singular": COLORS.Blues,
"color_general_multiple": COLORS.Spectral,
"font_general_family": "sans-serif",
"font_general_sansserif": ["Helvetica", "Arial"],
"font_general_color": "#000000",
"font_general_size": 11,
"font_general_style": FONT_STYLE.NORMAL,
"font_general_weight": FONT_WEIGHT.NORMAL,
"font_title_size": 12,
"font_title_color": "#000000",
"font_title_style": FONT_STYLE.NORMAL,
"font_title_weight": FONT_WEIGHT.NORMAL,
"font_subtitle_size": 11,
"font_subtitle_color": "#000000",
"font_subtitle_style": FONT_STYLE.NORMAL,
"font_subtitle_weight": FONT_WEIGHT.NORMAL,
"font_xlabel_size": 10,
"font_xlabel_color": "#000000",
"font_xlabel_style": FONT_STYLE.NORMAL,
"font_xlabel_weight": FONT_WEIGHT.NORMAL,
"font_ylabel_size": 10,
"font_ylabel_color": "#000000",
"font_ylabel_style": FONT_STYLE.NORMAL,
"font_ylabel_weight": FONT_WEIGHT.NORMAL,
"axes_spines_top_visible": True,
"axes_spines_right_visible": True,
"axes_spines_bottom_visible": True,
"axes_spines_left_visible": True,
"axes_spines_width": 0.5,
"axes_spines_zorder": 100,
"axes_ticks_length": 2,
"axes_ticks_label_size": 9,
"plot_legend_shadow": False,
"plot_legend_frameon": True,
"plot_legend_alignment": "left",
"plot_legend_font_size": 9,
"plot_legend_title_size": 10,
"plot_legend_label_color": "#000000",
"plot_area_alpha": 0.3,
"plot_area_color": None,
"plot_area_linewidth": 0,
"plot_area_hatch": None,
"plot_area_zorder": 3,
"plot_grid_alpha": 1,
"plot_grid_color": "#E6E6E6",
"plot_grid_linewidth": 0.5,
"plot_grid_linestyle": LINE_STYLE.SOLID,
"plot_grid_zorder": 0,
"plot_line_color": None,
"plot_line_style": LINE_STYLE.SOLID,
"plot_line_marker": None,
"plot_line_width": 1,
"plot_line_alpha": 1.0,
"plot_line_drawstyle": LINE_DRAW_STYLE.DEFAULT,
"plot_line_zorder": 3,
"plot_bar_color": None,
"plot_bar_alpha": 1.0,
"plot_bar_width": 0.8,
"plot_bar_zorder": 3,
"plot_bar_hatch": None,
"plot_bar_edge_width": 0.5,
"plot_bar_edge_color": "#000000",
"plot_bar_error_color": "#000000",
"plot_hist_color": None,
"plot_hist_alpha": 1.0,
"plot_hist_zorder": 3,
"plot_hist_fill": None,
"plot_hist_hatch": None,
"plot_hist_type": "bar",
"plot_hist_align": "mid",
"plot_hist_edge_width": 0.5,
"plot_hist_edge_color": "#000000",
"plot_vline_color": None,
"plot_vline_style": LINE_STYLE.SOLID,
"plot_vline_width": 1,
"plot_vline_alpha": 1.0,
"plot_hline_color": None,
"plot_hline_style": LINE_STYLE.SOLID,
"plot_hline_width": 1,
"plot_hline_alpha": 1.0,
"plot_heatmap_cmap": COLORS.Blues,
"plot_heatmap_alpha": 1.0,
"plot_heatmap_font_size": 9,
"plot_heatmap_font_color": "#000000",
"plot_heatmap_font_style": FONT_STYLE.NORMAL,
"plot_heatmap_font_weight": FONT_WEIGHT.NORMAL,
}
Once you define the theme, you can use it by updating the config module in the following way:
from datachart.config import config
config.update_config(CUSTOM_THEME)
Once you do this, all the plots will use the custom theme.
Bar Chart
_ = BarChart(
data=[
{"label": f"xx{id}", "y": 100 * (id + 1) * random.random()}
for id in range(10)
],
vlines=[{"x": 2 * i} for i in range(1, 4)],
hlines={"y": 400},
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
xmin=-0.5,
xmax=9.5,
)
Box Plot
_ = BoxPlot(
data=[
{"label": f"Group {chr(65 + cat_id)}", "value": random.gauss(50 + cat_id * 10, 15)}
for cat_id in range(5)
for _ in range(50)
],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_REGULAR,
)
Heatmap
_ = Heatmap(
data=[[x + y for x in range(8)] for y in range(8)],
valfmt=VALFMT.DECIMAL,
xticks=[idx for idx in range(8)],
xticklabels=[f"xxx{idx}" for idx in range(8)],
xtickrotate=45,
yticks=[idx for idx in range(8)],
yticklabels=[f"xxx{idx}" for idx in range(8)],
ytickrotate=0,
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.SQUARE_SMALL,
show_heatmap_values=True,
show_colorbars=True,
)
Histogram
_ = Histogram(
data=[
[{"x": 100 * idx * random.random()} for idx in range(100)]
for _ in range(2)
],
subtitle=[f"Histogram {id}" for id in range(2)],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.Y,
show_legend=True,
num_bins=40,
)
Line Chart
_ = LineChart(
data=[
[{"x": x / 10, "y": np.cos(x / 2)} for x in range(21)],
[{"x": x / 10, "y": np.sin(x / 2)} for x in range(21)],
],
subtitle=["cosine", "sine"],
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
show_legend=True,
)
Parallel Coordinate Plot
# Simulate Iris-like data with three species
iris_data = []
# Setosa: smaller petals, medium sepals
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(5.0, 0.35),
"sepal_width": random.gauss(3.4, 0.38),
"petal_length": random.gauss(1.5, 0.17),
"petal_width": random.gauss(0.2, 0.1),
"species": "setosa"
})
# Versicolor: medium everything
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(5.9, 0.52),
"sepal_width": random.gauss(2.8, 0.31),
"petal_length": random.gauss(4.3, 0.47),
"petal_width": random.gauss(1.3, 0.2),
"species": "versicolor"
})
# Virginica: larger everything
for _ in range(30):
iris_data.append({
"sepal_length": random.gauss(6.6, 0.64),
"sepal_width": random.gauss(3.0, 0.32),
"petal_length": random.gauss(5.5, 0.55),
"petal_width": random.gauss(2.0, 0.27),
"species": "virginica"
})
_ = ParallelCoords(
data=iris_data,
hue="species",
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_REGULAR,
show_legend=True,
)
Scatter Chart
chart_data_bubble_hue = [
{
"x": random.uniform(0, 10),
"y": random.uniform(0, 10),
"population": random.uniform(100, 1000),
"region": random.choice(["North", "South", "East", "West"])
}
for _ in range(50)
]
_ = ScatterChart(
data=chart_data_bubble_hue,
size="population",
hue="region",
size_range=(30, 250),
title="Title",
xlabel="the global x-axis label",
ylabel="the global y-axis label",
figsize=FIG_SIZE.A4_NARROW,
show_grid=SHOW_GRID.BOTH,
show_legend=True,
)