=== ASCII_Analysis.ipynb === This Jupyter notebook, titled 'ASCII_Analysis.ipynb', is a comprehensive analysis tool designed for the exploration and statistical study of ASCII data related to dance movements and the associated emotional states. The script includes functionalities for data preprocessing, visualization, and the extraction of meaningful statistics from time-series data. Through various statistical and signal processing techniques such as Lomb-Scargle periodograms and Gaussian fitting, it investigates properties like the center of position evolution, average distance from center, velocity analysis, and frequency domain analysis to discern patterns correlated with different emotions in dance movements. The notebook utilizes libraries such as pandas, matplotlib, numpy, scipy, seaborn, and mplEasyAnimate for its analysis. ```python import pandas as pd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from tqdm import tqdm import numpy as np from mplEasyAnimate import animation from scipy.signal import lombscargle import os from scipy.optimize import curve_fit import seaborn as sns ``` ```python def frameToArray(frame): start = 1 vecs = np.zeros(shape=(int((frame.shape[0]-1)/3), 3)) for itr, end in enumerate(range(4, frame.shape[0]+3, 3)): vecs[itr] = np.array(frame[start:end]) start = end return vecs ``` ```python def CalcCenterOfPos(frame): vecs = frameToArray(frame) return vecs.mean(axis=0) ``` ```python def CenterOfPosEvolution(df): COPs = np.zeros(shape=(df.shape[0], 3)) times = df['Time'].values for itr, frame in tqdm(df.iterrows(), total=df.shape[0]): COPs[itr] = CalcCenterOfPos(frame) return COPs, times ``` ```python def getAvgPosFromCenter(frame): COP = CalcCenterOfPos(frame) vecs = frameToArray(frame) return np.abs(vecs-COP).mean(axis=0) ``` ```python def getAvgDistFromCenter(frame): COP = CalcCenterOfPos(frame) vecs = frameToArray(frame) return np.mean(np.sqrt(np.sum(np.power(np.subtract(COP, vecs), 2), axis=1))) ``` ```python def evolveAvgPosFromCenter(df): SEPs = np.zeros(shape=(df.shape[0], 3)) times = df['Time'].values for itr, frame in tqdm(df.iterrows(), total=df.shape[0]): SEPs[itr] = getAvgPosFromCenter(frame) return SEPs, times ``` ```python def evolveAvgDistFromCenter(df): SEPs = np.zeros(shape=(df.shape[0],)) times = df['Time'].values for itr, frame in tqdm(df.iterrows(), total=df.shape[0]): SEPs[itr] = getAvgDistFromCenter(frame) return SEPs, times ``` ```python def genLSP(t, y, s=None): nyquist = 1/(2*(t[1]-t[0])) res = (t[1]-t[0])/t.shape[0] if not s: s = int(1/res) f = 2*np.pi*np.linspace(res/10, 0.5, s) pgram = lombscargle(t, y, f, normalize=True) return f, pgram ``` ```python analyzedFiles = os.listdir('AnalyzedData/') analyzedFiles = ["AnalyzedData/{}".format(x) for x in analyzedFiles if x[0] != '.'] ``` ```python emotions = [(x.split('.')[0]).split('_')[-1] for x in analyzedFiles] ``` ```python data = list() for file in analyzedFiles: analysis = np.load(file) data.append(analysis) ``` ```python for i, element in enumerate(data): data[i][1] = (data[i][1]-np.mean(data[i][1]))/np.mean(data[i][1]) ``` ```python velocities = list() for dance in data: vel = (np.roll(dance[1], -1) - np.roll(dance[1], 1)) / (np.roll(dance[0], -1) - np.roll(dance[0], 1)) velocities.append(np.vstack([dance[0], vel])) ``` ```python for dance in velocities: plt.plot(dance[0], abs(dance[1])) ``` ![png](output_14_0.png) ```python for dance in data: plt.plot(dance[0], dance[1]) ``` ![png](output_15_0.png) ```python fig, ax = plt.subplots(1, 1, figsize=(10, 7)) ax.plot(data[0][0], data[0][1], 'k', linewidth=1) ax.set_xlabel('Time [s]', fontsize=17) ax.set_ylabel('Mean Radial Seperation [m]', fontsize=17) ax.tick_params(axis='both', which='major', labelsize=15) plt.savefig("Figures/MeanRadialSeperation.pdf", bbox_inches='tight') ``` ![png](output_16_0.png) # Frequency Position Analysis ```python FTs = np.zeros(shape=(49, 2, 2000)) ``` ```python count = 0 for did, dance in tqdm(enumerate(data), total=len(data)): if did != 9: f, pgram = genLSP(dance[0], dance[1], s=2000) FTs[count, 0] = f FTs[count, 1] = pgram count += 1 ``` ```python for fid, FT in enumerate(FTs): if np.mean(FT[1]) > 0.4: print(fid) plt.plot(FT[0], FT[1]) ``` ![png](output_20_0.png) ```python fig, ax = plt.subplots(1, 1, figsize=(10, 7)) ax.plot(FTs[0][0], FTs[0][1], 'k', linewidth=1) ax.set_xlabel(r'Frequency [s$^{-1}$]', fontsize=17) ax.set_ylabel('Fractional Amplitude', fontsize=17) ax.tick_params(axis='both', which='major', labelsize=15) plt.savefig("Figures/FTExample.pdf", bbox_inches='tight') ``` ![png](output_21_0.png) ```python len(evalEmotions) ``` 49 ```python stats = np.zeros(shape=(49, 3)) evalEmotions = list() count = 0 for fid, FT in enumerate(FTs): stats[count] = np.array([FT[0][FT[1].argmax()], FT[1][FT[1].argmax()], np.mean(FT[1])]) evalEmotions.append(emotions[count]) count += 1 ``` ```python fig, axs = plt.subplots(3, 1, figsize=(10, 10)) axs[0].plot(stats[:, 0], stats[:, 1], 'o') axs[1].plot(stats[:, 1], stats[:, 2], 'x') axs[2].plot(stats[:, 0], stats[:, 2], 's') for stat, emotion in zip(stats, evalEmotions): axs[2].annotate(emotion, xy=(stat[0], stat[2])) ``` ![png](output_24_0.png) ```python gaus = lambda x, mu, sigma: 1/np.sqrt(2*np.pi*(sigma**2))*np.exp(-((x-mu)**2)/(2*(sigma**2))) bimodal = lambda x, mu1, sigma1, mu2, sigma2: gaus(x, mu1, sigma1)+gaus(x, mu2, sigma2) ``` ```python fig = plt.figure(figsize=(10, 7)) bins = plt.hist(stats[:, 0], bins=20) centers = (bins[1][1:]+bins[1][:-1])/2 plt.xlabel('Frequencey of Max Amplitude', fontsize=20) ``` Text(0.5, 0, 'Frequencey of Max Amplitude') ![png](output_26_1.png) ```python fit1, covar1 = curve_fit(gaus, centers, bins[0], p0=[0.1, 0.2]) err1 = np.sqrt(np.diag(covar1)) fit2, covar2 = curve_fit(gaus, centers, bins[0], p0=[1, 0.1]) err2 = np.sqrt(np.diag(covar2)) ``` ```python fig = plt.figure(figsize=(10, 7)) x = np.linspace(0, 1.75, 1000) bins = plt.hist(stats[:, 0], bins=20, color='grey', alpha=0.5, ec='black') plt.plot(x, gaus(x, *fit1)+gaus(x, *fit2), color='black', linestyle='dashed') plt.xlabel('Frequencey of Max Amplitude', fontsize=20) plt.annotate(r'$\mu_{{1}}={:0.2f}\pm{:0.2f}$ Hz'.format(fit1[0], err1[0]), xy=(0.5, 6), fontsize=15) plt.annotate(r'$\sigma_{{1}}={:0.2f}\pm{:0.2f}$ Hz'.format(fit1[1], err1[1]), xy=(0.5, 5.5), fontsize=15) plt.annotate(r'$\mu_{{2}}={:0.2f}\pm{:0.2f}$ Hz'.format(fit2[0], err2[0]), xy=(1, 6), fontsize=15) plt.annotate(r'$\sigma_{{2}}={:0.2f}\pm{:0.2f}$ Hz'.format(fit2[1], err2[1]), xy=(1, 5.5), fontsize=15) plt.savefig('Figures/FrequencyDist.pdf', bbox_inches='tight') ``` ![png](output_28_0.png) # Velocity Analysis ```python nonStatGaus = lambda x, mu, sigma, A: A*np.exp(-((x-mu)**2)/(2*(sigma**2))) ``` ```python meanVels = [np.std(x[1]) for x in velocities] ``` ```python x = np.linspace(2, 8, 1000) bins = plt.hist(meanVels, bins=7) centers = (bins[1][1:]+bins[1][:-1])/2 fit, covar = curve_fit(nonStatGaus, centers, bins[0], p0=[4.5, 6, 7]) plt.plot(x, nonStatGaus(x, *fit)) plt.show() ``` ![png](output_32_0.png) ```python timeSeriseStats = np.zeros(shape=(49, 4)) count = 0 for did, dance in enumerate(velocities): if did != 9: timeSeriseStats[count, 0] = np.mean(dance[1]) timeSeriseStats[count, 1] = np.median(dance[1]) timeSeriseStats[count, 2] = np.max(dance[1]) timeSeriseStats[count, 3] = np.std(dance[1]) count += 1 ``` ```python df = pd.DataFrame(data=timeSeriseStats, columns=['Mean', 'Median', 'Max', 'Sigma']) df['Emotion'] = pd.Series(evalEmotions, index=df.index) ``` ```python df ```
Mean Median Max Sigma Emotion
0 -0.001798 -0.004902 56.168820 2.978317 Miserable
1 -0.001649 0.002063 62.108348 5.054398 Mix
2 -0.004032 0.006175 44.446849 5.329097 Angry
3 -0.002111 0.007060 42.284433 3.910049 Tired
4 -0.000834 0.002970 46.395794 4.436914 Pleased
5 -0.001896 -0.001654 48.362561 4.013522 Sad
6 -0.002551 0.000869 59.083402 3.036652 Relaxed
7 -0.002301 -0.002254 48.161705 5.110528 Pleased
8 -0.002890 -0.000064 52.981581 4.607283 Afraid
9 0.000044 0.002082 48.025167 3.730987 Mix
10 -0.000073 -0.000042 55.873222 4.402845 Afraid
11 -0.000254 -0.001653 62.410698 6.520325 Sad
12 -0.001560 0.000646 41.603721 4.267015 Angry
13 -0.001363 -0.000718 32.500379 3.303371 Angry
14 -0.002550 -0.001232 53.745451 4.533554 Satisfied
15 -0.001855 0.001056 53.571594 4.125465 Tired
16 -0.002170 -0.001059 56.175345 3.739604 Annoyed
17 -0.000951 0.001410 43.203369 4.116629 Bored
18 0.000185 0.000682 53.907577 4.237050 Pleased
19 -0.000184 -0.000246 52.905508 4.148395 Excited
20 -0.001560 -0.001905 55.523178 4.340211 Happy
21 -0.001759 0.000900 45.436848 4.257791 Angry
22 -0.000372 0.002558 57.722183 4.424116 Miserable
23 0.000884 0.004534 31.542905 3.119212 Miserable
24 -0.002209 -0.000254 62.365436 6.278034 Relaxed
25 -0.003495 0.002474 62.691057 6.775984 Annoyed
26 -0.000142 -0.009252 52.386723 6.254499 Afraid
27 -0.000601 -0.002673 45.750873 5.537992 Excited
28 -0.002934 0.005929 35.486262 4.347244 Excited
29 -0.002131 0.002095 49.055195 5.256263 Happy
30 0.004173 -0.001804 51.143077 5.439556 Bored
31 -0.000224 -0.006051 40.074855 3.727305 Happy
32 -0.002232 0.004002 47.220204 5.129865 Afraid
33 -0.003202 0.001654 27.594398 3.238834 Annoyed
34 -0.002317 0.000272 63.977990 4.435240 Bored
35 -0.002719 0.004786 43.860434 4.161989 Annoyed
36 -0.000957 0.000309 41.176874 2.883719 Sad
37 -0.001290 -0.000089 55.583615 5.272462 Tired
38 -0.000217 -0.004358 49.607502 6.279034 Relaxed
39 -0.000071 -0.002206 38.600903 5.021533 Satisfied
40 -0.001090 -0.001596 68.660583 4.984018 Satisfied
41 -0.000999 0.000668 77.463016 5.703841 Mix
42 -0.001357 0.000859 54.578165 4.464673 Happy
43 0.003839 0.004214 42.680804 4.096789 Excited
44 -0.002007 -0.000875 55.284132 4.743275 Sad
45 0.004543 0.002699 44.558832 4.904963 Bored
46 0.000246 0.000620 34.547461 3.294687 Relaxed
47 -0.000669 0.007457 47.166044 5.101586 Pleased
48 -0.000959 -0.000093 48.413527 4.118721 Mix
```python with sns.axes_style("ticks"): sns.pairplot(df, hue='Emotion') plt.savefig('Figures/PairPlot.pdf', bbox_inches='tight') ``` /home/tboudreaux/anaconda3/envs/general/lib/python3.7/site-packages/scipy/stats/stats.py:1713: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result. return np.add.reduce(sorted[indexer] * weights, axis=axis) / sumval ![png](output_36_1.png) # Periodic Behavior in Velocity ```python FTs_V = np.zeros(shape=(49, 2, 2000)) ``` ```python count = 0 for did, dance in tqdm(enumerate(velocities), total=len(velocities)): if did != 9: f, pgram = genLSP(dance[0], dance[1], s=2000) FTs_V[count, 0] = f FTs_V[count, 1] = pgram count += 1 ``` ```python for fid, FT in enumerate(FTs_V): plt.plot(FT[0], FT[1]) ``` ![png](output_40_0.png) ```python stats_V = np.zeros(shape=(49, 3)) count = 0 for fid, FT in enumerate(FTs_V): stats_V[count] = np.array([FT[0][FT[1].argmax()], FT[1][FT[1].argmax()], np.mean(FT[1])]) count += 1 ``` ```python fig, axs = plt.subplots(3, 1, figsize=(10, 10)) axs[0].plot(stats_V[:, 0], stats_V[:, 1], 'o') axs[1].plot(stats_V[:, 1], stats_V[:, 2], 'x') axs[2].plot(stats_V[:, 0], stats_V[:, 2], 's') ``` [] ![png](output_42_1.png) ```python df = pd.DataFrame(data=stats_V, columns=['Max Frequency', 'Max Amplitude', 'Standard Deviation']) df['Emotion'] = pd.Series(evalEmotions, index=df.index) ``` ```python sns.pairplot(df, hue="Emotion") ``` /home/tboudreaux/anaconda3/envs/general/lib/python3.7/site-packages/scipy/stats/stats.py:1713: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result. return np.add.reduce(sorted[indexer] * weights, axis=axis) / sumval ![png](output_44_2.png) ```python ```