Tension plot

Contents

Tension plot#

In this example, we plot the tension of D’Addario plain steel and phosphor bronze guitar strings as a function of pitch for a scale length of 25.4” (e.g. Martin Dreadnought, OM).

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from pyabc2 import Pitch

from stringcalc.tension import load_daddario_data

Hide code cell output

abcjs loaded

Load data#

df = (
    load_daddario_data()
    .query("group_id in ['PL', 'PB']")
    [["id", "uw", "group_id"]]
)
df

Hide code cell output

id uw group_id
0 PL007 0.000011 PL
1 PL008 0.000014 PL
2 PL0085 0.000016 PL
3 PL009 0.000018 PL
4 PL0095 0.00002 PL
5 PL010 0.000022 PL
6 PL0105 0.000024 PL
7 PL011 0.000027 PL
8 PL0115 0.000029 PL
9 PL012 0.000032 PL
10 PL013 0.000037 PL
11 PL0135 0.00004 PL
12 PL014 0.000043 PL
13 PL015 0.00005 PL
14 PL016 0.000057 PL
15 PL017 0.000064 PL
16 PL018 0.000072 PL
17 PL019 0.00008 PL
18 PL020 0.000089 PL
19 PL022 0.000107 PL
20 PL024 0.000128 PL
21 PL026 0.00015 PL
134 PB020 0.000081 PB
135 PB021 0.000089 PB
136 PB022 0.000099 PB
137 PB023 0.000108 PB
138 PB024 0.000117 PB
139 PB025 0.000127 PB
140 PB026 0.000136 PB
141 PB027 0.000148 PB
142 PB029 0.000174 PB
143 PB030 0.000187 PB
144 PB032 0.00021 PB
145 PB034 0.000239 PB
146 PB035 0.000254 PB
147 PB036 0.000268 PB
148 PB039 0.000311 PB
149 PB042 0.000367 PB
150 PB045 0.000418 PB
151 PB047 0.000453 PB
152 PB049 0.000492 PB
153 PB052 0.000552 PB
154 PB053 0.00057 PB
155 PB056D 0.000635 PB
156 PB059 0.000705 PB
157 PB060 0.00073 PB
158 PB062 0.000777 PB
159 PB064 0.000828 PB
160 PB066 0.000877 PB
161 PB070 0.000968 PB

Plot#

# Compute range of freqs
pitches = [
    Pitch(v)
    for v in range(
        Pitch.from_name("C2").value,
        Pitch.from_name("B4").value + 1
    )
]
F = np.array([p.etf for p in pitches])

# Pitch labels, naturals only
xticks = []
xticklabels = []
for i, p in enumerate(pitches):
    pc = p.to_pitch_class()
    if pc.isnat:
        xticks.append(i)
        xticklabels.append(p.unicode())

L = 25.4

fig, ax = plt.subplots(figsize=(10, 5.5))

# PL - Plain Steel
df_ = df[df.group_id == "PL"]
colors = plt.cm.gray_r(np.linspace(0.15, 0.8, len(df_)))
for row, c in zip(df_.itertuples(), colors):
    UW = row.uw
    T = UW * (2 * L * F) ** 2 / 386.09
    ax.plot(T, label=row.id, c=c)

# PB - Phosphor Bronze
df_ = df[df.group_id == "PB"]
colors = plt.cm.copper_r(np.linspace(0.05, 0.7, len(df_)))
for row, c in zip(df_.itertuples(), colors):
    UW = row.uw
    T = UW * (2 * L * F) ** 2 / 386.09
    ax.plot(T, label=row.id, c=c)

ax.set_xticks(xticks)
ax.set_xticklabels(xticklabels)
ax.autoscale(axis="x", tight=True)
ax.grid()
ax.set_ylabel("Tension [lbf]")
ax.set_ylim((0, 30))
# ax.set_ylim((0.3, 40)); ax.set_yscale("log")

ax.legend(ncol=2, fontsize=9, bbox_to_anchor=(1.01, 0.5), loc="center left")

ax.text(
    0.96,
    0.06,
    f"$L = {L}$ in",
    va="bottom",
    ha="right",
    transform=ax.transAxes,
    bbox=dict(boxstyle="round", facecolor="0.85", alpha=0.8),
)

fig.tight_layout()

# fig.savefig("daddario-guitar-tension.png", transparent=True, dpi=200, bbox_inches="tight")
../_images/f61af2928eb01bdecda102f241481b413f3ce111a4038e07a70fe0774de9c35d.png

👆 Note the considerable region of overlap between the heavier plain steel and lighter phosphor bronze strings.