HTML5 und Javascript: Daten visualisieren mit Plotly.JS

Mit Plotly lassen sich relativ unkompliziert Daten in allen möglichen Darstellungsarten visualisieren.

 

z.B. Klangdaten einzelner Musikinstrumente:
Glasflöte
, Glastrompete, Glasplattenklavier, Glasharmonika (Pedal), Glasharmonika (Motor), Verrophon

Timbre Features: Formanten, Spectral Centroids, dynamische Klangfarbenfelder

Registergrenzen: Flöte, Oboe, Klarinette, Fagott

Messwerte an Inkubatoren: Innerhalb und außerhalb des Inkubators, Pegel in dB(A), Pegel in dB(SPL)

u.v.a.m.: Raumakustische Daten , Glockenklänge , Taubengurren, HipHop: Produzenten vs, Interpreten , Klangfarbe-Farbe-Synästhesie

Im Vergleich zu anderen Daten-Visualisierungs-Libraries ist Plotly die mit Abstand vielseitigste Library mit einer großen Community.

Sobald man sich die aktuelle Plotly-Library unter
https://cdn.plot.ly/plotly-latest.min.js
heruntergeladen hat, kann man direkt loslegen:

Zunächst legt man die heruntergeladene Datei (plotly-latest.min.js) in einen Ordner (z.B. mit dem Namen "header"), in dem sich auch die Datei mit den darzustellenden Daten befinden sollte. Hier wäre dies z.B. die Datei lukeme_array.js , die aus Signalanalysen der Lukeme-Klänge in Excel hervorgegangen ist (lukeme.xls).

 

 

Von CSV (bzw. Excel-Sheet) zum Javascript-Array

In lukeme_array.js sind die einzelnen Tabellenspalten aus der Excel-Datei als Arrays (= Listen) dargestellt, indem zunächst jeweils der Array-Name initialisiert wird (z.B. var name_array = []; oder var pitch_array = []; ) und dann die eckigen Klammern ([]) mit den jeweiligen Werten gefüllt werden.

Buchstaben oder Wörter werden hierbei durch Apostrophe und Kommata getrennt (z.B. ['a2', 'h2', 'e2', 'f2', 'h1', ...]), Zahlen werden nur durch Kommata getrennt (z.B. [880, 1006, 671, 703, 502, ...]).
Achtung: Bei Komma-Zahlen wird anstelle des Kommas ein Punkt verwendet (z.B. [0.020, 0.028, 0.025, 0.028, 0.023, ...]).

Hat man mehrere Excel-Dateien (z.B. die Hautleitwerte von mehreren Versuchspersonen als txt.- oder csv-Datei), so müssen sie vorher synchronisiert werden. Hierzu kann man sich am besten an der Audiospur orientieren (beim Nexus-10MKII über einen der EXG-Kanäle aufgenommen).
Hierzu nimmt man zunächst die Excel-Daten....


Hautleitwerte von Vpn1 und Vpn2 in Excel

...entfernt alle überflüssigen Informationen und beschriftet die Spalten eindeutiger ...


Hautleitwerte von Vpn1 und Vpn2 in Excel gesäubert und mit verständlicheren Überschriften

... und ersetzt via Suchen/Ersetzen alle Punkte durch Beistriche.


Hautleitwerte von Vpn1 und Vpn2 in Excel als Dezimalwerte

Nun kann man die Amplitudenwerte via Bedingte Formatierung ...


Auswahl Bedingte Formatierung in Excel

... als Balken bzw. Kurven visualisieren und darüber optisch die Zeitpunkte ermitteln, an denen das Klangbeispiel bei den jeweiligen Versuchspersonen einsetzte (für einen prägnanteren Start des Klangbeginns bietet es sich an, die Klangbeispiele am Anfang mit einem Knack zu versehen):


Hautleitwerte von Vpn1 und Vpn2 in Excel mit gemeinsamen Startpunkten des Klangbeispiels

Nun können beide Tabellen am jeweiligen Startpunkt zu einer Tabelle zusammengeführt werden ....


Hautleitwerte von Vpn1 und Vpn2 in Excel in einer Tabelle zusammengeführt

... und am Ende des Klangbeispiels entsprechend abgeschnitten werden.


Hautleitwerte von Vpn1 und Vpn2 in Excel in einer Tabelle zusammengeführt mit gemeinsamem Ende

Da man für die gemeinsame Darstellung der Hautleitwerte nur eine Zeit und nur eine Amplitude braucht, können Zeit und Amplitude bei der zweite Vpn (bzw. bei allen anderen Vpns, wenn man mehrere Tabellen zusammenführt) auch weggelassen werden.


Hautleitwerte von Vpn1 und Vpn2 in Excel bezogen auf eine Zeit und eine Amplitude

Wenn man diese Zeilen in Javascript-Arrays überführen möchte, dann bietet es sich an die Zeilenüberschrift als Array-Namen zu verwenden (am besten immer mit "_array" dahinter, damit man schon von der Variablenbezeichnung her weiß, dass es sich um ein Array handelt). Die erste Spalte würde also lauten:

var Zeit_vpn1_array =['00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04', '00:00:04'];

Hier ist es sinnvoller lieber eine aufsteigende Zahlenreihe zu verwenden, da die zeitliche Auflösung (Sekunden) zu grob gewählt ist, und man mit dem Zeitformat (00:00:00) keine richtige Zahl zum Verarbeiten hat, also (als zeit_array):

var zeit_array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27];


Die zweite Spalte (Amp_vpn1) könnte man als amplitude_array umbenennen und sie sähe dann folgendermaßen aus:

var Amplitude_array = [-8105.064, 4909.546, -4954.656, -4092.409, 7767.08, -9441.655, -3964.031, 6429.124, -367.49, -5119.383, 14598.257, -12373.519, -12647.501, 22557.585, -6541.072, -18004.752, 15941.683, 12083.996, -26127.096, 12360.408, 17972.199, -15439.845, -9781.761, 18909.541, -25033.04, -15883.169];


Hier ist es wichtig, dass das Komma in den Zahlen vorher in einen Punkt umgewandelt wird, da in Javascript bei Dezimalwerten ein Punkt verlangt wird und man das Komma für die Trennung der Zahlen in dem Array braucht.
Die dritte und vierte Spalte (Hautleitwert_vpn1 und Hautleitwert_vpn2) sehen dann entsprechend ähnlich aus:

var Hautleitwert_vpn1_array = [2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.108, 2.109, 2.109, 2.109, 2.109, 2.109];
var Hautleitwert_vpn2_array = [1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.968, 1.969, 1.969, 1.969, 1.969, 1.969, 1.969, 1.969, 1.969, 1.969];

Um diesen Vorgang zu automatisieren hat Veronika Weber auch das Matlab-Script xls2js.m geschrieben

 

Grundlegender Aufbau von Plotly-Visualisierungen

Sobald die Daten in dieser Art vorbereitet sind, kann man beide Dateien über das Script-Tag in eine html-Datei einbinden. Der typische Aufbau einer html-Datei mit der eingebundenen Plotly-Library und den eingebundenen vorbereiteten Daten-Arrays sähe dann folgendermaßen aus:

<html>

<head>
<script src="header/plotly-latest.min.js"></script>
<script src="header/lukeme_array.js"></script>
</head>

<body bgcolor="#FFFFFF" text="#000000">
<!--(hier kommt dann der im Browser sichtbare Inhalt hin) -->
</body>

</html>

 

Zwischen die beiden Body-Tags ( <body bgcolor="#FFFFFF" text="#000000"> und </body> ) kommen dann 5 Abschnitte, die je nach Darstellungsart teilweise anders gefüllt werden:

 

1. Ein durch DIV-Tags festgelegter Bereich mit einem Namen (hier "AnzeigeDiv") mit den Pixelmaßen für die Weite und Höhe der Darstellung (hier style="width:800,height:800"), in dem die Visualisierung angezeigt werden soll.

<div id="AnzeigeDiv" style="width:800,height:800"></div>

2. Ab hier beginnt ein Script-Teil (zwischen <script> und </script>), in dem alles Weitere geregelt wird. Zunächst werden die Daten und die Art der Darstellung in einzelnen "Traces" zusammengestellt, z.B.

var trace1 = {
x: pitch_array, // X-Achse: Array mit Tonhöhen der Lukeme aus lukeme_array.js
y: attackTime_array, //Y-Achse: Array mit Einschiwingzeiten der Lukeme aus lukeme_array.js
type: 'bar', // Darstellung in Balkengrafiken
name: 'Einschwingzeit', // Bezeichnung der Balken
text: pitch_array, // Namen der Werte: Array mit den Tonhöhennamen aus lukeme_array.js
};

var trace2 = {
x: pitch_array, // X-Achse: Array mit Tonhöhen der Lukeme aus lukeme_array.js
y: releaseTime_array, // Y-Achse: Array mit Ausklingzeiten der Lukeme aus lukeme_array.js
type: 'bar', // Darstellung in Balkengrafiken
name: 'Ausklingzeit', // Bezeichnung der Balken
text: pitch_array, // Namen der Werte: Array mit den Tonhöhennamen aus lukeme_array.js
};

Es können hier beliebig viele Traces angelegt werden, die auch beliebig gestaltet werden können (Farben, Transparenz, Punkte, Linien, Schriftarten etc.)

3. Alle Traces werden dann in einem Array namens "data" zusammengefasst:

var data = [ trace1, trace2];

4. Danach wird das Layout bestimmt, z.B.:

var layout = {
showlegend: true, // Legende für die einzelnen Kurven/Punkte an rechter Seite anzeigen
barmode: 'stack', //Balken werden übereinandergestapelt angezeigt
xaxis: {
title: 'Grundtonhöhen', // Titel der X-Achse
},
yaxis: {
title: 'Dauern [sec]', // Titel der Y-Achse
},
legend: { // Gestaltung der Legende
font: { family: 'Verdana, sans-serif', size: 10, color: 'black', }
},
title: 'Einschwing- und Ausklingzeiten der Lukeme', // Gesamttitel
};

5. Schließlich werden mit Plotly.newPlot(); alle Traces (data) und das Layout (layout) zusammengeführt und im oben definierten Bereich (AnzeigeDiv, s.o. unter 1.) zur Darstellung gebracht:

Plotly.newPlot('AnzeigeDiv', data, layout);

Nach diesem Schema laufen so ziemlich alle Darstellungsarten innerhalb von Plotly ab.

 

Für Daten aus der (systematischen) Musikwissenschaft sind folgende Darstellungsarten besonders spannend:

Zweidimensionale Darstellungen:

Drei- und mehrdimensionale Darstellungen: