Notes#
Show imports
import os
import dimcat as dc
import ms3
import pandas as pd
import plotly.express as px
from dimcat import filters, plotting
import utils
pd.set_option("display.max_rows", 1000)
pd.set_option("display.max_columns", 500)
Show source
RESULTS_PATH = os.path.abspath(os.path.join(utils.OUTPUT_FOLDER, "notes_stats"))
os.makedirs(RESULTS_PATH, exist_ok=True)
def make_output_path(
filename: str,
extension=None,
path=RESULTS_PATH,
) -> str:
return utils.make_output_path(filename=filename, extension=extension, path=path)
def save_figure_as(
fig, filename, formats=("png", "pdf"), directory=RESULTS_PATH, **kwargs
):
if formats is not None:
for fmt in formats:
plotting.write_image(fig, filename, directory, format=fmt, **kwargs)
else:
plotting.write_image(fig, filename, directory, **kwargs)
Loading data
Show source
D = utils.get_dataset("couperin_clavecin", corpus_release="v2.4")
package = D.inputs.get_package()
package_info = package._package.custom
git_tag = package_info.get("git_tag")
utils.print_heading("Data and software versions")
print("François Couperin – L'art de toucher le clavecin version v2.4")
print(f"Datapackage '{package.package_name}' @ {git_tag}")
print(f"dimcat version {dc.__version__}\n")
D
Data and software versions
--------------------------
François Couperin – L'art de toucher le clavecin version v2.4
Datapackage 'couperin_clavecin' @ v2.4
dimcat version 3.4.0
Dataset
=======
{'inputs': {'basepath': None,
'packages': {'couperin_clavecin': ["'couperin_clavecin.measures' (MuseScoreFacetName.MuseScoreMeasures)",
"'couperin_clavecin.notes' (MuseScoreFacetName.MuseScoreNotes)",
"'couperin_clavecin.expanded' (MuseScoreFacetName.MuseScoreHarmonies)",
"'couperin_clavecin.chords' (MuseScoreFacetName.MuseScoreChords)",
"'couperin_clavecin.metadata' (FeatureName.Metadata)"]}},
'outputs': {'basepath': None, 'packages': {}},
'pipeline': []}
Metadata#
filtered_D = filters.HasHarmonyLabelsFilter(keep_values=[True]).process(D)
all_metadata = filtered_D.get_metadata()
all_metadata.reset_index(level=1).groupby(level=0).nth(0).iloc[:, :20]
| piece | TimeSig | KeySig | last_mc | last_mn | length_qb | last_mc_unfolded | last_mn_unfolded | length_qb_unfolded | volta_mcs | all_notes_qb | n_onsets | n_onset_positions | guitar_chord_count | form_label_count | label_count | annotated_key | harmony_version | annotators | reviewers | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| corpus | ||||||||||||||||||||
| couperin_clavecin | 00_allemande | {1: '4/4'} | {1: -1} | 15 | 13 | 52.0 | 30 | 26 | 104.0 | () | 101.75 | 322 | 210 | 0 | 0 | 66 | d | 2.3.0 | Adrian Nagel (2.1.0), Davor Krkljus (2.3.0) | DK, Hanné Becker |
chronological_order = utils.chronological_corpus_order(all_metadata)
corpus_colors = dict(zip(chronological_order, utils.CORPUS_COLOR_SCALE))
notes_feature = filtered_D.get_feature("notes")
all_notes = notes_feature.df
print(f"{len(all_notes.index)} notes over {len(all_notes.groupby(level=[0,1]))} files.")
all_notes.head()
4012 notes over 9 files.
| mc | mn | quarterbeats | quarterbeats_all_endings | duration_qb | duration | mc_onset | mn_onset | timesig | staff | voice | chord_id | gracenote | midi | name | nominal_duration | octave | scalar | tied | tpc_name | tpc | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| corpus | piece | i | |||||||||||||||||||||
| couperin_clavecin | 00_allemande | 0 | 1 | 0 | 0 | 0 | 0.25 | 1/16 | 0 | 5/16 | 4/4 | 1 | 1 | 0 | <NA> | 69 | A4 | 1/16 | 4 | 1 | <NA> | A | 3 |
| 1 | 1 | 0 | 1/4 | 1/4 | 0.25 | 1/16 | 1/16 | 3/8 | 4/4 | 1 | 1 | 1 | <NA> | 71 | B4 | 1/16 | 4 | 1 | <NA> | B | 5 | ||
| 2 | 1 | 0 | 1/2 | 1/2 | 0.25 | 1/16 | 1/8 | 7/16 | 4/4 | 1 | 1 | 2 | <NA> | 73 | C#5 | 1/16 | 5 | 1 | <NA> | C# | 7 | ||
| 3 | 1 | 0 | 3/4 | 3/4 | 0.25 | 1/16 | 3/16 | 1/2 | 4/4 | 1 | 1 | 3 | <NA> | 74 | D5 | 1/16 | 5 | 1 | <NA> | D | 2 | ||
| 4 | 1 | 0 | 1 | 1 | 0.25 | 1/16 | 1/4 | 9/16 | 4/4 | 1 | 1 | 4 | <NA> | 69 | A4 | 1/16 | 4 | 1 | <NA> | A | 3 |
def weight_notes(nl, group_col="midi", precise=True):
summed_durations = nl.groupby(group_col).duration_qb.sum()
shortest_duration = summed_durations[summed_durations > 0].min()
summed_durations /= shortest_duration # normalize such that the shortest duration results in 1 occurrence
if not precise:
# This simple trick reduces compute time but also precision:
# The rationale is to have the smallest value be slightly larger than 0.5 because
# if it was exactly 0.5 it would be rounded down by repeat_notes_according_to_weights()
summed_durations /= 1.9999999
return repeat_notes_according_to_weights(summed_durations)
def repeat_notes_according_to_weights(weights):
try:
counts = weights.round().astype(int)
except Exception:
return pd.Series(dtype=int)
counts_reflecting_weights = []
for pitch, count in counts.items():
counts_reflecting_weights.extend([pitch] * count)
return pd.Series(counts_reflecting_weights)
Ambitus#
corpus_names = {
corp: utils.get_corpus_display_name(corp) for corp in chronological_order
}
chronological_corpus_names = list(corpus_names.values())
corpus_name_colors = {
corpus_names[corp]: color for corp, color in corpus_colors.items()
}
all_notes["corpus_name"] = all_notes.index.get_level_values(0).map(corpus_names)
grouped_notes = all_notes.groupby("corpus_name")
weighted_midi = pd.concat(
[weight_notes(nl, "midi", precise=False) for _, nl in grouped_notes],
keys=grouped_notes.groups.keys(),
).reset_index(level=0)
weighted_midi.columns = ["dataset", "midi"]
weighted_midi
| dataset | midi | |
|---|---|---|
| 0 | Couperin Clavecin | 31 |
| 1 | Couperin Clavecin | 31 |
| 2 | Couperin Clavecin | 31 |
| 3 | Couperin Clavecin | 31 |
| 4 | Couperin Clavecin | 31 |
| ... | ... | ... |
| 4827 | Couperin Clavecin | 85 |
| 4828 | Couperin Clavecin | 85 |
| 4829 | Couperin Clavecin | 85 |
| 4830 | Couperin Clavecin | 86 |
| 4831 | Couperin Clavecin | 86 |
4832 rows × 2 columns
# fig = px.violin(weighted_midi,
# x='dataset',
# y='midi',
# color='dataset',
# title="Corpus-wise distribution over registers (ambitus)",
# box=True,
# labels=dict(
# dataset='',
# midi='distribution of pitches by duration'
# ),
# category_orders=dict(dataset=chronological_corpus_names),
# color_discrete_map=corpus_name_colors,
# width=1000, height=600,
# )
# fig.update_traces(spanmode='hard') # do not extend beyond outliers
# fig.update_layout(**utils.STD_LAYOUT,
# showlegend=False)
# fig.update_yaxes(
# tickmode= 'array',
# tickvals= [12, 24, 36, 48, 60, 72, 84, 96],
# ticktext = ["C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7"],
# )
# fig.update_xaxes(tickangle=45)
# save_figure_as(fig, "ambitus_corpuswise_violins")
# fig.show()
Tonal Pitch Classes (TPC)#
weighted_tpc = pd.concat(
[weight_notes(nl, "tpc") for _, nl in grouped_notes],
keys=grouped_notes.groups.keys(),
).reset_index(level=0)
weighted_tpc.columns = ["dataset", "tpc"]
weighted_tpc
| dataset | tpc | |
|---|---|---|
| 0 | Couperin Clavecin | -4 |
| 1 | Couperin Clavecin | -3 |
| 2 | Couperin Clavecin | -3 |
| 3 | Couperin Clavecin | -3 |
| 4 | Couperin Clavecin | -3 |
| 5 | Couperin Clavecin | -3 |
| 6 | Couperin Clavecin | -3 |
| 7 | Couperin Clavecin | -2 |
| 8 | Couperin Clavecin | -2 |
| 9 | Couperin Clavecin | -2 |
| 10 | Couperin Clavecin | -2 |
| 11 | Couperin Clavecin | -2 |
| 12 | Couperin Clavecin | -2 |
| 13 | Couperin Clavecin | -2 |
| 14 | Couperin Clavecin | -2 |
| 15 | Couperin Clavecin | -2 |
| 16 | Couperin Clavecin | -2 |
| 17 | Couperin Clavecin | -2 |
| 18 | Couperin Clavecin | -2 |
| 19 | Couperin Clavecin | -2 |
| 20 | Couperin Clavecin | -2 |
| 21 | Couperin Clavecin | -2 |
| 22 | Couperin Clavecin | -2 |
| 23 | Couperin Clavecin | -2 |
| 24 | Couperin Clavecin | -2 |
| 25 | Couperin Clavecin | -2 |
| 26 | Couperin Clavecin | -1 |
| 27 | Couperin Clavecin | -1 |
| 28 | Couperin Clavecin | -1 |
| 29 | Couperin Clavecin | -1 |
| 30 | Couperin Clavecin | -1 |
| 31 | Couperin Clavecin | -1 |
| 32 | Couperin Clavecin | -1 |
| 33 | Couperin Clavecin | -1 |
| 34 | Couperin Clavecin | -1 |
| 35 | Couperin Clavecin | -1 |
| 36 | Couperin Clavecin | -1 |
| 37 | Couperin Clavecin | -1 |
| 38 | Couperin Clavecin | -1 |
| 39 | Couperin Clavecin | -1 |
| 40 | Couperin Clavecin | -1 |
| 41 | Couperin Clavecin | -1 |
| 42 | Couperin Clavecin | -1 |
| 43 | Couperin Clavecin | -1 |
| 44 | Couperin Clavecin | -1 |
| 45 | Couperin Clavecin | -1 |
| 46 | Couperin Clavecin | -1 |
| 47 | Couperin Clavecin | -1 |
| 48 | Couperin Clavecin | -1 |
| 49 | Couperin Clavecin | -1 |
| 50 | Couperin Clavecin | -1 |
| 51 | Couperin Clavecin | -1 |
| 52 | Couperin Clavecin | -1 |
| 53 | Couperin Clavecin | -1 |
| 54 | Couperin Clavecin | -1 |
| 55 | Couperin Clavecin | -1 |
| 56 | Couperin Clavecin | -1 |
| 57 | Couperin Clavecin | -1 |
| 58 | Couperin Clavecin | -1 |
| 59 | Couperin Clavecin | -1 |
| 60 | Couperin Clavecin | 0 |
| 61 | Couperin Clavecin | 0 |
| 62 | Couperin Clavecin | 0 |
| 63 | Couperin Clavecin | 0 |
| 64 | Couperin Clavecin | 0 |
| 65 | Couperin Clavecin | 0 |
| 66 | Couperin Clavecin | 0 |
| 67 | Couperin Clavecin | 0 |
| 68 | Couperin Clavecin | 0 |
| 69 | Couperin Clavecin | 0 |
| 70 | Couperin Clavecin | 0 |
| 71 | Couperin Clavecin | 0 |
| 72 | Couperin Clavecin | 0 |
| 73 | Couperin Clavecin | 0 |
| 74 | Couperin Clavecin | 0 |
| 75 | Couperin Clavecin | 0 |
| 76 | Couperin Clavecin | 0 |
| 77 | Couperin Clavecin | 0 |
| 78 | Couperin Clavecin | 0 |
| 79 | Couperin Clavecin | 0 |
| 80 | Couperin Clavecin | 0 |
| 81 | Couperin Clavecin | 0 |
| 82 | Couperin Clavecin | 0 |
| 83 | Couperin Clavecin | 0 |
| 84 | Couperin Clavecin | 0 |
| 85 | Couperin Clavecin | 0 |
| 86 | Couperin Clavecin | 0 |
| 87 | Couperin Clavecin | 0 |
| 88 | Couperin Clavecin | 0 |
| 89 | Couperin Clavecin | 0 |
| 90 | Couperin Clavecin | 0 |
| 91 | Couperin Clavecin | 0 |
| 92 | Couperin Clavecin | 0 |
| 93 | Couperin Clavecin | 1 |
| 94 | Couperin Clavecin | 1 |
| 95 | Couperin Clavecin | 1 |
| 96 | Couperin Clavecin | 1 |
| 97 | Couperin Clavecin | 1 |
| 98 | Couperin Clavecin | 1 |
| 99 | Couperin Clavecin | 1 |
| 100 | Couperin Clavecin | 1 |
| 101 | Couperin Clavecin | 1 |
| 102 | Couperin Clavecin | 1 |
| 103 | Couperin Clavecin | 1 |
| 104 | Couperin Clavecin | 1 |
| 105 | Couperin Clavecin | 1 |
| 106 | Couperin Clavecin | 1 |
| 107 | Couperin Clavecin | 1 |
| 108 | Couperin Clavecin | 1 |
| 109 | Couperin Clavecin | 1 |
| 110 | Couperin Clavecin | 1 |
| 111 | Couperin Clavecin | 1 |
| 112 | Couperin Clavecin | 1 |
| 113 | Couperin Clavecin | 1 |
| 114 | Couperin Clavecin | 1 |
| 115 | Couperin Clavecin | 1 |
| 116 | Couperin Clavecin | 1 |
| 117 | Couperin Clavecin | 1 |
| 118 | Couperin Clavecin | 1 |
| 119 | Couperin Clavecin | 1 |
| 120 | Couperin Clavecin | 1 |
| 121 | Couperin Clavecin | 1 |
| 122 | Couperin Clavecin | 1 |
| 123 | Couperin Clavecin | 1 |
| 124 | Couperin Clavecin | 1 |
| 125 | Couperin Clavecin | 1 |
| 126 | Couperin Clavecin | 1 |
| 127 | Couperin Clavecin | 1 |
| 128 | Couperin Clavecin | 1 |
| 129 | Couperin Clavecin | 1 |
| 130 | Couperin Clavecin | 1 |
| 131 | Couperin Clavecin | 1 |
| 132 | Couperin Clavecin | 1 |
| 133 | Couperin Clavecin | 1 |
| 134 | Couperin Clavecin | 1 |
| 135 | Couperin Clavecin | 1 |
| 136 | Couperin Clavecin | 1 |
| 137 | Couperin Clavecin | 1 |
| 138 | Couperin Clavecin | 1 |
| 139 | Couperin Clavecin | 2 |
| 140 | Couperin Clavecin | 2 |
| 141 | Couperin Clavecin | 2 |
| 142 | Couperin Clavecin | 2 |
| 143 | Couperin Clavecin | 2 |
| 144 | Couperin Clavecin | 2 |
| 145 | Couperin Clavecin | 2 |
| 146 | Couperin Clavecin | 2 |
| 147 | Couperin Clavecin | 2 |
| 148 | Couperin Clavecin | 2 |
| 149 | Couperin Clavecin | 2 |
| 150 | Couperin Clavecin | 2 |
| 151 | Couperin Clavecin | 2 |
| 152 | Couperin Clavecin | 2 |
| 153 | Couperin Clavecin | 2 |
| 154 | Couperin Clavecin | 2 |
| 155 | Couperin Clavecin | 2 |
| 156 | Couperin Clavecin | 2 |
| 157 | Couperin Clavecin | 2 |
| 158 | Couperin Clavecin | 2 |
| 159 | Couperin Clavecin | 2 |
| 160 | Couperin Clavecin | 2 |
| 161 | Couperin Clavecin | 2 |
| 162 | Couperin Clavecin | 2 |
| 163 | Couperin Clavecin | 2 |
| 164 | Couperin Clavecin | 2 |
| 165 | Couperin Clavecin | 2 |
| 166 | Couperin Clavecin | 2 |
| 167 | Couperin Clavecin | 2 |
| 168 | Couperin Clavecin | 2 |
| 169 | Couperin Clavecin | 2 |
| 170 | Couperin Clavecin | 2 |
| 171 | Couperin Clavecin | 2 |
| 172 | Couperin Clavecin | 2 |
| 173 | Couperin Clavecin | 2 |
| 174 | Couperin Clavecin | 2 |
| 175 | Couperin Clavecin | 2 |
| 176 | Couperin Clavecin | 2 |
| 177 | Couperin Clavecin | 2 |
| 178 | Couperin Clavecin | 2 |
| 179 | Couperin Clavecin | 2 |
| 180 | Couperin Clavecin | 2 |
| 181 | Couperin Clavecin | 2 |
| 182 | Couperin Clavecin | 2 |
| 183 | Couperin Clavecin | 2 |
| 184 | Couperin Clavecin | 2 |
| 185 | Couperin Clavecin | 2 |
| 186 | Couperin Clavecin | 3 |
| 187 | Couperin Clavecin | 3 |
| 188 | Couperin Clavecin | 3 |
| 189 | Couperin Clavecin | 3 |
| 190 | Couperin Clavecin | 3 |
| 191 | Couperin Clavecin | 3 |
| 192 | Couperin Clavecin | 3 |
| 193 | Couperin Clavecin | 3 |
| 194 | Couperin Clavecin | 3 |
| 195 | Couperin Clavecin | 3 |
| 196 | Couperin Clavecin | 3 |
| 197 | Couperin Clavecin | 3 |
| 198 | Couperin Clavecin | 3 |
| 199 | Couperin Clavecin | 3 |
| 200 | Couperin Clavecin | 3 |
| 201 | Couperin Clavecin | 3 |
| 202 | Couperin Clavecin | 3 |
| 203 | Couperin Clavecin | 3 |
| 204 | Couperin Clavecin | 3 |
| 205 | Couperin Clavecin | 3 |
| 206 | Couperin Clavecin | 3 |
| 207 | Couperin Clavecin | 3 |
| 208 | Couperin Clavecin | 3 |
| 209 | Couperin Clavecin | 3 |
| 210 | Couperin Clavecin | 3 |
| 211 | Couperin Clavecin | 3 |
| 212 | Couperin Clavecin | 3 |
| 213 | Couperin Clavecin | 3 |
| 214 | Couperin Clavecin | 3 |
| 215 | Couperin Clavecin | 3 |
| 216 | Couperin Clavecin | 3 |
| 217 | Couperin Clavecin | 3 |
| 218 | Couperin Clavecin | 3 |
| 219 | Couperin Clavecin | 3 |
| 220 | Couperin Clavecin | 3 |
| 221 | Couperin Clavecin | 3 |
| 222 | Couperin Clavecin | 3 |
| 223 | Couperin Clavecin | 3 |
| 224 | Couperin Clavecin | 3 |
| 225 | Couperin Clavecin | 3 |
| 226 | Couperin Clavecin | 3 |
| 227 | Couperin Clavecin | 3 |
| 228 | Couperin Clavecin | 3 |
| 229 | Couperin Clavecin | 3 |
| 230 | Couperin Clavecin | 4 |
| 231 | Couperin Clavecin | 4 |
| 232 | Couperin Clavecin | 4 |
| 233 | Couperin Clavecin | 4 |
| 234 | Couperin Clavecin | 4 |
| 235 | Couperin Clavecin | 4 |
| 236 | Couperin Clavecin | 4 |
| 237 | Couperin Clavecin | 4 |
| 238 | Couperin Clavecin | 4 |
| 239 | Couperin Clavecin | 4 |
| 240 | Couperin Clavecin | 4 |
| 241 | Couperin Clavecin | 4 |
| 242 | Couperin Clavecin | 4 |
| 243 | Couperin Clavecin | 4 |
| 244 | Couperin Clavecin | 4 |
| 245 | Couperin Clavecin | 4 |
| 246 | Couperin Clavecin | 4 |
| 247 | Couperin Clavecin | 4 |
| 248 | Couperin Clavecin | 4 |
| 249 | Couperin Clavecin | 4 |
| 250 | Couperin Clavecin | 4 |
| 251 | Couperin Clavecin | 4 |
| 252 | Couperin Clavecin | 4 |
| 253 | Couperin Clavecin | 4 |
| 254 | Couperin Clavecin | 4 |
| 255 | Couperin Clavecin | 4 |
| 256 | Couperin Clavecin | 4 |
| 257 | Couperin Clavecin | 4 |
| 258 | Couperin Clavecin | 4 |
| 259 | Couperin Clavecin | 4 |
| 260 | Couperin Clavecin | 4 |
| 261 | Couperin Clavecin | 4 |
| 262 | Couperin Clavecin | 4 |
| 263 | Couperin Clavecin | 4 |
| 264 | Couperin Clavecin | 4 |
| 265 | Couperin Clavecin | 4 |
| 266 | Couperin Clavecin | 4 |
| 267 | Couperin Clavecin | 4 |
| 268 | Couperin Clavecin | 5 |
| 269 | Couperin Clavecin | 5 |
| 270 | Couperin Clavecin | 5 |
| 271 | Couperin Clavecin | 5 |
| 272 | Couperin Clavecin | 5 |
| 273 | Couperin Clavecin | 5 |
| 274 | Couperin Clavecin | 5 |
| 275 | Couperin Clavecin | 5 |
| 276 | Couperin Clavecin | 5 |
| 277 | Couperin Clavecin | 5 |
| 278 | Couperin Clavecin | 5 |
| 279 | Couperin Clavecin | 5 |
| 280 | Couperin Clavecin | 5 |
| 281 | Couperin Clavecin | 5 |
| 282 | Couperin Clavecin | 5 |
| 283 | Couperin Clavecin | 5 |
| 284 | Couperin Clavecin | 5 |
| 285 | Couperin Clavecin | 5 |
| 286 | Couperin Clavecin | 5 |
| 287 | Couperin Clavecin | 5 |
| 288 | Couperin Clavecin | 5 |
| 289 | Couperin Clavecin | 5 |
| 290 | Couperin Clavecin | 5 |
| 291 | Couperin Clavecin | 5 |
| 292 | Couperin Clavecin | 5 |
| 293 | Couperin Clavecin | 5 |
| 294 | Couperin Clavecin | 5 |
| 295 | Couperin Clavecin | 5 |
| 296 | Couperin Clavecin | 5 |
| 297 | Couperin Clavecin | 5 |
| 298 | Couperin Clavecin | 6 |
| 299 | Couperin Clavecin | 6 |
| 300 | Couperin Clavecin | 6 |
| 301 | Couperin Clavecin | 6 |
| 302 | Couperin Clavecin | 6 |
| 303 | Couperin Clavecin | 6 |
| 304 | Couperin Clavecin | 6 |
| 305 | Couperin Clavecin | 6 |
| 306 | Couperin Clavecin | 6 |
| 307 | Couperin Clavecin | 6 |
| 308 | Couperin Clavecin | 6 |
| 309 | Couperin Clavecin | 6 |
| 310 | Couperin Clavecin | 6 |
| 311 | Couperin Clavecin | 6 |
| 312 | Couperin Clavecin | 6 |
| 313 | Couperin Clavecin | 6 |
| 314 | Couperin Clavecin | 6 |
| 315 | Couperin Clavecin | 6 |
| 316 | Couperin Clavecin | 6 |
| 317 | Couperin Clavecin | 6 |
| 318 | Couperin Clavecin | 7 |
| 319 | Couperin Clavecin | 7 |
| 320 | Couperin Clavecin | 7 |
| 321 | Couperin Clavecin | 7 |
| 322 | Couperin Clavecin | 7 |
| 323 | Couperin Clavecin | 7 |
| 324 | Couperin Clavecin | 7 |
| 325 | Couperin Clavecin | 7 |
| 326 | Couperin Clavecin | 7 |
| 327 | Couperin Clavecin | 7 |
| 328 | Couperin Clavecin | 7 |
| 329 | Couperin Clavecin | 7 |
| 330 | Couperin Clavecin | 7 |
| 331 | Couperin Clavecin | 7 |
| 332 | Couperin Clavecin | 7 |
| 333 | Couperin Clavecin | 8 |
| 334 | Couperin Clavecin | 8 |
| 335 | Couperin Clavecin | 8 |
| 336 | Couperin Clavecin | 8 |
| 337 | Couperin Clavecin | 8 |
| 338 | Couperin Clavecin | 8 |
| 339 | Couperin Clavecin | 9 |
| 340 | Couperin Clavecin | 9 |
| 341 | Couperin Clavecin | 9 |
| 342 | Couperin Clavecin | 10 |
| 343 | Couperin Clavecin | 10 |
| 344 | Couperin Clavecin | 11 |
As violin plot#
# fig = px.violin(weighted_tpc,
# x='dataset',
# y='tpc',
# color='dataset',
# title="Corpus-wise distribution over line of fifths (tonal pitch classes)",
# box=True,
# labels=dict(
# dataset='',
# tpc='distribution of tonal pitch classes by duration'
# ),
# category_orders=dict(dataset=chronological_corpus_names),
# color_discrete_map=corpus_name_colors,
# width=1000,
# height=600,
# )
# fig.update_traces(spanmode='hard') # do not extend beyond outliers
# fig.update_layout(**utils.STD_LAYOUT,
# showlegend=False)
# fig.update_yaxes(
# tickmode= 'array',
# tickvals= [-12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18],
# ticktext = ["Dbb", "Bbb", "Gb", "Eb", "C", "A", "F#", "D#", "B#", "G##", "E##"],
# zerolinecolor='grey',
# zeroline=True
# )
# fig.update_xaxes(tickangle=45)
# save_figure_as(fig, "pitch_class_distributions_corpuswise_violins")
# fig.show()
(all_notes)
| mc | mn | quarterbeats | quarterbeats_all_endings | duration_qb | duration | mc_onset | mn_onset | timesig | staff | voice | chord_id | gracenote | midi | name | nominal_duration | octave | scalar | tied | tpc_name | tpc | corpus_name | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| corpus | piece | i | ||||||||||||||||||||||
| couperin_clavecin | 00_allemande | 0 | 1 | 0 | 0 | 0 | 0.25 | 1/16 | 0 | 5/16 | 4/4 | 1 | 1 | 0 | <NA> | 69 | A4 | 1/16 | 4 | 1 | <NA> | A | 3 | Couperin Clavecin |
| 1 | 1 | 0 | 1/4 | 1/4 | 0.25 | 1/16 | 1/16 | 3/8 | 4/4 | 1 | 1 | 1 | <NA> | 71 | B4 | 1/16 | 4 | 1 | <NA> | B | 5 | Couperin Clavecin | ||
| 2 | 1 | 0 | 1/2 | 1/2 | 0.25 | 1/16 | 1/8 | 7/16 | 4/4 | 1 | 1 | 2 | <NA> | 73 | C#5 | 1/16 | 5 | 1 | <NA> | C# | 7 | Couperin Clavecin | ||
| 3 | 1 | 0 | 3/4 | 3/4 | 0.25 | 1/16 | 3/16 | 1/2 | 4/4 | 1 | 1 | 3 | <NA> | 74 | D5 | 1/16 | 5 | 1 | <NA> | D | 2 | Couperin Clavecin | ||
| 4 | 1 | 0 | 1 | 1 | 0.25 | 1/16 | 1/4 | 9/16 | 4/4 | 1 | 1 | 4 | <NA> | 69 | A4 | 1/16 | 4 | 1 | <NA> | A | 3 | Couperin Clavecin | ||
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | |
| 08_huitieme_prelude | 607 | 31 | 31 | 183/2 | 183/2 | 1.50 | 3/8 | 3/8 | 3/8 | 6/8 | 2 | 2 | 610 | <NA> | 40 | E2 | 1/4 | 2 | 3/2 | -1 | E | 4 | Couperin Clavecin | |
| 608 | 31 | 31 | 183/2 | 183/2 | 1.50 | 3/8 | 3/8 | 3/8 | 6/8 | 2 | 1 | 608 | <NA> | 52 | E3 | 1/4 | 3 | 3/2 | <NA> | E | 4 | Couperin Clavecin | ||
| 609 | 31 | 31 | 183/2 | 183/2 | 1.50 | 3/8 | 3/8 | 3/8 | 6/8 | 1 | 2 | 602 | <NA> | 55 | G3 | 1/4 | 3 | 3/2 | -1 | G | 1 | Couperin Clavecin | ||
| 610 | 31 | 31 | 183/2 | 183/2 | 1.50 | 3/8 | 3/8 | 3/8 | 6/8 | 1 | 3 | 606 | <NA> | 59 | B3 | 1/4 | 3 | 3/2 | -1 | B | 5 | Couperin Clavecin | ||
| 611 | 31 | 31 | 183/2 | 183/2 | 1.50 | 3/8 | 3/8 | 3/8 | 6/8 | 1 | 1 | 598 | <NA> | 64 | E4 | 1/4 | 4 | 3/2 | -1 | E | 4 | Couperin Clavecin |
4012 rows × 22 columns
width = 1400
height = 800
weighted_pitch_values = pd.concat(
[
weighted_midi.rename(columns={"midi": "value"}),
weighted_tpc.rename(columns={"tpc": "value"}),
],
keys=["MIDI pitch", "Tonal pitch class"],
names=["distribution"],
).reset_index(level=[0, 1])
fig = plotting.make_violin_plot(
weighted_pitch_values,
x_col="dataset",
y_col="value",
color="dataset",
facet_row="distribution",
box=True,
labels=dict(dataset="", tpc="distribution of tonal pitch classes by duration"),
category_orders=dict(dataset=chronological_corpus_names),
# color_discrete_map=corpus_name_colors,
color_discrete_sequence=px.colors.qualitative.Dark24,
traces_settings=dict(
spanmode="hard",
width=1,
# scalemode='width'
),
layout=dict(
showlegend=False,
margin=dict(
t=0,
b=0,
l=0,
r=0,
),
),
x_axis=dict(
# tickangle=45,
tickfont_size=15
),
y_axis=dict(
tickmode="array",
tickvals=[-12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 24, 36, 48, 60, 72, 84, 96],
ticktext=[
"Dbb",
"Bbb",
"Gb",
"Eb",
"C",
"A",
"F#",
"D#",
"B#",
"G##",
"C1",
"C2",
"C3",
"C4",
"C5",
"C6",
"C7",
],
zerolinecolor="grey",
zeroline=True,
),
width=width,
height=height,
)
utils.realign_subplot_axes(fig, y_axes=dict(title_text=""))
save_figure_as(fig, "notes_violin", width=width, height=height)
fig
fig = plotting.make_box_plot(
weighted_pitch_values,
x_col="dataset",
y_col="value",
color="dataset",
facet_row="distribution",
# box=True,
labels=dict(dataset="", tpc="distribution of tonal pitch classes by duration"),
category_orders=dict(dataset=chronological_corpus_names),
# color_discrete_map=corpus_name_colors,
color_discrete_sequence=px.colors.qualitative.Light24,
# traces_settings=dict(spanmode='hard'),
layout=dict(showlegend=False, margin=dict(t=0)),
x_axis=dict(tickangle=45, tickfont_size=15),
y_axis=dict(
tickmode="array",
tickvals=[-12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 24, 36, 48, 60, 72, 84, 96],
ticktext=[
"Dbb",
"Bbb",
"Gb",
"Eb",
"C",
"A",
"F#",
"D#",
"B#",
"G##",
"C1",
"C2",
"C3",
"C4",
"C5",
"C6",
"C7",
],
zerolinecolor="grey",
zeroline=True,
),
width=width,
height=height,
)
utils.realign_subplot_axes(fig, y_axes=True)
save_figure_as(fig, "notes_box", width=width, height=height)
fig
As bar plots#
bar_data = all_notes.groupby("tpc").duration_qb.sum().reset_index()
x_values = list(range(bar_data.tpc.min(), bar_data.tpc.max() + 1))
x_names = ms3.fifths2name(x_values)
fig = px.bar(
bar_data,
x="tpc",
y="duration_qb",
labels=dict(tpc="Named pitch class", duration_qb="Duration in quarter notes"),
color_discrete_sequence=utils.CORPUS_COLOR_SCALE,
width=1000,
height=300,
)
fig.update_layout(**utils.STD_LAYOUT)
fig.update_xaxes(
zerolinecolor="grey",
tickmode="array",
tickvals=x_values,
ticktext=x_names,
dtick=1,
ticks="outside",
tickcolor="black",
minor=dict(dtick=6, gridcolor="grey", showgrid=True),
)
save_figure_as(fig, "pitch_class_distribution_absolute_bars")
fig.show()
scatter_data = all_notes.groupby(["corpus_name", "tpc"]).duration_qb.sum().reset_index()
fig = px.bar(
scatter_data,
x="tpc",
y="duration_qb",
color="corpus_name",
labels=dict(
duration_qb="duration",
tpc="named pitch class",
),
category_orders=dict(dataset=chronological_corpus_names),
color_discrete_map=corpus_name_colors,
width=1000,
height=500,
)
fig.update_layout(**utils.STD_LAYOUT)
fig.update_xaxes(
zerolinecolor="grey",
tickmode="array",
tickvals=x_values,
ticktext=x_names,
dtick=1,
ticks="outside",
tickcolor="black",
minor=dict(dtick=6, gridcolor="grey", showgrid=True),
)
save_figure_as(fig, "pitch_class_distribution_corpuswise_absolute_bars")
fig.show()
As scatter plots#
fig = px.scatter(
scatter_data,
x="tpc",
y="duration_qb",
color="corpus_name",
labels=dict(
duration_qb="duration",
tpc="named pitch class",
),
category_orders=dict(dataset=chronological_corpus_names),
color_discrete_map=corpus_name_colors,
facet_col="corpus_name",
facet_col_wrap=3,
facet_col_spacing=0.03,
width=1000,
height=1000,
)
fig.update_traces(mode="lines+markers")
fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1]))
fig.update_layout(**utils.STD_LAYOUT, showlegend=False)
fig.update_xaxes(
zerolinecolor="grey",
tickmode="array",
tickvals=[-12, -6, 0, 6, 12, 18],
ticktext=["Dbb", "Gb", "C", "F#", "B#", "E##"],
visible=True,
)
fig.update_yaxes(zeroline=False, matches=None, showticklabels=True)
save_figure_as(fig, "pitch_class_distribution_corpuswise_scatter")
fig.show()
no_accidental = bar_data[bar_data.tpc.between(-1, 5)].duration_qb.sum()
with_accidental = bar_data[~bar_data.tpc.between(-1, 5)].duration_qb.sum()
entire = no_accidental + with_accidental
(
f"Fraction of note duration without accidental of the entire durations: {no_accidental} / {entire} = "
f"{no_accidental / entire}"
)
'Fraction of note duration without accidental of the entire durations: 1895.8208333333334 / 2413.541666666667 = 0.7854933103150625'
Notes and staves#
print("Distribution of notes over staves:")
utils.value_count_df(all_notes.staff)
Distribution of notes over staves:
| counts | % | |
|---|---|---|
| staff | ||
| 1 | 2589 | 64.53 |
| 2 | 1423 | 35.47 |