import numpy as np
import pandas as pd
from plotnine import (
ggplot,
aes,
geom_point,
geom_path,
scale_x_continuous,
scale_y_continuous,
guides,
theme,
element_line,
element_rect,
)from mizani.transforms import trans
Guitar Neck ###
Using a transformed x-axis to visualise guitar chords
The x-axis is transformed to resemble the narrowing width of frets on a 25.5 inch Strat. To do that we create custom transformation.
The key parts of any transform object are the transform
and inverse
functions.
class frets_trans(trans):
"""
Frets Transformation
"""
= 23 # Including fret 0
number_of_frets = (0, number_of_frets - 1)
domain
@staticmethod
def transform(x):
= np.asarray(x)
x return 25.5 - (25.5 / (2 ** (x / 12)))
@staticmethod
def inverse(x):
= np.asarray(x)
x return 12 * np.log2(25.5 / (25.5 - x))
@classmethod
def breaks_(cls, limits):
# Fixed major breaks
return cls.domain
@classmethod
def minor_breaks(cls, major, limits):
# The major breaks as passed to this method are in transformed space.
# The minor breaks are calculated in data space to reveal the
# non-linearity of the scale.
= cls.inverse(major)
_major = cls.transform(np.linspace(*_major, cls.number_of_frets))
minor return minor
The above transform is different from most in that, breaks and minor breaks do not change. This is common of very specialized scales. It can also be a key requirement when creating graphics for demontration purposes.
Some chord Data
# Notes: the 0 fret is an open strum, all other frets are played half-way between fret bars.
# The strings are 1:low E, 2: A, 3: D, 4: G, 5: B, 6: E
= pd.DataFrame({"Fret": [0, 2.5, 1.5, 0, 0.5, 0], "String": [1, 2, 3, 4, 5, 6]})
c_chord
# Sequence based on the number of notes in the chord
"Sequence"] = list(range(1, 1 + len(c_chord["Fret"])))
c_chord[
# Standard markings for a Stratocaster
= pd.DataFrame(
markings
{"Fret": [2.5, 4.5, 6.5, 8.5, 11.5, 11.5, 14.5, 16.5, 18.5, 20.5],
"String": [3.5, 3.5, 3.5, 3.5, 2, 5, 3.5, 3.5, 3.5, 3.5],
} )
Visualizing the chord
# Gallery, elaborate
# Look and feel of the graphic
= "#FFDDCC"
neck_color = "#998888"
fret_color = "#AA9944"
string_color
= theme(
neck_theme =(10, 2),
figure_size=element_rect(fill=neck_color),
panel_background=element_line(color=string_color, size=2.2),
panel_grid_major_y=element_line(color=fret_color, size=2.2),
panel_grid_major_x=element_line(color=fret_color, size=1),
panel_grid_minor_x
)
("Fret", "String"))
ggplot(c_chord, aes(+ geom_path(aes(color="Sequence"), size=3)
+ geom_point(aes(color="Sequence"), fill="#FFFFFF", size=3)
+ geom_point(data=markings, fill="#000000", size=4)
+ scale_x_continuous(trans=frets_trans)
+ scale_y_continuous(breaks=range(0, 7), minor_breaks=[])
+ guides(color=False)
+ neck_theme
)
Credit: This example was motivated by Jonathan Vitale who wanted to create graphics for a guitar scale trainer.