import numpy as np
import pandas as pd
import plotly as pltSpinorama manual
How to use the library step by step!
How to use the library?
How to load the data?
Start by loading some classical libraries:
Then some specific functions from Spinorama:
from spinorama.load_spl_hv_txt import parse_graph_spl_hv_txt
from spinorama.load import filter_graphs
from spinorama.constant_paths import MEAN_MIN, MEAN_MAX, DEFAULT_FREQ_RANGELoading a dataset in text format
The parser expect to find 72 files in this directory:
- name of the files matches *_H angle.txt for horizontal measurements with angle between -170 and 180 in 10 degrees increment
- name of the files matches *_V angle.txt for vertical measurements with angle between -170 and 180 in 10 degrees increment
speaker = 'Ascend Acoustics Sierra-2EX V2'
dir = f'../datas/measurements/{speaker}/vendor'
mformat='spl_hv_txt'
# read horizontal and vertical data
# spl_H and spl_V are dataframe
_, spl_H = parse_graph_spl_hv_txt(dir, 'H')
_, spl_V = parse_graph_spl_hv_txt(dir, 'V')
# put them in a convenient dictionnary of dataframe
df = filter_graphs(speaker, spl_H, spl_V, MEAN_MIN, MEAN_MAX, mformat=mformat, mdistance=1)How to load all the precomputed data in one call
import logging
import sys, os
sys.path.append(os.path.expanduser("../src"))
sys.path.append(os.path.expanduser(".."))
from generate_common import cache_load_seq, get_custom_logger
import datas.speaker as metadataSet logging level:
level = logging.DEBUG
logger = get_custom_logger(level=level, duplicate=True)
Load the data:
datas = cache_load_seq(filters={}, smoke_test=True)If you use smoke_test set to True, you only load a few speakers. If set to False, you load all of them, it can take one or two minutes to load the files. It returs a dictionnary organised by speaker, then by origin then by version of the measurement.
List of speakers:
print(datas.keys())List of graphs for a speaker:
print(datas['DIYSG HT-10'].keys())
print(datas['DIYSG HT-10']['Misc'].keys())
print(datas['DIYSG HT-10']['Misc']['misc-mtg90'].keys())CEA2034 for the same speaker:
print(datas['DIYSG HT-10']['Misc']['misc-mtg90']['CEA2034'][0:10])CEA2034 for the same speaker in a different format:
print(datas['DIYSG HT-10']['Misc']['misc-mtg90']['CEA2034_unmelted'][0:10])Computing with the data
Computing the spinorama (CEA2034)
from spinorama.compute_cea2034 import compute_cea2034
# compute the spin
spin = compute_cea2034(df['SPL Horizontal_unmelted'], df['SPL Vertical_unmelted'])Computing classical values for this speaker
from spinorama.compute_estimates import estimates
# compute the spin
spin = compute_cea2034(df['SPL Horizontal_unmelted'], df['SPL Vertical_unmelted'])
properties = estimates(spin, df['SPL Horizontal_unmelted'], df['SPL Vertical_unmelted'])
print('Reference point (Hz) at which the SPL value dropped by 3 dB with respect to the average of the on-axis measurement between [{}, {}]: {:5.1f} Hz'.format(
properties['ref_from'],
properties['ref_to'],
properties['ref_3dB'],
))
print('Directivity in degrees at which the SPL value dropped by 6 d with respect to the on-axis measurementB: {:5.1f} deg'.format(properties['directivity_horizontal_avg']))
propertiesCompute the harmann/olive score
Compute the PIR (Predicted In-Room Response)
from spinorama.compute_cea2034 import estimated_inroom_hv
pir = estimated_inroom_hv(df['SPL Horizontal_unmelted'], df['SPL Vertical_unmelted'])Compute the PIR (Predicted In-Room Response)
from spinorama.misc import graph_melt, graph_unmelt
from spinorama.compute_cea2034 import compute_cea2034, estimated_inroom_hv
from spinorama.compute_scores import speaker_pref_rating
spin = compute_cea2034(df['SPL Horizontal_unmelted'], df['SPL Vertical_unmelted'])
pir = estimated_inroom_hv(df['SPL Horizontal_unmelted'], df['SPL Vertical_unmelted'])
scores = speaker_pref_rating(graph_melt(spin), graph_melt(pir), rounded=True)
scoresPlotting the data
Example of the parameters you can change to adapt the layout to your liking. See plotly documentation for all the options
my_layout = dict(
width=700,
height=400,
title=dict(
x=0.5,
y=1.0,
xanchor="center",
yanchor="top",
text=speaker,
font=dict(
size=18,
),
),
legend=dict(
x=1.2,
y=1,
xanchor="center",
orientation="v",
font=dict(
size=10,
),
),
font=dict(
size=10
),
margin=dict(
l=0,
r=0,
b=30,
t=30,
pad=4
),
)All the plot functions are in:
import spinorama.plot as plotCEA2034 plot (aka spinorama plot)
plot_spin = plot.plot_spinorama(
spin=spin,
params=plot.plot_params_default,
minmax_slopes=None,
is_normalized=False,
valid_freq_range=DEFAULT_FREQ_RANGE
)
plot_spin.update_layout(my_layout)
plot_spinNormalized CEA2034 plot
plot_spin = plot.plot_spinorama(
spin=spin,
params=plot.plot_params_default,
minmax_slopes=None,
is_normalized=True,
valid_freq_range=DEFAULT_FREQ_RANGE
)
plot_spin.update_layout(my_layout)
plot_spinOn Axis plot
plot_onaxis = plot.plot_graph(df['On Axis_unmelted'], plot.plot_params_default, DEFAULT_FREQ_RANGE)
plot_onaxis.update_layout(my_layout)
plot_onaxisIf you also want to see regression lines:
plot_onaxis = plot.plot_graph_flat(df['On Axis_unmelted'], "On Axis", plot.plot_params_default, DEFAULT_FREQ_RANGE)
plot_onaxis.update_layout(my_layout)
plot_onaxisEarly reflection plot
plot_er = plot.plot_graph(df['Early Reflections_unmelted'], plot.plot_params_default, DEFAULT_FREQ_RANGE)
plot_er.update_layout(my_layout)
plot_erPredicted In-Room Response (aka PIR) plot
plot_pir = plot.plot_graph_regression(
df=df['Estimated In-Room Response_unmelted'],
measurement='Estimated In-Room Response',
params=plot.plot_params_default,
minmax_slopes=None,
is_normalized=False,
valid_freq_range=DEFAULT_FREQ_RANGE
)
plot_pir.update_layout(my_layout)
plot_pirDirectivity plots
There are various ways to represent directivity plots:
Contour plots
plot_contour_h = plot.plot_contour(df['SPL Horizontal_unmelted'], plot.contour_params_default, DEFAULT_FREQ_RANGE)
plot_contour_h.update_layout(my_layout)
plot_contour_hThe same one, normalized to on axis:
plot_contour_h = plot.plot_contour(df['SPL Horizontal_normalized_unmelted'], plot.contour_params_default, DEFAULT_FREQ_RANGE)
plot_contour_h.update_layout(my_layout)
plot_contour_h3D Contour plots
plot_contour_h = plot.plot_contour_3d(df['SPL Horizontal_unmelted'], plot.contour_params_default, DEFAULT_FREQ_RANGE)
plot_contour_h.update_layout(my_layout)
plot_contour_hThe same one, normalized to on axis:
plot_contour_h = plot.plot_contour_3d(df['SPL Horizontal_normalized_unmelted'], plot.contour_params_default, DEFAULT_FREQ_RANGE)
plot_contour_h.update_layout(my_layout)
plot_contour_hRadar plots
plot_contour_h = plot.plot_radar(df['SPL Horizontal_unmelted'], plot.radar_params_default, DEFAULT_FREQ_RANGE)
plot_contour_h.update_layout(my_layout)
plot_contour_hplot_contour_h = plot.plot_radar(df['SPL Vertical_unmelted'], plot.radar_params_default, DEFAULT_FREQ_RANGE)
plot_contour_h.update_layout(my_layout)
plot_contour_h