import sys
sys.path.append('/Users/spacecoffin/Development')

import GravelKicker as gk
import librosa
import numpy as np
import os
import pandas as pd

from datetime import datetime
from supriya.tools import nonrealtimetools

this_dir = '/Users/spacecoffin/Development/GravelKicker/__gen_files'

pmtx = gk.generator.gendy1.gen_params(rows=100)

df = gk.generator.gendy1.format_params(pmtx)

df.to_pickle()

pmtx

"""
Explanation: I realized I made a mistake in the design of the Gendy GK module: the module is based on the premise that all arguments to a synth are real valued. The Gendy parameters ampdist and durdist are categorical variables and as such violate the assumption.
End of explanation
"""


%time

for i, row in df.iterrows():
    
    session = nonrealtimetools.Session()
    
    builder = gk.generator.gendy1.make_builder(row)
    
    out = gk.generator.gendy1.build_out(builder)
    
    synthdef = builder.build()
    
    with session.at(0):
        synth_a = session.add_synth(duration=10, synthdef=synthdef)
    
    gk.util.render_session(session, this_dir, row["hash"])

"""
Explanation: Generation/rendering timing
~$0.189$ seconds per example/.aiff.
18.9s for 100
End of explanation
"""


%timeit

for i, row in df.iterrows():
    
    y, sr = librosa.load(os.path.join(this_dir, "aif_files", row["hash"] + ".aiff"))
    
    _y_normed = librosa.util.normalize(y)
    _mfcc = librosa.feature.mfcc(y=_y_normed, sr=sr, n_mfcc=13)
    _cent = np.mean(librosa.feature.spectral_centroid(y=_y_normed, sr=sr))
    
    _mfcc_mean = gk.feature_extraction.get_stats(_mfcc)["mean"]
    
    X_row = np.append(_mfcc_mean, _cent)
    
    if i==0:
        X_mtx = X_row
    else:
        X_mtx = np.vstack((X_mtx, X_row))

"""
Explanation: Feature extraction timing
~$0.88$ seconds per example/.aiff.
1m 28s for 100
End of explanation
"""


for i, row in df.iterrows():
    
    session = nonrealtimetools.Session()
    
    builder = gk.generator.gendy1.make_builder(row)
    
    out = gk.generator.gendy1.build_out(builder)
    
    synthdef = builder.build()
    
    with session.at(0):
        synth_a = session.add_synth(duration=10, synthdef=synthdef)
    
    gk.util.render_session(session, this_dir, row["hash"])
    
    y, sr = librosa.load(os.path.join(this_dir, "aif_files", row["hash"] + ".aiff"))
    
    _y_normed = librosa.util.normalize(y)
    _mfcc = librosa.feature.mfcc(y=_y_normed, sr=sr, n_mfcc=13)
    _cent = np.mean(librosa.feature.spectral_centroid(y=_y_normed, sr=sr))
    
    _mfcc_mean = gk.feature_extraction.get_stats(_mfcc)["mean"]
    
    X_row = np.append(_mfcc_mean, _cent)
    
    if i==0:
        X_mtx = X_row
    else:
        X_mtx = np.vstack((X_mtx, X_row))

X_mtx.shape

def col_rename_4_mfcc(c):
    if (c < 13):
        return "mfcc_mean_{}".format(c)
    else:
        return "spectral_centroid"

pd.DataFrame(X_mtx).rename_axis(lambda c: col_rename_4_mfcc(c), axis=1)

from sklearn import linear_model
from sklearn import model_selection
from sklearn import preprocessing

import sklearn as sk

import matplotlib.pyplot as plt
%matplotlib inline

pmtx.shape

X_mtx.shape

X_mtx[0]

X_train, X_test, y_train, y_test = sk.model_selection.train_test_split(
    X_mtx, pmtx, test_size=0.4, random_state=1)

# Create linear regression objectc
regr = linear_model.LinearRegression()

# Train the model using the training sets
regr.fit(X_train, y_train)

# The coefficients
print('Coefficients: \n', regr.coef_)
# The mean squared error
print("Mean squared error: %.2f"
      % np.mean((regr.predict(X_test) - y_test) ** 2))
# Explained variance score: 1 is perfect prediction
print('Variance score: %.2f' % regr.score(X_test, y_test))

"""
Explanation: Thought: For feature extraction, it would probably be faster to extract all time domain vectors $y$ into a NumPy array and perform the necessary LibROSA operations across the rows of the vector, possibly leveraging under-the-hood efficiencies. 
"1min 43s per loop" below
End of explanation
"""


# Scale data
standard_scaler = sk.preprocessing.StandardScaler()
X_scaled = standard_scaler.fit_transform(X_mtx)
#Xte_s = standard_scaler.transform(X_test)

robust_scaler = sk.preprocessing.RobustScaler()
X_rscaled = robust_scaler.fit_transform(X_mtx)
#Xte_r = robust_scaler.transform(X_test)

X_scaled.mean(axis=0)

X_scaled.mean(axis=0).mean()

X_scaled.std(axis=0)

X_train, X_test, y_train, y_test = sk.model_selection.train_test_split(
    X_scaled, pmtx, test_size=0.4, random_state=1)

# Create linear regression objectc
regr = linear_model.LinearRegression()

# Train the model using the training sets
regr.fit(X_train, y_train)

# The coefficients
print('Coefficients: \n', regr.coef_)
# The mean squared error
print("Mean squared error: %.2f"
      % np.mean((regr.predict(X_test) - y_test) ** 2))
# Explained variance score: 1 is perfect prediction
print('Variance score: %.2f' % regr.score(X_test, y_test))

y_test[0]

X_test[0]

regr.predict(X_test[0])

y_test[0]

"""
Explanation: Preprocessing
End of explanation
"""


