I thought making a python package for the notebook would be nice: (to simplify usage and avoid common boiler plate code)
import icsound
ics = icsound.icsound()
ics
<icsound.icsound instance at 0x3a4aea8>
ics.start_engine()
icsound: rtaudio: ALSA module enabled icsound: rtmidi: ALSA Raw MIDI module enabled icsound: --Csound version 6.03.1 (double samples) May 12 2014 icsound: graphics suppressed, ascii substituted icsound: 0dBFS level = 1.0 icsound: orch now loaded icsound: audio buffered in 256 sample-frame blocks icsound: ALSA output: total buffer size: 1024, period size: 256 icsound: writing 512 sample blks of 64-bit floats to dac icsound: SECTION 1:
from sklearn import datasets
iris = datasets.load_iris()
Y = iris.target
ics.send_code('''
instr blip
asig oscil 0.1, 880
aenv linen 1, 0.005, p3, p3-0.005
outs asig*aenv, asig*aenv
endin
''')
icsound: instr blip uses instrument number 1
dur = 3
value_scaling = 1/(max(iris.data[:,0]) - min(iris.data[:,0]))
value_offset = min(iris.data[:,0])
score = ''
for length in iris.data[:,0]:
norm_index = (length - value_offset)* value_scaling
time = norm_index * dur
score += 'i "blip" %f 0.05\n'%time
ics.send_score(score)
icsound: 0.29935icsound: 0.29935icsound: WARNING: icsound: Buffer underrun in real-time audio outputicsound: 0.09340icsound: 0.09340icsound: 0.28021icsound: 0.28021icsound: 0.09340icsound: 0.09340icsound: 0.37361icsound: 0.37361icsound: 0.18681icsound: 0.18681icsound: 0.46701icsound: 0.46701icsound: 0.56042icsound: 0.56042icsound: 0.93403icsound: 0.93403icsound: 0.84063icsound: 0.84063icsound: 0.37361icsound: 0.37361icsound: 0.09340icsound: 0.09340icsound: 0.56042icsound: 0.56042icsound: 0.65382icsound: 0.65382icsound: 0.56042icsound: 0.56042icsound: 0.74722icsound: 0.74722icsound: 0.65382icsound: 0.65382icsound: 0.28021icsound: 0.28021icsound: 0.56042icsound: 0.56042icsound: 0.56042icsound: 0.56042icsound: 0.37361icsound: 0.37361icsound: 0.84063icsound: 0.84063icsound: 0.65382icsound: 0.65382icsound: 0.46701icsound: 0.46701icsound: 0.18681icsound: 0.18681icsound: 0.74722icsound: 0.74722icsound: 0.28021icsound: 0.28021icsound: 0.37361icsound: 0.37361icsound: 0.09340icsound: 0.09340icsound: 0.09340icsound: 0.09340icsound: 0.28021icsound: 0.28021icsound: 0.09340icsound: 0.09340icsound: 0.09340icsound: 0.09340icsound: 0.09340icsound: 0.09340icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound:
ics.send_code('''
gisine ftgen 0, 0, 4096, 10, 1
''')
icsound: ftable 101: icsound: ftable 101: 4096 points, scalemax 1.000 icsound: .-''''''-._ icsound: _-' '. icsound: _- '. icsound: - '_ icsound: .' - icsound: - '_ icsound: _' . icsound: . - icsound: - '_ icsound: _'_____________________________________._______________________________________ icsound: - . icsound: - - icsound: '_ _' icsound: . . icsound: - - icsound: '. _' icsound: -_ - icsound: -_ .' icsound: -_ _.' icsound: '-._____..'
ics.send_code('''
instr fm
icarfreq = p4
icmratio = p5
imoddepth = p6
aphs phasor icarfreq
aphsmod oscili imoddepth, icarfreq*icmratio
asig table3 aphs + aphsmod, gisine, 1, 0, 1
aenv linen 0.2,0.01, p3, p3-0.01
outs asig*aenv, asig*aenv
endin
''')
http://scikit-learn.org/stable/auto_examples/neighbors/plot_kde_1d.html
Kernel density can be mapped to a synthesis parameter, in addition to the dotplot sonification
from sklearn.neighbors.kde import KernelDensity
X = iris.data[:,0]
0.37361icsound: 0.37361
plot(X, marker='+', lw=0)
[<matplotlib.lines.Line2D at 0x47a4290>]
scatter(random.random(X.shape),X, marker='+', lw=1)
xlim((0,1))
(0, 1)
kde = KernelDensity(kernel='gaussian', bandwidth=0.1).fit(X[:,newaxis])
X_plot = linspace(min(X), max(X), 500)[:, newaxis]
fill(X_plot, np.exp(kde.score_samples(X_plot)), fc='#AAAAFF')
[<matplotlib.patches.Polygon at 0x4bc0d90>]
kde = KernelDensity(kernel='gaussian', bandwidth=0.2).fit(X[:,newaxis])
X_plot = linspace(min(X), max(X), 500)[:, newaxis]
fill(X_plot, np.exp(kde.score_samples(X_plot)), fc='#AAAAFF')
[<matplotlib.patches.Polygon at 0x498bad0>]
kde = KernelDensity(kernel='tophat', bandwidth=0.2).fit(X[:,newaxis])
X_plot = linspace(min(X)*0.9, max(X)* 1.1, 500)[:, newaxis]
fill(X_plot, np.exp(kde.score_samples(X_plot)), fc='#AAAAFF')
[<matplotlib.patches.Polygon at 0x4ef8d10>]
X = iris.data[:,3]
scatter(X, random.random(X.shape), marker='+')
<matplotlib.collections.PathCollection at 0x4f22310>
kde = KernelDensity(kernel='gaussian', bandwidth=0.2).fit(X[:,newaxis])
X_plot = linspace(-0.5, max(X)* 1.3, 500)[:, newaxis]
fill(X_plot, np.exp(kde.score_samples(X_plot)), fc='#AAAAFF')
[<matplotlib.patches.Polygon at 0x50b1e90>]
ics.send_code('''
instr fm
icarfreq = p4
icmratio = p5
imoddepth = p6
aphs phasor icarfreq
aphsmod oscili imoddepth, icarfreq*icmratio
asig table3 aphs + aphsmod, gisine, 1, 0, 1
aenv linen 0.1,0.01, p3, p3-0.01
outs asig*aenv, asig*aenv
endin
''')
0.59771icsound: 0.59771icsound: instr fm uses instrument number 2
notes = ''
base_freq = 110
freq_range = 110* 2**5
time_scale = 2.0
scores = exp(kde.score_samples(X[:, None]))
for value, score in zip(X, scores):
time = (value - min(X)) * time_scale
freq = base_freq + (freq_range * score/max(scores))
notes += 'i "fm" %f 0.1 %f 0.5 0.6\n'%(time, freq)
ics.send_score(notes)
0.29935icsound: 0.29935icsound: 0.59318icsound: 0.59318icsound: 2.78052icsound: 2.78052icsound: number of samples out of range:icsound: 1733icsound: 1733icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.69627icsound: 0.69627icsound: 0.69551icsound: 0.69551icsound: 0.09913icsound: 0.09913icsound: 0.09846icsound: 0.09846icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.69761icsound: 0.69761icsound: 0.29738icsound: 0.29738icsound: 0.49917icsound: 0.49917icsound: 1.26721icsound: 1.26721icsound: number of samples out of range:icsound: 271icsound: 271icsound: 0.79514icsound: 0.79514icsound: 1.19241icsound: 1.19241icsound: number of samples out of range:icsound: 136icsound: 136icsound: 0.39692icsound: 0.39692icsound: 0.19732icsound: 0.19732icsound: 1.18574icsound: 1.18574icsound: number of samples out of range:icsound: 142icsound: 142icsound: 0.49479icsound: 0.49479icsound: 0.59471icsound: 0.59471icsound: 0.59970icsound: 0.59970icsound: 0.29462icsound: 0.29462icsound: 0.78960icsound: 0.78960icsound:
kde = KernelDensity(kernel='gaussian', bandwidth=0.2).fit(X[:,newaxis])
scatter(X, np.exp(kde.score_samples(X[:,None])), marker ='+')
0.29886icsound: 0.29886
<matplotlib.collections.PathCollection at 0x56a6310>
virginicas = argwhere(iris.target == list(iris.target_names).index('virginica'))[:,0]
setosas = argwhere(iris.target == list(iris.target_names).index('setosa'))[:,0]
versicolors = argwhere(iris.target == list(iris.target_names).index('versicolor'))[:,0]
0.29886icsound: 0.29886
virginicas
array([100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149])
boxplot([iris.data[setosas][:,3], iris.data[virginicas][:,3], iris.data[versicolors][:,3]]);
boxplot([iris.data[setosas][:,0], iris.data[virginicas][:,0], iris.data[versicolors][:,0]]);
Directly sonify the boxplot values
Use two variables for two synthesis parameters.
X = iris.data[:,3]
Y = iris.data[:,0]
scatter(X, Y, marker='+')
xlabel(iris.feature_names[3])
ylabel(iris.feature_names[0])
<matplotlib.text.Text at 0x5aff790>
notes = ''
dur = 3.0
base_freq = 110
freq_range = 110* 2**5
scale = 1/(max(X) - min(X))
for feat3, feat0 in zip(X, Y):
time = (feat3 - min(X)) * scale * dur
freq = base_freq + (freq_range * feat0/max(Y))
notes += 'i "fm" %f 0.1 %f 0.5 0.6\n'%(time, freq)
ics.send_score(notes)
0.26667icsound: 0.26667icsound: 0.27430icsound: 0.27430icsound: 0.56277icsound: 0.56277icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 2.25991icsound: 2.25991icsound: number of samples out of range:icsound: 99icsound: 99icsound: 0.56000icsound: 0.56000icsound: 0.60584icsound: 0.60584icsound: 0.09955icsound: 0.09955icsound: 0.09841icsound: 0.09841icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.55832icsound: 0.55832icsound: 0.27703icsound: 0.27703icsound: 0.43486icsound: 0.43486icsound: 1.04463icsound: 1.04463icsound: number of samples out of range:icsound: 2icsound: 2icsound: 0.68028icsound: 0.68028icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.96300icsound: 0.96300icsound: 0.37479icsound: 0.37479icsound: 0.19507icsound: 0.19507icsound: 0.95580icsound: 0.95580icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.00000icsound: 0.45316icsound: 0.45316icsound: 0.46908icsound: 0.46908icsound: 0.48354icsound: 0.48354icsound: 0.28107icsound: 0.28107icsound: 0.68529icsound: 0.68529icsound:
http://scikit-learn.sourceforge.net/dev/modules/decomposition.html#principal-component-analysis-pca
When two variables are highly correlated it is good to try to "remove" that correlation to leave the distinct features. This can be done through Principal Component Analysis.
"PCA effectively rotates the axes in a multivariate space to find the principal axis along which the variance in the dataset is maximized, taking advantage of the covariance between all the variables" Sonification handbook page 185
angle = 0.4*pi
rot_matrix = array([[cos(angle), -sin(angle)], [sin(angle), cos(angle)]])
rot_matrix
0.26667icsound: 0.26667
array([[ 0.30901699, -0.95105652], [ 0.95105652, 0.30901699]])
points = np.dot(normal(scale=(8,19), size=(400, 2)), rot_matrix).T
scatter(*points)
<matplotlib.collections.PathCollection at 0x5cd9910>
from matplotlib.mlab import PCA
results = PCA(points.T)
scatter(*points)
plot([results.mu[0], results.sigma[0]], [results.mu[1], results.sigma[1]],'r', lw=4)
[<matplotlib.lines.Line2D at 0x5adcf90>]
results.sigma, results.mu
(array([ 17.94998485, 9.60118969]), array([ 1.56590579, -0.11931622]))
scatter(*(results.project(points.T).T))
<matplotlib.collections.PathCollection at 0x5d08cd0>
from sklearn.decomposition import PCA
X_reduced = PCA(n_components=2).fit_transform(points.T)
scatter(*X_reduced.T)
<matplotlib.collections.PathCollection at 0x61eeed0>
from mpl_toolkits.mplot3d import Axes3D
fig = figure(1, figsize=(8, 6))
ax = Axes3D(fig, elev=-150, azim=110)
X_reduced = PCA(n_components=3).fit_transform(iris.data)
ax.scatter(X_reduced[:, 0], X_reduced[:, 1], X_reduced[:, 2], c=Y)
ax.set_title("First three PCA directions")
ax.set_xlabel("1st eigenvector")
ax.w_xaxis.set_ticklabels([])
ax.set_ylabel("2nd eigenvector")
ax.w_yaxis.set_ticklabels([])
ax.set_zlabel("3rd eigenvector")
ax.w_zaxis.set_ticklabels([])
[]
Can be used to improve separation of auditory dotplots:
http://sonification.de/handbook/index.php/chapters/chapter8/#S8.1
from sklearn.cluster import KMeans
kmeans = KMeans(3, random_state=8)
Y_hat = kmeans.fit(iris.data).labels_
plt.scatter(iris.data[:,0], iris.data[:,1], c=Y_hat, cmap=cm.binary);
kmeans.cluster_centers_
array([[ 5.9016129 , 2.7483871 , 4.39354839, 1.43387097], [ 5.006 , 3.418 , 1.464 , 0.244 ], [ 6.85 , 3.07368421, 5.74210526, 2.07105263]])
kmeans.cluster_centers_[:,:2]
array([[ 5.9016129 , 2.7483871 ], [ 5.006 , 3.418 ], [ 6.85 , 3.07368421]])
scatter(*kmeans.cluster_centers_[:,:2].T, marker='x')
<matplotlib.collections.PathCollection at 0x678dc50>
plt.scatter(iris.data[:,0], iris.data[:,1], c=Y_hat, cmap=cm.binary)
scatter(*kmeans.cluster_centers_[:,:2].T, marker='x', s=100, lw=5)
<matplotlib.collections.PathCollection at 0x6792f50>
plt.scatter(iris.data[:,2], iris.data[:,3], c=Y_hat, cmap=cm.binary)
scatter(*kmeans.cluster_centers_[:,2:].T, marker='x', s=100, lw=5)
<matplotlib.collections.PathCollection at 0x67a3310>
Many ways of calculating multidimensional space distance:
http://docs.scipy.org/doc/scipy/reference/spatial.distance.html
from scipy.spatial.distance import cosine
distances = []
for point in iris.data:
distances.append(cosine(point, kmeans.cluster_centers_[1]))
plot(distances)
[<matplotlib.lines.Line2D at 0x6cb1410>]
notes = ''
dur = 8.0
base_freq = 110
freq_range = 110* 2**5
scale = 1/(max(X) - min(X))
for feat3, feat0, dist in zip(X, Y, distances):
time = (feat3 - min(X)) * scale * dur
freq = base_freq + (freq_range * feat0/max(Y))
cmratio = dist*10
notes += 'i "fm" %f 0.5 %f %f 0.6\n'%(time, freq, cmratio)
0.51773icsound: 0.51773
ics.send_score(notes)
icsound: 0.42560icsound: 0.42560icsound: WARNING: icsound: Buffer underrun in real-time audio outputicsound: 0.58276icsound: 0.58276icsound: 1.51952icsound: 1.51952icsound: number of samples out of range:icsound: 84icsound: 84icsound: 0.64351icsound: 0.64351icsound: 0.55313icsound: 0.55313icsound: 0.19559icsound: 0.19559icsound: 0.13123icsound: 0.13123icsound: 0.55628icsound: 0.55628icsound: 0.41586icsound: 0.41586icsound: 0.48278icsound: 0.48278icsound: 0.90262icsound: 0.90262icsound: 0.88620icsound: 0.88620icsound: 1.01682icsound: 1.01682icsound: number of samples out of range:icsound: 1icsound: 1icsound: 0.48874icsound: 0.48874icsound: 0.29528icsound: 0.29528icsound: 0.79947icsound: 0.79947icsound: 0.60059icsound: 0.60059icsound: 0.58924icsound: 0.58924icsound: 0.55459icsound: 0.55459icsound: 0.38865icsound: 0.38865icsound: 0.64405icsound: 0.64405icsound:
Two parameters
A rule tree determines aspects of sonification, e.g. rhythm.
By: Andrés Cabrera mantaraya36@gmail.com
For Course MAT 240F at UCSB
This ipython notebook is licensed under the CC-BY-NC-SA license: http://creativecommons.org/licenses/by-nc-sa/4.0/