import turicreate as tc
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

"""
Explanation: Using turicreate for easy ML on SEEG dataset
For example, one thing that makes it easy is that turicreate automagically creates dummy variables for categorical features.
End of explanation
"""


sf = tc.SFrame.read_csv('electrodes_clean.csv')
sf.explore() # in GUI

# optional save to SFrame
# sf = tc.SFrame('electrodes_clean.sframe')

"""
Explanation: Reading cleaned data
End of explanation
"""


sf_reg   = sf.remove_column('TPLE category')
sf_class = sf.remove_column('TPLE')

"""
Explanation: Preparing data
We cannot have both TPLE and TPLE category in same set or results will be biased. So create two data sets: one for regression (removing TPLE category as feature) and one for classification (removing TPLE as feature).
Regarding the final (automatically selected) model:
- &lt;model&gt;.summary() summarizes the model parameters
- &lt;model&gt;.features shows which features have been included (= all selected for model building)
End of explanation
"""


sf_reg_train, sf_reg_test = sf_reg.random_split(0.8)
reg_model = tc.regression.create(sf_reg_train, target = 'TPLE')

reg_model.evaluate(sf_reg_test)

reg_model.summary()

"""
Explanation: Regression approach
End of explanation
"""


sf_class_train, sf_class_test = sf_class.random_split(0.8)

class_model = tc.classifier.create(sf_class_train, target = 'TPLE category')

metrics = class_model.evaluate(sf_class_test)
metrics
# metrics['confusion_matrix']

class_model.summary()

"""
Explanation: Classification approach
Multi-class solution
Using TPLE category
End of explanation
"""


# create new dataset - easier when experimenting with different cutoff values
# remove column 'TPLE category' - otherwise we severely bias results
sf_dev = sf_class.remove_column('TPLE category') 

def evaluate_classification_for_cutoff(value):
    '''Creates dataframe with predefined cutoff value. 
    
    Useful to play with different cutoffs. Value represents the deviation in mm.
    Returns metrics of model'''
    sf_dev['Deviated'] = sf['TPLE'].apply(lambda tple: 'yes' if tple > value else 'no')
    sf_dev_train, sf_dev_test = sf_dev.random_split(0.8)
    model = tc.classifier.create(sf_dev_train, target = 'Deviated', verbose = False)
    metrics = model.evaluate(sf_dev_test)
    return metrics
    
cutoff_values = [1.5, 2.0, 2.5, 3.0, 3.5, 4.0]
results = {}

for cv in cutoff_values:
    metr = evaluate_classification_for_cutoff(cv)
    results.update({cv: metr})

plt.figure()
for cutoff, metric in results.items():
    acc = metric['accuracy']; auc = metric['auc']
    print(f"Cutoff {cutoff} - Accuracy: {acc:.2f}  |  AUC: {auc:.2f}")
    plt.plot(cutoff, acc, 'bo', label = 'Accuracy') # Accuracy in BLUE
    plt.plot(cutoff, auc, 'ro', label = 'AUC') # AUC in RED

"""
Explanation: Binary solution
Creating new column "Deviated" (yes/no) based on -arbitrary- cut off value.
End of explanation
"""


