=== 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 |