Extract Data

The relevant data can be extracted as described below, for instance, if a different visualisation backend than Plotly should be used (see Basic Example for basic functionality).

Loading Files

There are some options for loading files. First, the load_file() function provides a number of parameters. Second, the load_corpus() function can be used to parallelise loading of multiple files (see documentation for more details). Here, we simply load the same file twice, parallelise loading, and cache results (subsequent runs of this script will reuse the cached result from the first run). The resulting corpus corresponds to a concatenation of the outputs generated by the load_file() function with the number of files as its first dimension. Note that the file_paths (and scapes in the corpus) may have a different order than the input file_paths (see documentation of load_corpus() for details).

import numpy as np

from musicflower.loader import load_corpus
file_path = 'Prelude_No._1_BWV_846_in_C_Major.mxl'
resolution = 50
corpus, file_paths = load_corpus(
    data=[file_path, file_path],
    n=resolution,
    parallel=True,
    use_cache=True
)
print(corpus.shape)

Out:

  0%|          | 0/2 [00:00<?, ?it/s]
 50%|#####     | 1/2 [00:00<00:00,  1.59it/s]
100%|##########| 2/2 [00:00<00:00,  3.14it/s]
(2, 1275, 12)

Colours and 3D Coordinates

These data can be mapped to colours and 3D coordinates as shown in the Basic Example, that is

from musicflower.plotting import key_colors
from musicflower.util import get_fourier_component, remap_to_xyz
colors = key_colors(corpus)
x, y, z = remap_to_xyz(*get_fourier_component(pcds=corpus, fourier_component=5))
print(colors.shape)
print(x.shape)

Out:

(2, 1275, 3)
(2, 1275)

Triangular Surface

The points in 3D space define a triangular surface, which corresponds the surface shown in a key scape plot “folded and wrapped” in 3D space. The point indices of the respective triangles can be obtained with the surface_scape_indices() function. The resolution can either be explicitly specified or via an array dimension.

from musicflower.util import surface_scape_indices
i, j, k = surface_scape_indices(colors, axis=1)  # from array dimension
i_, j_, k_ = surface_scape_indices(resolution)   # from resolution
np.array_equal([i, j, k], [i_, j_, k_])          # result is the same

Out:

True

The triangle with a specific index can be obtained as

piece = 0
idx = 0
print("1st vertex (i):", x[piece, i[idx]], y[piece, i[idx]], z[piece, i[idx]])
print("2nd vertex (j):", x[piece, j[idx]], y[piece, j[idx]], z[piece, j[idx]])
print("3rd vertex (k):", x[piece, k[idx]], y[piece, k[idx]], z[piece, k[idx]])

Out:

1st vertex (i): 1.016927877403892 0.7426998034456707 0.5644950789161736
2nd vertex (j): 1.0026452680541689 0.7305989113488147 0.5572501208474614
3rd vertex (k): 0.9955507901181572 0.7374709060596941 0.560905773736201

or, more compactly, by concatenating coordinates and indices and using NumPy’s advanced indexing

xyz = np.concatenate((x[..., None], y[..., None], z[..., None]), axis=-1)
ijk = np.concatenate((i[..., None], j[..., None], k[..., None]), axis=-1)
print(xyz[piece, ijk[idx]])

Out:

[[1.01692788 0.7426998  0.56449508]
 [1.00264527 0.73059891 0.55725012]
 [0.99555079 0.73747091 0.56090577]]

Time Traces

In Basic Example the time traces were plotted, but we did not extract the actual data for them. They are computed by interpolating along rows of the triangular map using the get_time_traces() function. In the output, the first dimension are time steps, the second runs along the traces (from the top of the triangle to the bottom), and the last one are xyz-coordinates or RGB-colours, respectively. The third (batch) dimension are the different pieces in this case.

from musicflower.util import get_time_traces
xyz_traces, colors_traces = get_time_traces(x=x, y=y, z=z, colors=colors, n_steps=200, axis=1)
print(xyz_traces.shape, colors_traces.shape)

Out:

(201, 50, 2, 3) (201, 50, 2, 3)

Total running time of the script: ( 0 minutes 0.731 seconds)

Gallery generated by Sphinx-Gallery