Implementation von Texturen¶
Sowohl in Bokeh als auch in Altair können benutzerdefinierte Muster verwendet werden.
Implementation Bokeh¶
In Bokeh werden ganze Dateien geladen, deswegen muss bei Tilings dafür gesorgt werden, dass die SVG ein Rechteck enthält, dessen Maße passend zu einer Tile sind und als fill
das Pattern enthält.
Wir benötigen folgende Importe, um Bokeh zu verwenden und im Notebook anzuzeigen, um lokale Dateien verwenden zu können, müssen wir base64-codieren.
[1]:
from bokeh.io import show, output_notebook
from bokeh.plotting import figure
from bokeh.models import ImageURLTexture
from bokeh.resources import INLINE
import base64
output_notebook(resources=INLINE)
Dann definieren wir eine Liste mit den Dateinamen der SVG-Dateien:
[2]:
svg_files = [
"dotspattern.svg",
"caretpattern.svg",
"trianglepattern.svg",
"spiralpattern.svg",
"crosspattern.svg",
"diamondpattern.svg",
"squarepattern.svg",
"tristarpattern.svg"
]
Wir codieren die lokalen SVG-Dateien zu Base64-Data-URLs, dies ist für online verfügbare Dateien nicht nötig, schadet dort aber auch nicht.
[3]:
# Funktion zum Umwandeln der SVGs in Base64-URLs
def svg_to_base64(svg_path):
with open(svg_path, "rb") as svg_file:
encoded_svg = base64.b64encode(svg_file.read()).decode("utf-8")
return f"data:image/svg+xml;base64,{encoded_svg}"
# Dictionary aus Hatchpattern und SVGs erstellen
hatch_patterns = {f"pattern_{i}":
ImageURLTexture(
url=svg_to_base64("../../_static/pattern/"+svg_files[i])
) for i in range(len(svg_files))}
Farbnamen als Bezeichner der x-Achse und Beispielwerte für den Plot:
[4]:
categories = ["Purple", "Teal", "Orange", "Blue", "Red", "Cyan", "Magenta", "Green"]
values = [90, 80, 50, 55, 50, 60, 40, 80]
Nun erstellen wir den Bokeh-Plot mit einem Säulendiagramm (vbar
)
[5]:
p = figure(x_range=categories, height=400,
title="cusy Pattern Example", tools="")
p.vbar(x=categories, top=values, width=0.9,
fill_color="#75757533", # Hintergrundfarbe der Säulen
hatch_extra=hatch_patterns, # Pattern anwenden
hatch_pattern=[f"pattern_{i}" for i in range(len(categories))],
line_color=None)
[5]:
Um die SVG-Muster anzeigen zu lassen, müssen wir das SVG-Backend auswählen.
[6]:
p.output_backend="svg"
p.y_range.start=0 # Säulen auf der x-Achse beginnen lassen
p.background_fill_color = None # Hintergrundfarbe entfernen
p.border_fill_color = None # Umrandung entfernen
show(p)
Implementation Vega-Altair¶
In Altair wird direkt die pattern
-Funktionalität der SVG benutzt. Hier wird über die ID ein Pattern aus den SVG-defs
ausgewählt.
Wir benötigen die Funktion display_html
von IPython, um die SVGs inline ins HTML zu integrieren, damit wir sie später als Pattern in Altair verwenden können.
[7]:
from IPython.display import display_html
Wir definieren eine Funktion zum Einlesen und decodieren der SVG. Anschließend rufen wir die Funktion für unsere SVG auf und integrieren die Pattern in das HTML.
[8]:
def read_svg(svg_path):
with open(svg_path, "rb") as svg_file:
svg = svg_file.read().decode("utf-8")
return svg
display_html(
read_svg("../../_static/pattern/cusypattern.svg"),
raw=True
)
Wir benutzen einen pandas-Dataframe, um die Daten für Altair bereitzustellen.
[9]:
import altair as alt
import pandas as pd
# Daten definieren
data = pd.DataFrame({
"category": ["Purple", "Teal", "Orange", "Blue", "Red", "Cyan", "Magenta", "Green"],
"value": [90, 80, 50, 55, 50, 60, 40, 80],
"pattern": [
"pattern_0",
"pattern_1",
"pattern_2",
"pattern_3",
"pattern_4",
"pattern_5",
"pattern_6",
"pattern_7"
]
})
alt.Fill
-Channel benutzen wir die ID des jeweiligen SVG-Pattern, um die Füllung festzulegen.[10]:
chart = alt.Chart(data, title="cusy Pattern Example", width=600, height=400).mark_bar(stroke=None).encode(
x=alt.X("category:N",
sort=["Purple", "Teal", "Orange", "Blue", "Red", "Cyan", "Magenta", "Green"],
axis=alt.Axis(title=None, labelAngle=0)),
y=alt.Y("value:Q", axis=alt.Axis(title=None)),
fill=alt.Fill("pattern:N",
scale=alt.Scale(
range=[
"url(#dotspattern)",
"url(#caretpattern)",
"url(#trianglepattern)",
"url(#spiralpattern)",
"url(#crosspattern)",
"url(#diamondpattern)",
"url(#squarepattern)",
"url(#tristarpattern)",
]
),
legend=None)
)
[11]:
alt.renderers.set_embed_options(renderer='svg')
chart
[11]: