__author__ = 'kin_chun'
import numpy as np
from flask import Flask, request, jsonify, render_template, make_response , url_for,redirect
import joblib
import os
import io
import base64
import csv
import pandas
import pydotplus
from pandas.plotting import scatter_matrix
import matplotlib.pyplot as plt
from sklearn import model_selection
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.ensemble import RandomForestClassifier
from six import StringIO
from IPython.display import Image
from sklearn.tree import export_graphviz
import pydotplus
import warnings
import os.path
from sklearn import metrics
from sklearn.metrics import plot_confusion_matrix

warnings.filterwarnings('always')  # "error", "ignore", "always", "default", "module" or "once"
warnings.filterwarnings(action="ignore", message="unclosed", category=ResourceWarning)
warnings.filterwarnings("ignore")

#python to open csv for MAC
folder_MAC = 'C:/Users/Admin/Desktop/CSV file/Backup/Flask Testing/Display'
file_name_MAC = 'Master_MAC_Attack.csv'
file_path_MAC = os.path.join(folder_MAC, file_name_MAC)

#python to open csv for DHCP
folder_DHCP = 'C:/Users/Admin/Desktop/CSV file/Backup/Flask Testing/Display'
file_name_DHCP = 'Master_Spoofing_Attack.csv'
file_path_DHCP = os.path.join(folder_DHCP, file_name_DHCP)

#python to open csv for ICMP
folder_ICMP = 'C:/Users/Admin/Desktop/CSV file/Backup/Flask Testing/Display'
file_name_ICMP = 'Master_ICMP_Attack.csv'
file_path_ICMP = os.path.join(folder_ICMP, file_name_ICMP)

#python to open csv for SYN
folder_SYN = 'C:/Users/Admin/Desktop/CSV file/Backup/Flask Testing/Display'
file_name_SYN = 'Master_SYN_Attack.csv'
file_path_SYN = os.path.join(folder_SYN, file_name_SYN)

app = Flask(__name__)

def plot_classification_report(classificationReport,
                               title='Classification report',
                               cmap='RdBu'):
            classificationReport = classification_report(Y_validation, newpredictions_rfc)
            classificationReport = classificationReport.replace('\n\n', '\n')
            classificationReport = classificationReport.replace(' / ', '/')
            lines = classificationReport.split('\n')

            classes, plotMat, support, class_names = [], [], [], []
            for line in lines[1:]:  # if you don't want avg/total result, then change [1:] into [1:-1]
                t = line.strip().split()
                if len(t) < 2:
                    continue
                classes.append(t[0])
                v = [float(x) for x in t[1: len(t) - 1]]
                support.append(int(t[-1]))
                class_names.append(t[0])
                plotMat.append(v)

            plotMat = np.array(plotMat)
            xticklabels = ['Precision', 'Recall', 'F1-score']
            yticklabels = ['{0} ({1})'.format(class_names[idx], sup)
                           for idx, sup in enumerate(support)]

            plt.imshow(plotMat, interpolation='nearest', cmap='RdBu', aspect='auto')
            plt.title('Classification Report')
            plt.colorbar()
            plt.xticks(np.arange(3), xticklabels, rotation=45)
            plt.yticks(np.arange(len(classes)), yticklabels)

            upper_thresh = plotMat.min() + (plotMat.max() - plotMat.min()) / 10 * 8
            lower_thresh = plotMat.min() + (plotMat.max() - plotMat.min()) / 10 * 2
            for i, j in itertools.product(range(plotMat.shape[0]), range(plotMat.shape[1])):
                plt.text(j, i, format(plotMat[i, j], '.2f'),
                         horizontalalignment="center",
                         color="white" if (plotMat[i, j] > upper_thresh or plotMat[i, j] < lower_thresh) else "black")

            plt.ylabel('Metrics')
            plt.xlabel('Classes')
            plt.tight_layout()
            plt.show()

def plot_classification_report(cr, title='Classification report ', with_avg_total=False, cmap=plt.cm.Blues):

    lines = cr.split('\n')

    classes = []
    plotMat = []

    for line in lines[2 : (len(lines) - 3)]:
        #print(line)
        t = line.split()
        # print(t)
        if(len(t)==0):
            break
        else:
            classes.append(t[0])
            v = [float(x) for x in t[1: len(t) - 1]]
            print(v)
            plotMat.append(v)

    if with_avg_total:
        aveTotal = lines[len(lines) - 1].split()
        classes.append('avg/total')
        vAveTotal = [float(x) for x in t[1:len(aveTotal) - 1]]
        plotMat.append(vAveTotal)

    plt.imshow(plotMat, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    x_tick_marks = np.arange(3)
    y_tick_marks = np.arange(len(classes))
    plt.xticks(x_tick_marks, ['precision', 'recall', 'f1-score'], rotation=45)
    plt.yticks(y_tick_marks, classes)
    plt.tight_layout()
    plt.ylabel('Classes')
    plt.xlabel('Measures')

@app.route('/')
def main():
    return render_template('main.html')

@app.route('/deploy', methods=['POST'])
def deploy():

    attackType = request.form["attack"]
    modelType = request.form['model']
    ratio = request.form['ratio']
    dataset = request.form['dataset']

    if modelType == "lr":
        classifier = LogisticRegression()
    elif modelType == "lda":
        classifier = LinearDiscriminantAnalysis()
    elif modelType == "knn":
        classifier = KNeighborsClassifier()
    elif modelType == "dt":
        classifier = DecisionTreeClassifier()

    if ratio == "ratio70":
        validation_size = 0.30
    elif ratio == "ratio80":
        validation_size = 0.20

    if dataset == "mac_dataset":
        file_path = file_path_MAC
    elif dataset == "dhcp_dataset":
        file_path = file_path_DHCP
    elif dataset == "syn_dataset":
        file_path = file_path_SYN
    elif dataset == "icmp_dataset":
        file_path = file_name_ICMP

    # import dataset
    if dataset == "mac_dataset":
        dataset = pandas.read_csv("Master_MAC_Attack.csv")
    elif dataset == "dhcp_dataset":
        dataset = pandas.read_csv("Master_Spoofing_Attack.csv")
    elif dataset == "syn_dataset":
        dataset = pandas.read_csv("Master_SYN_Attack.csv")
    elif dataset == "icmp_dataset":
        dataset = pandas.read_csv("Master_ICMP_Attack.csv")

    #(Array has to be defined to avoid UnboundLocalError)
    # split dataset
    array = dataset.values
    print (array)
    if attackType == "mac":
        X = array[:,0:6]
        Y = array[:,6]
    elif attackType == "dhcp":
        X = array[:,0:8]
        Y = array[:,8]
    elif attackType == "syn":
        X = array[:,0:8]
        Y = array[:,8]
    elif attackType == "icmp":
        X = array[:,0:8]
        Y = array[:,8]

    # split dataset
    # array = dataset.values
    # print (array)
    # X and Y has already been configure during the attackType
    #X = array[:,0:8]
    #Y = array[:,8]
    # Validation size has been configure during the ratio selection
    #validation_size = 0.30
    seed = 42

    # Split dataset into training set and test set
    X_train, X_validation, Y_train, Y_validation = model_selection.train_test_split(X, Y, test_size=validation_size, random_state=seed)
    X_train_set, X_test, Y_train_set, Y_test = model_selection.train_test_split(X_train, Y_train, test_size=validation_size, random_state=seed)

    # Test options and evaluation metric
    scoring = 'accuracy'

    # Fit algorithm model

    models = []
    models.append(('LR', LogisticRegression()))
    models.append(('LDA', LinearDiscriminantAnalysis()))
    models.append(('KNN', KNeighborsClassifier()))
    models.append(('CART', DecisionTreeClassifier()))

    # evaluate each model in turn
    results = []
    names = []
    for name, model in models:
            kfold = model_selection.KFold(n_splits=5, shuffle=True, random_state=seed)
            cv_results = model_selection.cross_val_score(model, X_train, Y_train, cv=kfold, scoring=scoring)
            results.append(cv_results)
            names.append(name)
            msg = "Highest Accuracy is %s with Accuracy: %f (+/- %f)" % (name, cv_results.mean(), cv_results.std())
            print(msg)

    #Compare Algorithms
    fig = plt.figure()
    fig.suptitle('Algorithm Comparison')
    ax = fig.add_subplot(111)
    plt.boxplot(results)
    ax.set_xticklabels(names)
    # plt.clf()
    # plt.cla()
    # plt.close()

    my_stringIObytes = io.BytesIO()
    plt.savefig(my_stringIObytes, format='png')
    my_stringIObytes.seek(0)
    my_base64_pngData = base64.b64encode(my_stringIObytes.read())
    data_uri = "data:image/png;base64," + my_base64_pngData.decode("ascii")

    #plt.show()

    if modelType == "lr":
        # Testing For Logistic Regression
            print("-------------------------------------------------------")

        # Make predictions on validation dataset
            print("\n Logistic Regression results on test set \n")
        # Create Logistic Regression classifer object
            logistic = LogisticRegression()
        # Train Logistic Regression Classifer
            logistic.fit(X_train_set, Y_train_set)
        #saving the model using joblib
            filename = 'logistic_finalized_DT_model.sav'
            joblib.dump(logistic, filename)
        # load the model from disk
            loaded_model = joblib.load(filename)
            result = loaded_model.score(X_test, Y_test)
            print (result)
        #Predict the response for test dataset
            predictions_rfc = logistic.predict(X_test)
            print("\nLogistic Regression accuracy test: \n")
            print(accuracy_score(Y_test, predictions_rfc))
            print(confusion_matrix(Y_test, predictions_rfc))
            print(classification_report(Y_test, predictions_rfc, zero_division=0))

            Train_Accuracy = accuracy_score(Y_test, predictions_rfc)
            Train_Confusion_Matrix = confusion_matrix(Y_test, predictions_rfc)
            Train_Classification_Report = classification_report(Y_test, predictions_rfc)
            # matrix = plot_confusion_matrix(logistic, X_test, Y_test, cmap=plt.cm.Blues)
            # plt.show()

        # Make predictions on test dataset
            print("\nLogistic Regression results on final validation \n")
            newlogistic = DecisionTreeClassifier()
            newlogistic.fit(X_train_set, Y_train_set)
            newpredictions_rfc = newlogistic.predict(X_validation)
            print("\nLogistic Regression accuracy validation: \n")
            print(accuracy_score(Y_validation, newpredictions_rfc))
            print(confusion_matrix(Y_validation, newpredictions_rfc))
            print(classification_report(Y_validation, newpredictions_rfc))
            df = dataset.reset_index(drop = False)

            Test_Accuracy = accuracy_score(Y_validation, newpredictions_rfc)
            Test_Confussion_Matrix = confusion_matrix(Y_validation, newpredictions_rfc)
            Test_Classification_Report = classification_report(Y_validation, newpredictions_rfc)
            matrix = plot_confusion_matrix(newlogistic, X_test, Y_test, cmap=plt.cm.Blues)
            # plt.show()

            # #Compare Algorithms
            # fig = plt.figure()
            # fig.suptitle('Confusion Matrix')
            # ax = fig.add_subplot(111)
            # plt.boxplot(results)
            # ax.set_xticklabels(names)

            my_stringIObytes = io.BytesIO()
            plt.savefig(my_stringIObytes, format='png')
            my_stringIObytes.seek(0)
            my_base64_pngData = base64.b64encode(my_stringIObytes.read())
            data_uri_matrix = "data:image/png;base64," + my_base64_pngData.decode("ascii")
            plt.close()

            # plot_classification_report(classification_report(Y_validation, newpredictions_rfc) )
            # The following is classification report coding to display visualization (heatmap only)

            lines = classification_report(Y_validation, newpredictions_rfc).split('\n')

            classes = []
            plotMat = []

            for line in lines[2 : (len(lines) - 3)]:
                #print(line)
                t = line.split()
                print(t)
                if(len(t)==0):
                    break
                else:
                    classes.append(t[0])
                    v = [float(x) for x in t[1: len(t) - 1]]
                    print(v)
                    plotMat.append(v)

            # if with_avg_total:
                # aveTotal = lines[len(lines) - 1].split()
                # classes.append('avg/total')
                # vAveTotal = [float(x) for x in t[1:len(aveTotal) - 1]]
                # plotMat.append(vAveTotal)

            plt.imshow(plotMat, interpolation='nearest', cmap=plt.cm.Blues)
            plt.title('Classification report ')
            plt.colorbar()
            x_tick_marks = np.arange(3)
            y_tick_marks = np.arange(len(classes))
            plt.xticks(x_tick_marks, ['precision', 'recall', 'f1-score'], rotation=45)
            plt.yticks(y_tick_marks, classes)
            plt.tight_layout()
            plt.ylabel('Classes')
            plt.xlabel('Measures')
            my_stringIObytes = io.BytesIO()
            plt.savefig(my_stringIObytes, format='png')
            my_stringIObytes.seek(0)
            my_base64_pngData = base64.b64encode(my_stringIObytes.read())
            data_uri_report = "data:image/png;base64," + my_base64_pngData.decode("ascii")

            # plt.close()
            # Classification Report (Not accurate)
            #-----------------------------------------------------------------------------------
            #-----------------------------------------------------------------------------------
            # classificationReport = classification_report(Y_validation, newpredictions_rfc)
            # plot_classification_report(classificationReport)
            # plt.show()

            # Instantiate the classification model and visualizer

    elif modelType == "lda":
        # Testing For Linear Discriminant Analysis
            print("-------------------------------------------------------")
        # Make predictions on validation dataset
            print("\n Linear Discriminant Analysis results on 30% test set \n")
        # Create Logistic Regression classifer object
            lda = LinearDiscriminantAnalysis()
        # Train Linear Discriminant Analysis Classifer
            lda.fit(X_train_set, Y_train_set)
        #saving the model using joblib
            filename = 'lda_finalized_DT_model.sav'
            joblib.dump(lda, filename)
        # load the model from disk
            loaded_model = joblib.load(filename)
            result = loaded_model.score(X_test, Y_test)
            print (result)
        #Predict the response for test dataset
            predictions_rfc = lda.predict(X_test)
            print("\nLinear Discriminant Analysis accuracy test: \n")
            print(accuracy_score(Y_test, predictions_rfc))
            print(confusion_matrix(Y_test, predictions_rfc))
            print(classification_report(Y_test, predictions_rfc, zero_division=0))

            Train_Accuracy = accuracy_score(Y_test, predictions_rfc)
            Train_Confusion_Matrix = confusion_matrix(Y_test, predictions_rfc)
            Train_Classification_Report = classification_report(Y_test, predictions_rfc)
            # matrix = plot_confusion_matrix(lda, X_test, Y_test, cmap=plt.cm.Blues)
            # plt.show()

        # Make predictions on test dataset
            print("\nLinear Discriminant Analysis results on final 30% validation \n")
            newlda = DecisionTreeClassifier()
            newlda.fit(X_train_set, Y_train_set)
            newpredictions_rfc = newlda.predict(X_validation)
            print("\nLinear Discriminant Analysis accuracy validation: \n")
            print(accuracy_score(Y_validation, newpredictions_rfc))
            print(confusion_matrix(Y_validation, newpredictions_rfc))
            print(classification_report(Y_validation, newpredictions_rfc))
            df = dataset.reset_index(drop = False)

            Test_Accuracy = accuracy_score(Y_validation, newpredictions_rfc)
            Test_Confussion_Matrix = confusion_matrix(Y_validation, newpredictions_rfc)
            Test_Classification_Report = classification_report(Y_validation, newpredictions_rfc)
            matrix = plot_confusion_matrix(newlda, X_test, Y_test, cmap=plt.cm.Blues)
            # plt.show()

            # #Compare Algorithms
            # fig = plt.figure()
            # fig.suptitle('Confusion Matrix')
            # ax = fig.add_subplot(111)
            # plt.boxplot(results)
            # ax.set_xticklabels(names)

            my_stringIObytes = io.BytesIO()
            plt.savefig(my_stringIObytes, format='png')
            my_stringIObytes.seek(0)
            my_base64_pngData = base64.b64encode(my_stringIObytes.read())
            data_uri_matrix = "data:image/png;base64," + my_base64_pngData.decode("ascii")
            plt.close()

            lines = classification_report(Y_validation, newpredictions_rfc).split('\n')

            classes = []
            plotMat = []

            for line in lines[2 : (len(lines) - 3)]:
                #print(line)
                t = line.split()
                print(t)
                if(len(t)==0):
                    break
                else:
                    classes.append(t[0])
                    v = [float(x) for x in t[1: len(t) - 1]]
                    print(v)
                    plotMat.append(v)

            plt.imshow(plotMat, interpolation='nearest', cmap=plt.cm.Blues)
            plt.title('Classification report ')
            plt.colorbar()
            x_tick_marks = np.arange(3)
            y_tick_marks = np.arange(len(classes))
            plt.xticks(x_tick_marks, ['precision', 'recall', 'f1-score'], rotation=45)
            plt.yticks(y_tick_marks, classes)
            plt.tight_layout()
            plt.ylabel('Classes')
            plt.xlabel('Measures')
            my_stringIObytes = io.BytesIO()
            plt.savefig(my_stringIObytes, format='png')
            my_stringIObytes.seek(0)
            my_base64_pngData = base64.b64encode(my_stringIObytes.read())
            data_uri_report = "data:image/png;base64," + my_base64_pngData.decode("ascii")

    elif modelType == "knn":
        # Testing For KNeighbors
            print("-------------------------------------------------------")

        # Make predictions on validation dataset
            print("\n KNeighbors results on 30% test set \n")
        # Create K Neighbors classifer object
            KNeighbors = KNeighborsClassifier()
        # Train KNeighbors Classifer
            KNeighbors.fit(X_train_set, Y_train_set)
        #saving the model using joblib
            filename = 'kneighbors_finalized_DT_model.sav'
            joblib.dump(KNeighbors, filename)
        # load the model from disk
            loaded_model = joblib.load(filename)
            result = loaded_model.score(X_test, Y_test)
            print (result)
        #Predict the response for test dataset
            predictions_rfc = KNeighbors.predict(X_test)
            print("\nK Neighbors accuracy test: \n")
            print(accuracy_score(Y_test, predictions_rfc))
            print(confusion_matrix(Y_test, predictions_rfc))
            print(classification_report(Y_test, predictions_rfc, zero_division=0))

            Train_Accuracy = accuracy_score(Y_test, predictions_rfc)
            Train_Confusion_Matrix = confusion_matrix(Y_test, predictions_rfc)
            Train_Classification_Report = classification_report(Y_test, predictions_rfc)
            # matrix = plot_confusion_matrix(KNeighbors, X_test, Y_test, cmap=plt.cm.Blues)
            # plt.show()

        # Make predictions on test dataset
            print("\nK Neighbors results on final 30% validation \n")
            newKNeighbors = DecisionTreeClassifier()
            newKNeighbors.fit(X_train_set, Y_train_set)
            newpredictions_rfc = newKNeighbors.predict(X_validation)
            print("\nK Neighbors accuracy validation: \n")
            print(accuracy_score(Y_validation, newpredictions_rfc))
            print(confusion_matrix(Y_validation, newpredictions_rfc))
            print(classification_report(Y_validation, newpredictions_rfc))
            df = dataset.reset_index(drop = False)

            Test_Accuracy = accuracy_score(Y_validation, newpredictions_rfc)
            Test_Confussion_Matrix = confusion_matrix(Y_validation, newpredictions_rfc)
            Test_Classification_Report = classification_report(Y_validation, newpredictions_rfc)
            matrix = plot_confusion_matrix(newKNeighbors, X_test, Y_test, cmap=plt.cm.Blues)
            # plt.show()

            # #Compare Algorithms
            # fig = plt.figure()
            # fig.suptitle('Confusion Matrix')
            # ax = fig.add_subplot(111)
            # plt.boxplot(results)
            # ax.set_xticklabels(names)

            my_stringIObytes = io.BytesIO()
            plt.savefig(my_stringIObytes, format='png')
            my_stringIObytes.seek(0)
            my_base64_pngData = base64.b64encode(my_stringIObytes.read())
            data_uri_matrix = "data:image/png;base64," + my_base64_pngData.decode("ascii")
            plt.close()

            lines = classification_report(Y_validation, newpredictions_rfc).split('\n')

            classes = []
            plotMat = []

            for line in lines[2 : (len(lines) - 3)]:
                #print(line)
                t = line.split()
                print(t)
                if(len(t)==0):
                    break
                else:
                    classes.append(t[0])
                    v = [float(x) for x in t[1: len(t) - 1]]
                    print(v)
                    plotMat.append(v)

            plt.imshow(plotMat, interpolation='nearest', cmap=plt.cm.Blues)
            plt.title('Classification report ')
            plt.colorbar()
            x_tick_marks = np.arange(3)
            y_tick_marks = np.arange(len(classes))
            plt.xticks(x_tick_marks, ['precision', 'recall', 'f1-score'], rotation=45)
            plt.yticks(y_tick_marks, classes)
            plt.tight_layout()
            plt.ylabel('Classes')
            plt.xlabel('Measures')
            my_stringIObytes = io.BytesIO()
            plt.savefig(my_stringIObytes, format='png')
            my_stringIObytes.seek(0)
            my_base64_pngData = base64.b64encode(my_stringIObytes.read())
            data_uri_report = "data:image/png;base64," + my_base64_pngData.decode("ascii")

    elif modelType == "dt":
        # Make predictions on validation dataset
            print("\n CART results on 30% test set \n")
        # Create Decision Tree classifer object
            cart = DecisionTreeClassifier()
        # Train Decision Tree Classifer
            cart.fit(X_train_set, Y_train_set)
        #saving the model using joblib
            filename = 'decision_finalized_DT_model.sav'
            joblib.dump(cart, filename)
        # load the model from disk
            loaded_model = joblib.load(filename)
            result = loaded_model.score(X_test, Y_test)
            print (result)
        #Predict the response for test dataset
            predictions_rfc = cart.predict(X_test)
            print("\nCART accuracy test: \n")
            print(accuracy_score(Y_test, predictions_rfc))
            print(confusion_matrix(Y_test, predictions_rfc))
            print(classification_report(Y_test, predictions_rfc))

            Train_Accuracy = accuracy_score(Y_test, predictions_rfc)
            Train_Confusion_Matrix = confusion_matrix(Y_test, predictions_rfc)
            Train_Classification_Report = classification_report(Y_test, predictions_rfc)
            # matrix = plot_confusion_matrix(cart, X_test, Y_test, cmap=plt.cm.Blues)
            # plt.show()

        # Make predictions on test dataset
            print("\nCART results on final 30% validation \n")
            newcart = DecisionTreeClassifier()
            newcart.fit(X_train_set, Y_train_set)
            newpredictions_rfc = newcart.predict(X_validation)
            print("\nCART accuracy validation: \n")
            print(accuracy_score(Y_validation, newpredictions_rfc))
            print(confusion_matrix(Y_validation, newpredictions_rfc))
            print(classification_report(Y_validation, newpredictions_rfc))
            df = dataset.reset_index(drop = False)

            Test_Accuracy = accuracy_score(Y_validation, newpredictions_rfc)
            Test_Confussion_Matrix = confusion_matrix(Y_validation, newpredictions_rfc)
            Test_Classification_Report = classification_report(Y_validation, newpredictions_rfc)
            matrix = plot_confusion_matrix(newcart, X_test, Y_test, cmap=plt.cm.Blues)
            # plt.show()

            # #Compare Algorithms
            # fig = plt.figure()
            # fig.suptitle('Confusion Matrix')
            # ax = fig.add_subplot(111)
            # plt.boxplot(results)
            # ax.set_xticklabels(names)

            my_stringIObytes = io.BytesIO()
            plt.savefig(my_stringIObytes, format='png')
            my_stringIObytes.seek(0)
            my_base64_pngData = base64.b64encode(my_stringIObytes.read())
            data_uri_matrix = "data:image/png;base64," + my_base64_pngData.decode("ascii")
            plt.close()

            lines = classification_report(Y_validation, newpredictions_rfc).split('\n')

            classes = []
            plotMat = []

            for line in lines[2 : (len(lines) - 3)]:
                #print(line)
                t = line.split()
                print(t)
                if(len(t)==0):
                    break
                else:
                    classes.append(t[0])
                    v = [float(x) for x in t[1: len(t) - 1]]
                    print(v)
                    plotMat.append(v)
            plt.imshow(plotMat, interpolation='nearest', cmap=plt.cm.Blues)
            plt.title('Classification report ')
            plt.colorbar()
            x_tick_marks = np.arange(3)
            y_tick_marks = np.arange(len(classes))
            plt.xticks(x_tick_marks, ['precision', 'recall', 'f1-score'], rotation=45)
            plt.yticks(y_tick_marks, classes)
            plt.tight_layout()
            plt.ylabel('Classes')
            plt.xlabel('Measures')
            my_stringIObytes = io.BytesIO()
            plt.savefig(my_stringIObytes, format='png')
            my_stringIObytes.seek(0)
            my_base64_pngData = base64.b64encode(my_stringIObytes.read())
            data_uri_report = "data:image/png;base64," + my_base64_pngData.decode("ascii")

    return render_template('deploy.html', data=msg, data2=Train_Accuracy, data3=data_uri_matrix, data4=Test_Classification_Report, comparison_uri=data_uri, data5=Test_Accuracy, data6=Test_Confussion_Matrix, data7=Test_Classification_Report, data8=data_uri_report)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000, debug=True)


import dlib
import numpy as np
import cv2
from matplotlib import pyplot as plt

# create VideoCapture object
cap = cv2.VideoCapture('./video/try1.mp4')

# get original size of frame // 取得原影片畫面尺寸
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# get Frames, fps, code type
fps = cap.get(cv2.CAP_PROP_FPS)  # get Frame Per Second
F_Count = cap.get(cv2.CAP_PROP_FRAME_COUNT)  # get total frames count

# get Frames, fps, code type
fourcc = cv2.VideoWriter_fourcc(*'XVID')  # use FOUR Character Code // 使用 XVID 編碼(MPEG-4)

# create VideoWriter Object // 輸出影片至 output.avi
out = cv2.VideoWriter('./video/test_out.mp4', fourcc, fps, (w, h))

# ------initial settings-------
ag = 0  # frame angle
fsize = 0.1  # frame size
fw = 0  # frame weight

# create kernel // 濾波用矩陣
k = np.ones((7, 7), np.uint8)

# addition for addWeighted
epic = 0

# create Dlib face detector object  # Dlib 的人臉偵測器
detector = dlib.get_frontal_face_detector()

# set the location of Region Of Interest(ROI) // 指定 ROI 座標位置
RECT = ((480, 20), (610, 230))
(left, top), (right, bottom) = RECT

# function for ROI operation
def roiarea(frame):  # 取出 ROI 子畫面
    return frame[top:bottom, left:right]

def replaceroi(frame, roi):  # 將 ROI 區域貼回到原畫面
    frame[top:bottom, left:right] = roi
    return frame

# start playing
while cap.isOpened():
    # read success or not & read frame // ret 讀取成功與否; frame為讀取出來的每一個frame
    ret, frame = cap.read()

    # break if not readable // 未讀取成功則跳出
    if not ret:
        break
    # fixed background // 創建固定背景
    gc = np.full((h, w, 3), 0, dtype='uint8')

    # show basic info of the video(cap)  //  顯示影片基本資訊
    cv2.putText(gc, f'{cap.get(cv2.CAP_PROP_POS_FRAMES)} frames, {cap.get(cv2.CAP_PROP_POS_MSEC):.0f} ms',
                (10, 20), cv2.FONT_HERSHEY_SIMPLEX, .4, (123, 245, 12), 0, cv2.LINE_AA)

    # SHOW TIME !
    # 1.rotate&fade-in
    if cap.get(cv2.CAP_PROP_POS_FRAMES) < 80:
        # control angle and size // 旋轉角度和尺寸控制
        M1 = cv2.getRotationMatrix2D((w / 2, h / 2), ag, fsize)
        frame = cv2.warpAffine(frame, M1, (w, h))
        cv2.putText(gc, "1.rotate & fade-in", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 1,
                    cv2.LINE_AA)
        if ag < 360:
            ag = ag + 360 / 80  # rotate
        if fsize < 1.0:
            fsize = fsize + 0.9 / 80  # increase size
        if cap.get(cv2.CAP_PROP_POS_FRAMES) < 80 / 2 and fw < 1.00:
            fw = fw + 0.01  # add frame weight
        elif cap.get(cv2.CAP_PROP_POS_FRAMES) > 80 / 2 and fw < 1.00:
            fw = fw + 0.04  # add MORE frame weight

    # 2.Split\Merge & Star
    elif 100 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 120:
        star = cv2.xfeatures2d.StarDetector_create()  # create STAR object // 初始化STAR檢測器
        kp = star.detect(frame, None)  # get feature by STAR // 使用STAR尋找特徵點
        frame = cv2.drawKeypoints(frame, kp, None, color=-1)
        cv2.putText(gc, "2.Split&Merge&Star", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0,
                    cv2.LINE_AA)
    elif 120 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 140:
        b, g, r = cv2.split(frame)
        frame = cv2.merge([r, g, b])
        cv2.putText(gc, "2.Split&Merge&Star", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0,
                    cv2.LINE_AA)
    elif 140 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 160:
        star = cv2.xfeatures2d.StarDetector_create()  # create STAR object // 初始化STAR檢測器
        kp = star.detect(frame, None)  # get feature by STAR // 使用STAR尋找特徵點
        frame = cv2.drawKeypoints(frame, kp, None, color=-1)
        cv2.putText(gc, "2.Split&Merge&Star", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0,
                    cv2.LINE_AA)
    elif 160 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 180:
        b, g, r = cv2.split(frame)
        frame = cv2.merge([r, b, g])
        cv2.putText(gc, "2.Split&Merge&Star", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0,
                    cv2.LINE_AA)
    elif 180 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 200:
        star = cv2.xfeatures2d.StarDetector_create()  # create STAR object // 初始化STAR檢測器
        kp = star.detect(frame, None)  # get feature by STAR // 使用STAR尋找特徵點
        frame = cv2.drawKeypoints(frame, kp, None, color=-1)
        cv2.putText(gc, "2.Split&Merge&Star", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0,
                    cv2.LINE_AA)
    elif 200 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 220:
        b, g, r = cv2.split(frame)
        frame = cv2.merge([g, r, b])
        cv2.putText(gc, "2.Split&Merge&Star", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0,
                    cv2.LINE_AA)
    elif 220 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 240:
        star = cv2.xfeatures2d.StarDetector_create()  # 初始化STAR檢測器
        kp = star.detect(frame, None)  # 使用STAR尋找特徵點
        frame = cv2.drawKeypoints(frame, kp, None, color=-1)
        cv2.putText(gc, "2.Split&Merge&Star", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0,
                    cv2.LINE_AA)

    # 3.DLib Face Detect
    elif 240 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 320:
        face_rects, scores, idx = detector.run(frame, 0)  # detect the face // 偵測人臉

        for i, d in enumerate(face_rects):  # get output //  取出所有偵測的結果
            x1 = d.left();
            y1 = d.top();
            x2 = d.right();
            y2 = d.bottom()
            text = f'{scores[i]:.2f}, ({idx[i]:0.0f})'

            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 4, cv2.LINE_AA)  # 以方框標示偵測的人臉
            cv2.putText(frame, text, (x1, y1), cv2.FONT_HERSHEY_DUPLEX,  # 標示分數
                        0.7, (255, 255, 255), 1, cv2.LINE_AA)
        cv2.putText(gc, "3.DLib Face Detect", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0,
                    cv2.LINE_AA)

    # 4.HSV
    elif 320 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 400:
        frame = cv2.cvtColor(frame, cv2.COLOR_HSV2BGR)
        cv2.putText(gc, "4.HSV", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0, cv2.LINE_AA)

    # 5.Canny & ROI
    elif 400 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 480:
        frame = cv2.Canny(frame, 120, 250)
        frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
        roi = roiarea(frame)  # 取出子畫面
        roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)  # BGR to HSV
        frame = replaceroi(frame, roi)  # 將處理完的子畫面貼回到原本畫面中
        cv2.rectangle(frame, RECT[0], RECT[1], (0, 0, 255), 2)  # 在 ROI 範圍處畫個框
        cv2.putText(gc, "5.Canny & ROI", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0, cv2.LINE_AA)

    # 6.Dilate
    elif 480 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 560:
        frame = cv2.dilate(frame, k, iterations=2)
        cv2.putText(gc, "6.Dilate", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0, cv2.LINE_AA)

    # 7.Gradient
    elif 560 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 640:
        frame = cv2.morphologyEx(frame, cv2.MORPH_GRADIENT, k)
        cv2.putText(gc, "7.Gradient", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0, cv2.LINE_AA)

    # 8.Erode
    elif 640 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 720:
        frame = cv2.erode(frame, k, iterations=1)
        cv2.putText(gc, "8.Erode", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0, cv2.LINE_AA)

    # 9.DoG
    elif 720 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 800:
        img_G0 = cv2.GaussianBlur(frame, (3, 3), 0)
        img_G1 = cv2.GaussianBlur(frame, (5, 5), 0)
        frame = img_G0 - img_G1
        cv2.putText(gc, "9.DoG", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 0, cv2.LINE_AA)

    # 10.Fadeout
    elif 800 <= cap.get(cv2.CAP_PROP_POS_FRAMES) < 833:
        cv2.putText(gc, "10.fade-out", (400, 360), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 0), 0, cv2.LINE_AA)
        epic = epic + 10

    # -------- needed --------------------
    c = cv2.waitKey(25)  # wait 25 ms

    if c == 27:  # key escape
        break

    result = cv2.addWeighted(gc, 1, frame, fw, epic)
    cv2.imshow('result', result)
    out.write(result)  # 寫入影格
# -------- code end --------------------
cap.release()
out.release()  # 輸出用
cv2.waitKey(0)
cv2.destroyAllWindows()


import os
import traceback

def read_file_to_string(file_path):
    if not os.path.exists(file_path):
        raise FileNotFoundError('File does not exist.')
    with open(file_path, 'r') as f:
        return f.read()

def read_target(target):
    if not isinstance(target, str):
        raise ValueError('ale2csv needs a string, either raw ALE or a file path.')
    if os.path.exists(target):
        return read_file_to_string(target)
    else:
        return target


# 공포감 수 만큼 사람빼서 그룹만들기
def count_group(data):
    max = data[-1]
    for _ in range(max):
        data.pop()
num = int(input())

data = list(map(int, input().split()))
data.sort() # 마지막 인덱스값이 최대 공포감

count = 0

while len(data) != 0:
    count_group(data)
    count += 1

print(count)


from RPI_Operant.hardware.box import Box
import time
import random
from pathlib import Path
experiment_name = Path(__file__).stem
RUNTIME_DICT = {'vole':000, 'day':1, 'experiment':experiment_name, 'side':1}
USER_HARDWARE_CONFIG_PATH = '/home/pi/RPI_Operant2/RPI_Operant/default_setup_files/default_cooperant_hardware.yaml'
USER_SOFTWARE_CONFIG_PATH = '/home/pi/RPI_Operant2/RPI_Operant/default_setup_files/cooperant_magazine.yaml'

box = Box()

def run():
    box.setup(run_dict=RUNTIME_DICT,
              user_hardware_config_file_path=USER_HARDWARE_CONFIG_PATH,
              user_software_config_file_path=USER_SOFTWARE_CONFIG_PATH,
              start_now=True, simulated = True)

    time.sleep(0.5)

    if RUNTIME_DICT['side'] == 1:
        lever = box.levers.lever_1
        speaker = box.speakers.speaker_1
        dispenser = box.port_dispensers.dispenser_1
    elif RUNTIME_DICT['side'] == 2:
        lever = box.levers.lever_2
        speaker = box.speakers.speaker_2
        dispenser = box.port_dispensers.dispenser_2

    for i in range(1,box.software_config['values']['rounds']+1, 1):

        '''vvvvvvvvvvvvv simulation test stuff vvvvvvvvvvv'''
        r1 = random.random()
        if r1 < 0.8:
            sim_press = True
            press_time = random.random()*(2)
            round_start_for_sim = time.time()

        else:
            sim_press = False

        r2 = random.random()
        if r2 < 0.90:
            sim_retrieve = True
        else:
            sim_retrieve = False

        box.timing.new_round(length = box.software_config['values']['round_length'])
        lever_phase = box.timing.new_phase(f'lever_out', length = box.software_config['values']['lever_out_time'])
        press_timeout = box.timing.new_timeout(length = box.software_config['values']['lever_out_to_dispense_time'])

        press_latency = lever.extend()
        lever.wait_for_n_presses(n=1, latency_obj = press_latency)
        test_phase = box.timing.new_phase('format testing', length = 20)
        while press_timeout.active() and lever_phase.active():

            if sim_press:
                if round_start_for_sim + press_time < time.time():
                    lever.simulate_lever_press()
                    time.sleep(0.05)

            if lever.presses_reached:

                lever.retract()
                lever_phase.end_phase()
                speaker.play_tone(tone_name = 'pellet_tone')
                dispenser.dispense()

        if not lever.presses_reached:
            speaker.play_tone(tone_name = 'pellet_tone')
            dispenser.dispense()

        if sim_retrieve:
            retrieve_time = 3 * random.random()
            retrieve_start = time.time()

        while lever_phase.active():
            ''''''
            if sim_retrieve:
                if retrieve_start + retrieve_time > time.time():
                    dispenser.simulate_retrieved()
                    sim_retrieve = False

        phase = box.timing.new_phase(name ='ITI', length = box.timing.round_time_remaining())
        if not lever.presses_reached:
            lever.retract()

        while not box.timing.round_over():
            ''''''
            if sim_retrieve:
                if retrieve_start + retrieve_time < time.time():
                    dispenser.simulate_retrieved()
                    sim_retrieve = False

        phase.end_phase()

    box.shutdown()

if __name__ == '__main__':
    run()


import pygame
from pygame.locals import *
import sys, subprocess, time

def main():
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    pygame.display.set_caption("Side-scrolling Multiplayer Online Platformer")
    clock = pygame.time.Clock()
    font = pygame.font.Font("./font/cour.ttf", 50)
    hotkey_font = pygame.font.Font("./font/cour.ttf",20,bold=pygame.font.Font.bold)
    hotkey_info_surface = hotkey_font.render("ESC : Back  ENTER : Select",True,(255,255,255))

    buttons = ["JOIN GAME", "HOST GAME", "ADDRESS BOOK", "BACK"]
    menu_item = [0,1,2,3]
    current_item = 0

    screen.fill('Black')
    menu_item[0] = font.render(buttons[0], True, "Black")
    menu_item[1] = font.render(buttons[1], True, "White")
    menu_item[2] = font.render(buttons[2], True, "White")
    menu_item[3] = font.render(buttons[3], True, "White")
    pointer = font.render(">", True, "White")
    highlight = pygame.Surface((400, 60))
    highlight.fill('White')

    pointer_y = 100

    screen.blit(highlight,(140,100+(60*current_item)))

    ## loop to check for mouse action and its position ##
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_DOWN:
                    if pointer_y < 280:
                        screen.fill('Black')
                        pointer_y += 60
                        current_item += 1
                        screen.blit(highlight,(140,100+(60*current_item)))
                        menu_item[current_item] = font.render(buttons[current_item], True, "Black")
                        menu_item[current_item-1] = font.render(buttons[current_item-1], True, "White")

                if event.key == pygame.K_RETURN:
                    if current_item == 2:
                        print("Selected ADDRESS BOOK")
                        import ip_config
                        ip_config.main()

                    if current_item == 1:
                        print("Selected HOST GAME")
                        subprocess.Popen(["py","-3","server.py","127.0.0.1"])
                        time.sleep(1)
                        import game
                        game.main("127.0.0.1")

                    if current_item == 3:
                        print("Selected BACK")
                        import menu
                        menu.main()

                    if current_item == 0:
                        print("Selected JOIN GAME")
                        import join_game
                        join_game.main()

                if event.key == pygame.K_ESCAPE:
                    import menu
                    menu.main()

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP:
                    if pointer_y > 100:
                        screen.fill('Black')
                        pointer_y -= 60
                        current_item -= 1
                        screen.blit(highlight,(140,100+(60*current_item)))
                        menu_item[current_item+1] = font.render(buttons[current_item+1], True, "White")
                        menu_item[current_item] = font.render(buttons[current_item], True, "Black")

        screen.blit(menu_item[0],(150,100+(60*0)))
        screen.blit(menu_item[1],(150,100+(60*1)))
        screen.blit(menu_item[2],(150,100+(60*2)))
        screen.blit(menu_item[3],(150,100+(60*3)))
        screen.blit(pointer,(100,pointer_y))
        screen.blit(hotkey_info_surface,(10,450))

        pygame.display.update()
        clock.tick(60)


class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        chars_map, max_len, l, r, n = {}, 0, 0, 0, len(s)

        while r < n:
            c = s[r]
            if c in chars_map and l <= chars_map[c]:
                l = chars_map[c] + 1
            else:
                max_len = max(max_len, r - l + 1)
            chars_map[c] = r
            r += 1

        return max_len

# 'cbacdabe'

# map
# b 1
# c 3 l 1, r 3
# d 4 l 1, r 4
# l 1 r 5
# a 5
# l 3, r 5
# l 3, r 6


"""
created on 2022.05.13 @barbara
"""

def linha():
    print("______________________________")

print("Bem vindo!")
linha()
print("Esse programa irá calcular uma progressão aritmética")
linha()

S = 0
for x in range (3,333,3):    #range(i,n, p) > gera um intervalo de i a n-1 com intervalo p entre os números.
    S = S + x
print("O resultado da PA é:",S)


PROJECT_NAME = "pcf8583_daughterboard"

import sys, os
here = os.path.dirname(sys.argv[0])
sys.path.insert(0, os.path.join(here, "../../third_party/myelin-kicad.pretty"))
import myelin_kicad_pcb
Pin = myelin_kicad_pcb.Pin

diodes = [
    myelin_kicad_pcb.Component(
        footprint="Diode_SMD:D_SMA",
        identifier="D?",
        value="S1ATR",
        desc="Rectifier diode",
        pins=[
            Pin(1, "1", a),
            Pin(2, "2", k),
        ],
    )
    for a, k in [("5V", "5VD_cat"), ("BATT", "BATTD_cat")]
]

resistors = [
    myelin_kicad_pcb.R0805("47R", "5VD_cat", "NVR_POWER", ref="R1"),
    myelin_kicad_pcb.R0805("47R", "BATTD_cat", "NVR_POWER", ref="R2"),
    myelin_kicad_pcb.R0805("180R", "5VD_cat", "supercap_P", ref="R3"),
]

power_caps = [
    myelin_kicad_pcb.C0805("10u", "GND", "NVR_POWER", ref="C1"),
    myelin_kicad_pcb.C0805("100n", "GND", "NVR_POWER", ref="C2"),
]

supercap = myelin_kicad_pcb.Component(
    footprint="myelin-kicad:dgh255q5r5",
    identifier="C4",
    value="DGH255Q5R5",
    desc="Supercapacitor",
    pins=[
        Pin(1, "1", "supercap_P"),  # positive terminal
        Pin(2, "2", "GND"),  # negative terminal
    ],
)

pcf8583 = [
    myelin_kicad_pcb.Component(
        footprint=fp,
        identifier=ident,
        value="PCF8583",
        pins=[
            Pin( 1, "OSCI", "OSCI"),
            Pin( 2, "OSCO", "OSCO"),
            Pin( 3, "A0",   "GND"),
            Pin( 4, "VSS",  "GND"),
            Pin( 5, "SDA",  "SDA"),
            Pin( 6, "SCL",  "SCL"),
            Pin( 7, "nINT"),
            Pin( 8, "VDD",  "NVR_POWER"),  # TODO battery, not 5V
        ],
    )
    for ident, fp in [
        ("NVRAM", "Package_DIP:DIP-8_W7.62mm"),
        ("NVSMD", "myelin-kicad:so8_pcf8583t_7.5x7.5mm"),
    ]
]

crystal = myelin_kicad_pcb.Component(
    footprint="Crystal:Crystal_AT310_D3.0mm_L10.0mm_Horizontal_1EP_style2",
    identifier="XTAL",
    value="32.768kHz",
    desc="",
    pins=[
        Pin( 1, "", "OSCO"),
        Pin( 2, "", "OSCI"),
        Pin( 3, "", "GND"),
    ],
)

xtal_cap = myelin_kicad_pcb.C0805("15p", "OSCI", "NVR_POWER", ref="C3")

# Batt: three-pin connector with power in the middle and ground on both outer
# pins, to match PL8 on the Master 128

battery = myelin_kicad_pcb.Component(
    footprint="Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical",
    identifier="BATT",
    value="Battery",
    desc="",
    pins=[
        Pin( 1, "BATT-", "GND"),
        Pin( 2, "BATT+", "BATT"),
        Pin( 3, "BATT-", "GND"),
    ],
)

header = myelin_kicad_pcb.Component(
    footprint="Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical",
    identifier="HDR",
    value="Ext",
    desc="4 pin 0.1 inch male header",
    pins=[
        # Probably best to run this through ribbon cable, so SCL gets some
        # shielding.
        Pin( 1, "SDA", "SDA"),
        Pin( 2, "GND", "GND"),
        Pin( 3, "SCL", "SCL"),
        Pin( 4, "5V",  "5V"),
    ],
)

myelin_kicad_pcb.dump_netlist("%s.net" % PROJECT_NAME)
myelin_kicad_pcb.dump_bom("bill_of_materials.txt",
                          "readable_bill_of_materials.txt")


import re
from collections import OrderedDict
from shutil import copy2
from os import makedirs
from os.path import exists, getsize
from os.path import getmtime
from os.path import join as join_path
from xml.etree import ElementTree
from xml.etree.ElementTree import ParseError

from . import BASE_DIR
from . import SYS_PATHS
from . import VM_PATHS
from . import VALID_VIDEO_EXT
from . import XML_FILES

class ProfileError(Exception):
    """Base Exception."""
    pass

class ProfileBlankNameError(ProfileError):
    """Exception for Profile Blank Name."""
    pass

class ProfileBlankPresetError(ProfileError):
    """Exception form Profile Blank Preset."""
    pass

class ProfileBlankParamsError(ProfileError):
    """Exception form Profile Blank Params."""
    pass

class ProfileExtensionError(ProfileError):
    """Exception form Profile Extension Error."""
    pass

class _XMLProfile:
    """Class to manage the xml profiles file."""

    def __init__(self):
        """Class initializer."""
        # Create xml files.
        self._xml_files = XML_FILES
        self._create_xml_files()

    def restore_default_profiles(self):
        """Restore default profiles."""
        self._copy_xml_file(file_name=self._xml_files.customized)

    def add_xml_profile(self, profile_name, preset, params, extension):
        """Add a conversion profile."""
        if not profile_name:
            raise ProfileBlankNameError

        profile_name = profile_name.upper()

        if not preset:
            raise ProfileBlankPresetError

        if not params:
            raise ProfileBlankParamsError

        if not extension.startswith('.') or extension not in VALID_VIDEO_EXT:
            raise ProfileExtensionError('Invalid video file extension')

        extension = extension.lower()

        xml_profile = ElementTree.Element(profile_name)

        xml_preset = self._create_xml_preset(preset, params, extension)

        self._insert_xml_elements(xml_profile=xml_profile,
                                  xml_preset=xml_preset,
                                  xml_root=self._get_xml_root(
                                      self._xml_files.customized))

    def export_xml_profiles(self, dst_dir):
        """Export a file with the conversion profiles."""
        # Raise PermissionError if user doesn't have write permission
        try:
            copy2(src=self._user_xml_file_path(
                file_name=self._xml_files.customized),
                  dst=dst_dir)
        except OSError:
            raise PermissionError

    def import_xml_profiles(self, src_file):
        """Import a conversion profile file."""
        try:
            dst_directory = self._user_xml_file_path(
                self._xml_files.customized)
            copy2(src=src_file, dst=dst_directory)
        except OSError:
            raise PermissionError

    def get_xml_profile_attr(self, target_quality, attr_name='preset_params'):
        """Return a param of ConversionProfile."""
        param_map = {'preset_name': 0,
                     'preset_params': 1,
                     'file_extension': 2,
                     'preset_name_es': 3}

        for xml_file in self._xml_files:
            for element in self._get_xml_root(xml_file_name=xml_file):
                for item in element:
                    if (item[0].text == target_quality or
                            item[3].text == target_quality):
                        return item[param_map[attr_name]].text

    def get_xml_profile_qualities(self, locale):
        """Return a list of available Qualities per conversion profile."""
        qualities_per_profile = OrderedDict()

        for xml_file in self._xml_files:
            for element in self._get_xml_root(xml_file):
                qualities = self._get_qualities(element, locale)
                if element.tag not in qualities_per_profile:
                    qualities_per_profile[element.tag] = qualities
                else:
                    qualities_per_profile[element.tag] += qualities

        return qualities_per_profile

    @staticmethod
    def _get_qualities(element, locale):
        qualities = []
        for item in element:
            if locale == 'es_ES':
                qualities.append(item[3].text)
            else:
                qualities.append(item[0].text)
        return qualities

    def _user_xml_file_path(self, file_name):
        """Return the path to the profiles file."""
        return join_path(self._user_xml_files_directory(), file_name)

    def _insert_xml_elements(self, xml_profile, xml_preset, xml_root):
        """Insert an xml element into an xml root."""
        for i, elem in enumerate(xml_root[:]):
            if elem.tag == xml_profile.tag:
                xml_root[i].insert(0, xml_preset)
                self._save_xml_tree(xml_tree=xml_root)
                break
        else:
            xml_profile.insert(0, xml_preset)
            xml_root.insert(0, xml_profile)
            self._save_xml_tree(xml_tree=xml_root)

    def _save_xml_tree(self, xml_tree):
        """Save the xml tree."""
        xml_profiles_path = self._user_xml_file_path(
            self._xml_files.customized)

        with open(xml_profiles_path, 'wb') as xml_file:
            xml_file.write(b'<?xml version="1.0"?>\n')
            ElementTree.ElementTree(xml_tree).write(xml_file, encoding='UTF-8')

    def _create_xml_files(self):
        """Create a xml file with the conversion profiles."""
        makedirs(self._user_xml_files_directory(), exist_ok=True)

        for xml_file in self._xml_files:
            if not self._xml_file_is_correct(xml_file):
                self._copy_xml_file(file_name=xml_file)

    def _copy_xml_file(self, file_name):
        """Copy profiles xml file."""
        xml_file_sys_path = self._sys_xml_file_path(file_name)
        xml_file_user_path = self._user_xml_file_path(file_name)

        copy2(src=xml_file_sys_path, dst=xml_file_user_path)

    def _xml_file_is_correct(self, file_name):
        """Validate xml files in user config directory."""
        xml_file_user_path = self._user_xml_file_path(file_name)
        xml_file_sys_path = self._sys_xml_file_path(file_name)

        if not exists(xml_file_user_path) or not getsize(xml_file_user_path):
            return False

        if getmtime(xml_file_sys_path) > getmtime(xml_file_user_path):
            return False

        return True

    def _get_xml_root(self, xml_file_name):
        """Return the xml root."""
        path = self._user_xml_file_path(file_name=xml_file_name)
        try:
            tree = ElementTree.parse(path)
        except ParseError:
            self.restore_default_profiles()
            tree = ElementTree.parse(path)
        return tree.getroot()

    @staticmethod
    def _user_xml_files_directory():
        """Return the user xml directory path."""
        return join_path(SYS_PATHS.config, 'profiles')

    @staticmethod
    def _sys_xml_file_path(file_name):
        """Return the path to xml profiles file in the system."""
        file_path = join_path(SYS_PATHS.profiles, file_name)
        if exists(file_path):
            # if VideoMorph is installed
            return file_path

        # if not installed
        return join_path(BASE_DIR, VM_PATHS.profiles, file_name)

    @staticmethod
    def _create_xml_preset(preset, params, extension):
        """Return a xml preset."""
        regexp = re.compile(r'[A-z][0-9]?')
        preset_tag = ''.join(regexp.findall(preset))
        xml_preset = ElementTree.Element(preset_tag)
        xml_preset_name = ElementTree.Element('preset_name')
        xml_preset_name.text = preset
        xml_params = ElementTree.Element('preset_params')
        xml_params.text = params
        xml_extension = ElementTree.Element('file_extension')
        xml_extension.text = extension
        xml_preset_name_es = ElementTree.Element('preset_name_es')
        xml_preset_name_es.text = preset

        for i, elem in enumerate([xml_preset_name, xml_params,
                                  xml_extension, xml_preset_name_es]):
            xml_preset.insert(i, elem)

        return xml_preset

class ConversionProfile:
    """Base class for a Conversion Profile."""

    def __init__(self, prober):
        """Class initializer."""
        self._xml_profile = _XMLProfile()
        self._quality = None
        self.prober = prober
        self.extension = None
        self.params = None

    def __getattr__(self, attr):
        """Delegate to manage the _XMLProfile object."""
        return getattr(self._xml_profile, attr)

    def update(self, new_quality):
        """Set the target Quality and other parameters needed to get it."""
        self._quality = new_quality
        # Update the params and extension when the target quality change
        self.params = self._xml_profile.get_xml_profile_attr(
            target_quality=self._quality,
            attr_name='preset_params')
        self.extension = self._xml_profile.get_xml_profile_attr(
            target_quality=self._quality,
            attr_name='file_extension')

    @property
    def quality_tag(self):
        """Generate a tag from profile quality string."""
        tag_regex = re.compile(r'[A-Z][0-9]?')
        tag = ''.join(tag_regex.findall(self._quality))

        if not tag:
            tag = ''.join(word[0] for word in self._quality.split()).upper()

        return '[' + tag + ']-'


def calcBeauty(sub):
    myDict = {}
    for item in sub:
        if item not in myDict:
            myDict[item] = 0
        else:
            myDict[item] += 1
    max = 0
    min = 500
    for char in myDict:
        if myDict[char] > max:
            max = myDict[char]
        if myDict[char] < min:
            min = myDict[char]
    return max-min

def main(s):
    sumBeauty = 0
    for i in range(len(s)):
        for j in range(len(s)+1):
            sub = s[i:j]
            if len(sub) > 0:
                sumBeauty += calcBeauty(sub)
    print(sumBeauty)

s = input()
main(s)


from cmath import inf
import sys
from itertools import accumulate as ac
input = sys.stdin.readline

N, M = map(int, input().split())
nums = [list(map(int, input().split())) for _ in range(N)]

sum_r = []
for num in nums:
    sum_r.append(list(ac(num)))

sum_c = []
for num in zip(*nums):
    sum_c.append(list(ac(num)))

#행을 먼저 검사
Mx = max(sum_r[0][-1], sum_r[-1][-1])
mx = inf
for i in range(1, N-1):
    mx = min(mx, sum_r[i])

#열도 검사
My = max(sum_c[0][-1], sum_c[-1][-1])


"""
The :py:mod:`vc2_conformance.decoder.picture_syntax` module contains pseudocode
functions from (12) Picture syntax.
"""

from vc2_conformance.pseudocode.metadata import ref_pseudocode

from vc2_conformance.constraint_table import allowed_values_for

from vc2_conformance.pseudocode.slice_sizes import slices_have_same_dimensions

from vc2_conformance.pseudocode.parse_code_functions import is_ld, is_hq

from vc2_conformance.decoder.io import (
    tell,
    byte_align,
    read_uint_lit,
    read_uint,
    read_bool,
)

from vc2_data_tables import (
    WaveletFilters,
    QUANTISATION_MATRICES,
)

from vc2_conformance.level_constraints import LEVEL_CONSTRAINTS

from vc2_conformance.version_constraints import (
    wavelet_transform_version_implication,
)

from vc2_conformance.decoder.assertions import (
    assert_in,
    assert_in_enum,
    assert_level_constraint,
    assert_picture_number_incremented_as_expected,
    log_version_lower_bound,
)

from vc2_conformance.decoder.exceptions import (
    ZeroSlicesInCodedPicture,
    SliceBytesHasZeroDenominator,
    SliceBytesIsLessThanOne,
    NoQuantisationMatrixAvailable,
    BadWaveletIndex,
    BadHOWaveletIndex,
    QuantisationMatrixValueNotAllowedInLevel,
    SliceSizeScalerIsZero,
)

from vc2_conformance.decoder.transform_data_syntax import transform_data

__all__ = [
    "picture_parse",
    "picture_header",
    "wavelet_transform",
    "transform_parameters",
    "extended_transform_parameters",
    "slice_parameters",
    "quant_matrix",
]

@ref_pseudocode
def picture_parse(state):
    """(12.1)"""
    byte_align(state)
    picture_header(state)
    byte_align(state)
    wavelet_transform(state)

@ref_pseudocode
def picture_header(state):
    """(12.2)"""
    state["picture_number"] = read_uint_lit(state, 4)

    # (12.2) Checks that the picture incremented by one, wraps correctly and
    # fields have even-numbered picture numbers first.
    assert_picture_number_incremented_as_expected(state, tell(state))  ## Not in spec

@ref_pseudocode
def wavelet_transform(state):
    """(12.3)"""
    transform_parameters(state)
    byte_align(state)
    transform_data(state)

@ref_pseudocode
def transform_parameters(state):
    """(12.4.1)"""
    state["wavelet_index"] = read_uint(state)

    # (12.4.1) Check wavelet type is supported
    ## Begin not in spec
    assert_in_enum(state["wavelet_index"], WaveletFilters, BadWaveletIndex)
    ## End not in spec

    # (C.3) Check level allows this wavelet type
    ## Begin not in spec
    assert_level_constraint(state, "wavelet_index", state["wavelet_index"])
    ## End not in spec

    state["dwt_depth"] = read_uint(state)

    # (C.3) Check level allows this wavelet depth
    assert_level_constraint(state, "dwt_depth", state["dwt_depth"])  ## Not in spec

    state["wavelet_index_ho"] = state["wavelet_index"]
    state["dwt_depth_ho"] = 0

    if state["major_version"] >= 3:
        extended_transform_parameters(state)

    slice_parameters(state)

    quant_matrix(state)

@ref_pseudocode
def extended_transform_parameters(state):
    """(12.4.4.1)"""
    asym_transform_index_flag = read_bool(state)
    # (C.3) Check level allows an asymmetric transform types
    ## Begin not in spec
    assert_level_constraint(
        state, "asym_transform_index_flag", asym_transform_index_flag
    )
    ## End not in spec

    if asym_transform_index_flag:
        state["wavelet_index_ho"] = read_uint(state)

        # (12.4.4.2) Check wavelet type is supported
        ## Begin not in spec
        assert_in_enum(state["wavelet_index_ho"], WaveletFilters, BadHOWaveletIndex)
        ## End not in spec

        # (C.3) Check level allows this wavelet type
        ## Begin not in spec
        assert_level_constraint(state, "wavelet_index_ho", state["wavelet_index_ho"])
        ## End not in spec

    asym_transform_flag = read_bool(state)
    # (C.3) Check level allows an asymmetric transform depths
    ## Begin not in spec
    assert_level_constraint(state, "asym_transform_flag", asym_transform_flag)
    ## End not in spec

    if asym_transform_flag:
        state["dwt_depth_ho"] = read_uint(state)

        # (C.3) Check level allows this wavelet depth
        ## Begin not in spec
        assert_level_constraint(state, "dwt_depth_ho", state["dwt_depth_ho"])
        ## End not in spec

    # (11.2.2) Log increased minimum version requirements if an asymmetric
    # transform was used.
    ## Begin not in spec
    minimum_required_version = wavelet_transform_version_implication(
        state["wavelet_index"],
        state["wavelet_index_ho"],
        state["dwt_depth_ho"],
    )
    log_version_lower_bound(state, minimum_required_version)
    ## End not in spec

@ref_pseudocode
def slice_parameters(state):
    """(12.4.5.2)"""
    state["slices_x"] = read_uint(state)
    # (C.3) Check level allows this number of horizontal slices
    assert_level_constraint(state, "slices_x", state["slices_x"])  ## Not in spec

    state["slices_y"] = read_uint(state)
    # (C.3) Check level allows this number of vertical slices
    assert_level_constraint(state, "slices_y", state["slices_y"])  ## Not in spec

    # Errata: Spec doesn't prevent zero-slice pictures
    #
    # (12.4.5.2) Must have at least once slice
    ## Begin not in spec
    if state["slices_x"] == 0 or state["slices_y"] == 0:
        raise ZeroSlicesInCodedPicture(state["slices_x"], state["slices_y"])
    ## End not in spec

    # (C.3) Check if this level expects slice counts which result in every
    # slice having the same number of transform components
    ## Begin not in spec
    assert_level_constraint(
        state, "slices_have_same_dimensions", slices_have_same_dimensions(state)
    )
    ## End not in spec

    if is_ld(state):
        state["slice_bytes_numerator"] = read_uint(state)
        # (C.3) Check level allows the specified numerator
        ## Begin not in spec
        assert_level_constraint(
            state, "slice_bytes_numerator", state["slice_bytes_numerator"]
        )
        ## End not in spec

        state["slice_bytes_denominator"] = read_uint(state)
        # (C.3) Check level allows the specified denominator
        ## Begin not in spec
        assert_level_constraint(
            state, "slice_bytes_denominator", state["slice_bytes_denominator"]
        )
        ## End not in spec

        # Errata: spec doesn't disallow a slice_bytes_denominator of zero
        #
        # (12.4.5.2) Must have non-zero slice_bytes denominator (i.e. no divide
        # by zero)
        ## Begin not in spec
        if state["slice_bytes_denominator"] == 0:
            raise SliceBytesHasZeroDenominator(state["slice_bytes_numerator"])
        ## End not in spec

        # Errata: spec doesn't disallow slice_bytes_* values which evaluate to
        # less than one byte.
        #
        # (12.4.5.2) slice_bytes_numerator/slice_bytes_denominator must be
        # greater than or equal to one byte to avoid zero-byte slices in the
        # bitstream.
        ## Begin not in spec
        if state["slice_bytes_numerator"] < state["slice_bytes_denominator"]:
            raise SliceBytesIsLessThanOne(
                state["slice_bytes_numerator"],
                state["slice_bytes_denominator"],
            )
        ## End not in spec

    if is_hq(state):
        state["slice_prefix_bytes"] = read_uint(state)
        # (C.3) Check level allows the specified prefix byte count
        ## Begin not in spec
        assert_level_constraint(
            state, "slice_prefix_bytes", state["slice_prefix_bytes"]
        )
        ## End not in spec

        state["slice_size_scaler"] = read_uint(state)

        # Errata: not enforced in spec
        #
        # (12.4.5.2) slice size scaler should not be zero
        ## Begin not in spec
        if state["slice_size_scaler"] == 0:
            raise SliceSizeScalerIsZero()
        ## End not in spec

        # (C.3) Check level allows the specified slice size scaler
        ## Begin not in spec
        assert_level_constraint(state, "slice_size_scaler", state["slice_size_scaler"])
        ## End not in spec

@ref_pseudocode
def quant_matrix(state):
    """(12.4.5.3)"""
    custom_quant_matrix = read_bool(state)
    # (C.3) Check level allows use of custom quantisation matrices
    ## Begin not in spec
    assert_level_constraint(state, "custom_quant_matrix", custom_quant_matrix)
    ## End not in spec

    if custom_quant_matrix:
        # (C.3) Check that quantisation matrix values are in the level-defined
        # range
        ## Begin not in spec
        allowed_values = allowed_values_for(
            LEVEL_CONSTRAINTS,
            "quant_matrix_values",
            state["_level_constrained_values"],
        )

        def check(quant_matrix_value):
            assert_in(
                quant_matrix_value,
                allowed_values,
                QuantisationMatrixValueNotAllowedInLevel,
                state["_level_constrained_values"],
            )

        ## End not in spec

        # NB: For historical reasons, we use a dict not an array in this
        # implementation.
        ### state["quant_matrix"] = new_array(state["dwt_depth_ho"] + state["dwt_depth"] + 1)
        state["quant_matrix"] = {}  ## Not in spec
        if state["dwt_depth_ho"] == 0:
            state["quant_matrix"][0] = {}
            state["quant_matrix"][0]["LL"] = read_uint(state)
            check(state["quant_matrix"][0]["LL"])  ## Not in spec
        else:
            state["quant_matrix"][0] = {}
            state["quant_matrix"][0]["L"] = read_uint(state)
            check(state["quant_matrix"][0]["L"])  ## Not in spec
            for level in range(1, state["dwt_depth_ho"] + 1):
                state["quant_matrix"][level] = {}
                state["quant_matrix"][level]["H"] = read_uint(state)
                check(state["quant_matrix"][level]["H"])  ## Not in spec
        for level in range(
            state["dwt_depth_ho"] + 1, state["dwt_depth_ho"] + state["dwt_depth"] + 1
        ):
            state["quant_matrix"][level] = {}
            state["quant_matrix"][level]["HL"] = read_uint(state)
            check(state["quant_matrix"][level]["HL"])  ## Not in spec
            state["quant_matrix"][level]["LH"] = read_uint(state)
            check(state["quant_matrix"][level]["LH"])  ## Not in spec
            state["quant_matrix"][level]["HH"] = read_uint(state)
            check(state["quant_matrix"][level]["HH"])  ## Not in spec
    else:
        # (12.4.5.3) If no custom quantisation matrix has been specified, a
        # default table must be available
        ## Begin not in spec
        configuration = (
            state["wavelet_index"],
            state["wavelet_index_ho"],
            state["dwt_depth"],
            state["dwt_depth_ho"],
        )
        if configuration not in QUANTISATION_MATRICES:
            raise NoQuantisationMatrixAvailable(*configuration)
        ## End not in spec

        set_quant_matrix(state)

@ref_pseudocode(deviation="inferred_implementation")
def set_quant_matrix(state):
    """(12.4.5.3)"""
    state["quant_matrix"] = QUANTISATION_MATRICES[
        (
            state["wavelet_index"],
            state["wavelet_index_ho"],
            state["dwt_depth"],
            state["dwt_depth_ho"],
        )
    ]


#coding:utf-8
'''
    石头剪刀布
'''
import random
player = int(input("0剪刀，1石头，2布"))
computer = random.randint(0,2)

if (player == 0 and computer == 2) or (player == 1 and computer == 0) or (player==2 and computer ==1):
    print("winner")
elif (player == computer):
    print("平局")
else:
    print("fail")


#!/usr/bin/env python

#=============================================================================
# Created by Michael Notter
# at OHBM 2016 Brainhack in Lausanne, June 2016
# Edited with more comments by Kirstie Whitaker
# at Cambridge Brainhack-Global 2017, March 2017
# Contact: kw401@cam.ac.uk
#=============================================================================

#=============================================================================
# IMPORTS
#=============================================================================
import argparse
import future        # pip install future
from glob import glob as gg
import os
from os.path import join as opj
from os.path import basename as opb
import sys
import textwrap

import numpy as np
from matplotlib import pylab
from matplotlib import pyplot as plt
import nibabel as nb
import nilearn
from nipy.labs import viz
from scipy.ndimage import label as sci_label

#=============================================================================
# FUNCTIONS
#=============================================================================
def setup_argparser():
    '''
    Code to read in arguments from the command line
    Also allows you to change some settings
    '''
    # Build a basic parser.
    help_text = ('Show the locations of clusters in a statistical map in MNI space.')

    sign_off = 'Author: Kirstie Whitaker <kw401@cam.ac.uk>'

    parser = argparse.ArgumentParser(description=help_text,
                                     epilog=sign_off,
                                     formatter_class=argparse.RawTextHelpFormatter)

    # Now add the arguments
    parser.add_argument(dest='stats_file',
                            type=str,
                            metavar='stats_file',
                            help=textwrap.dedent('3D nifti file in MNI space containing the statistical values\n ' +
                                                  'you want to visualise.\n' +
                                                  'Note that this file can be pre-thresholded or not.\n' +
                                                  'If your file is already thresholded then you will need to\n ' +
                                                  'pass an argument to the -t option otherwise it will default to 2.3.\n ' +
                                                  'A suggested value is 0.01.' ))

    parser.add_argument('-ce, --cluster_extent',
                            type=str,
                            metavar='cluster_extent',
                            help=textwrap.dedent("Minimum cluster extent for a region to be included in the visualisation\n (integer)\n Default: 20"),
                            default=20)

    parser.add_argument('-t, --cluster_thr',
                            type=str,
                            metavar='threshold',
                            help=textwrap.dedent("Minimum statistical value for a region to be included in the visualisation\n (float)\n Default: 2.3"),
                            default=2.3)

    parser.add_argument('--csv',
                            action='store_true',
                            help=textwrap.dedent('Create a csv file with cluster information.\n Default: False'),
                            default=False)

    parser.add_argument('--cluster_title',
                            action='store_true',
                            help=textwrap.dedent('Show cluster information in the title of the plot.\n Default: False'),
                            default=False)

    parser.add_argument('-c', '--cmap',
                            type=str,
                            metavar='cmap',
                            help=textwrap.dedent('Any matplotlib colormap listed at\n  http://matplotlib.org/examples/color/colormaps_reference.html\n Default: RdBu_r'),
                            default='hot')

    parser.add_argument('-cb', '--cbar',
                            action='store_true',
                            help=textwrap.dedent('Display a colorbar on the right of the plots\n Default: False'),
                            default=False)

    parser.add_argument('--black_bg',
                            action='store_true',
                            help=textwrap.dedent('Set the background to black.\n Default: White'),
                            default=False)
    """
    parser.add_argument('--thr_abs',
                            type=float,
                            metavar='thr_abs',
                            help=textwrap.dedent('Mask the input image such that all values\n  which have an absolute value less than this threshold\n  are not shown.\nIf None then no thresholding is undertaken.\nDefault: None'),
                            default=None)

    parser.add_argument('--thr_pos',
                            type=float,
                            metavar='thr_pos',
                            help=textwrap.dedent('Mask the input image such that all values\n  less than this threshold are not shown.\nIf None then no thresholding is undertaken.\nDefault: None'),
                            default=None)
    parser.add_argument('-l', '--lower',
                            type=float,
                            metavar='lowerthr',
                            help='Lower limit for colormap',
                            default=None)

    parser.add_argument('-u', '--upper',
                            type=float,
                            metavar='upperthr',
                            help='Upper limit for colormap',
                            default=None)
    """

    parser.add_argument('--dpi',
                            type=float,
                            metavar='dpi',
                            help='DPI of output png file\n Default: 300',
                            default=300)

    parser.add_argument('--format',
                            type=float,
                            metavar='format',
                            help=textwrap.dedent('Format of the output image file.\n Eg: png, pdf, tif, jpeg, svg. \n Default: png'),
                            default='png')

    arguments = parser.parse_args()

    return arguments, parser

def get_labels(data, cluster_thr=0, min_extent=0):
    """
    Get number of clusters in dataset as well as a labeled volume
    Minimal extent of each cluster and voxel-vise threshold can be specified
    """

    # Threshold the data by zeroing all voxels with values that have an
    # absolute value less than the cluster threshold
    thr_data = abs(data) > cluster_thr

    # Find all the clusters in the thresholded data
    labels, nlabels = sci_label(thr_data)

    # Now loop through all the clusters
    # and if a cluster is smaller than the minimum cluster extent
    # exclude it from the list (set the values to zero)
    for idx in range(1, nlabels + 1):
        if np.sum(labels == idx) < min_extent:
            labels[labels == idx] = 0

    # Re-run the clustering command to get only the clusters
    # that are larger than the minimum extent
    labels, nlabels = sci_label(labels)

    # overwrites the input data with the thresholded data
    binarized_data = labels.astype('bool')
    data[np.invert(binarized_data)] = 0

    return labels, nlabels, data, binarized_data

def get_cluster_info(img, affine, data):
    """
    Returns peak coordinations and cluster information of a given dataset,
    if labeled file and affine is provided
    """

    # Set up some variables we're going to need
    coords = []          #
    cs = []              # cluster sum values
    maxcoords = []       # peak coordinate locations
    clusterInfo = []     # list of lists containing max, min,
                         # mean and std of the cluster

    # Find all the label ids (that aren't 0!)
    labelID = np.setdiff1d(np.unique(img.ravel()), [0])

    # Loop through the labels
    for lab in labelID:
        # Calculate the voume of the cluster
        sumval = np.sum(img == lab)
        cs.append(sumval)

        # Calculate the max, min, mean and std of the cluster
        maxval = np.max(data[img == lab])
        minval = np.min(data[img == lab])
        meanval = np.mean(data[img == lab])
        stdval = np.std(data[img == lab])

        # Save these values in a list
        clusterInfo.append([sumval, maxval, minval, meanval, stdval])

        # Get the location of the peak coordinate
        maxidx = np.nonzero(np.multiply(data, img == lab) == maxval)
        maxcoords.append([m[0] for m in maxidx])

    # Transform the lists into numpy arrays
    maxcoords = np.asarray(maxcoords)
    clusterInfo = np.asarray(clusterInfo)

    # Sort the lists by the volume of the clusters
    maxcoords = maxcoords[np.argsort(cs)[::-1], :]
    clusterInfo = clusterInfo[np.argsort(cs)[::-1], :]

    # Loop through the clusters and put the peak coordinates
    # in MNI space
    for i, lab in enumerate(labelID[np.argsort(cs)[::-1]]):
        coords.append(np.dot(affine,
                             np.hstack((maxcoords[i], 1)))[:3].tolist())

    # Add the peak coordinate information to the clusterInfo array
    clusterInfo = np.hstack((np.array(coords), clusterInfo))

    # Returns peak coordination and additional cluster infos
    return coords, clusterInfo

def show_slices(data, affine,
                    coords=None,
                    cmap=None,
                    show_colorbar=None,
                    showCross=False,
                    cluster_thr=0,
                    annotate=True,                              ###### KW DOCUMENT
                    template='../scripts/templates/MNI152_T1_1mm_brain.nii.gz', ####### KW DOCUMENT
                    dpiRes=300,
                    suffix='png',
                    show_title=False):

    # Prepare background image
    anatimg = nb.load(template)
    anatdata, anataff = anatimg.get_data(), anatimg.affine()
    anatdata = anatdata.astype(np.float)
    anatdata[anatdata < 10.] = np.nan

    # Create output figure for each peak coordinate
    # (so a different figure for each cluster)
    for idx, coord in enumerate(coords):

        # Name the output file to include the cluster id,
        # the cluster threshold and the minimum cluster extent
        outfile = 'Cluster_{}_thr{:04.2f}_minext{:03:0f}'.format(idx, cluster_thr, cluster_extent)

        # If show_title argument has been set to true then print the file name
        # and the peak coordinates in the title of the figure
        if show_title:
            title = '{} {}'.format(outfile + coord)
        else:
            title = ''

        # Woooo plot three orthogonal views of the cluster sliced through the
        # peak coordinate
        osl = viz.plot_map(
                    np.asarray(data), affine, anat=anatdata, anat_affine=anataff,
                    threshold=cluster_thr, cmap=cmap, annotate=annotate,
                    black_bg=False, cut_coords=coord, draw_cross=showCross,
                    slicer='ortho', title=title)

        # If the show colorbar option is true then show the color bar on the
        # right hand side of the image
        if show_colorbar:
            cbarLocation = [-0.1, 0.2, 0.015, 0.6]
            im = plt.gca().get_images()[1]
            cb = plt.colorbar(im, cax=plt.axes(cbarLocation),
                              orientation='horizontal', format='%.2f')
            cb.set_ticks([cb._values.min(), cb._values.max()])

        # Save the figure!
        osl.frame_axes.figure.savefig(
            opj(output_folder, '{}.{}'.format(outfile, suffix)),
            dpi=dpiRes, bbox_inches='tight', transparent=True)

        # DONE! Close the plot
        plt.close()

#=============================================================================
# SET SOME VARIABLES
#=============================================================================
# Read in the arguments from argparse
arguments, parser = setup_argparser()

stats_file = arguments.stats_file
cluster_extent = arguments.cluster_extent
cluster_thr = arguments.cluster_thr
store_csv = arguments.csv
cluster_title = arguments.cluster_title
cmap = arguments.cmap
show_colorbar = arguments.cbar
#thr_abs = arguments.thr_abs
#thr_pos = arguments.thr_pos
#black_bg = arguments.black_bg
#lower_thresh = arguments.lower
#upper_thresh = arguments.upper
dpi = arguments.dpi
image_format = arguments.format

# Set a couple of hard coded options
#symmetric_cbar=False

#===============================================================================
# Get the colormap from nilearn
#===============================================================================
if hasattr(cm, cmap):
    cmap = getattr(cm, cmap)

#===============================================================================
# Create the output folder
#===============================================================================
output_folder = '{}_CLUSTERS'.format(stats_file.rsplit('.nii', 1)[0])

if not os.isdir(output_folder):
    os.path.makedirs(output_folder)

def create_output(stats_file, cluster_extent, threshold, template, create_CSV,
                  show_cross, annotate_figure, cmap, show_colorbar,
                  show_title, dpi, imageType):

    # Read in the stats file
    img = nb.load(stats_file)
    data = img.get_data()
    affine = img.affine()

    # Find the clusters
    labels, nlabels, data, binarized_data = get_labels(data,
                                                       cluster_thr=cluster_thr,
                                                       min_extent=cluster_extent)

    # Catch if nlabels is 0, i.e. no clusters survived thresholding
    if nlabels == 0:
        print('No clusters survive the thresholds in {}'.format(stats_file))
        return

    # If there *are* cluster though, then get the cluster information
    # for each of them
    print('{} clusters were found in {}'.format(nlabels, stats_file))
    coords, clusterInfo = get_cluster_info(labels, affine, data)

    """
    # Get file prefix
    if filePath.endswith('.nii'):
        filename = opb(filePath)[:-4]
    elif filePath.endswith('.nii.gz'):
        filename = opb(filePath)[:-7]
    """

    # Create output folder
    output_folder = '{}_CLUSTERS'.format(stats_file.rsplit('.nii', 1)[0])
    if not os.isdir(output_folder):
        os.path.makedirs(output_folder)

    # Create figures
    show_slices(data, affine,
                        coords=coords,
                        cmap=cmap,
                        show_colorbar=show_colorbar,
                        showCross=False,                            ####### KW THINK ABOUT
                        cluster_thr=cluster_thr,
                        annotate=True,                              ###### KW DOCUMENT
                        template='../scripts/templates/MNI152_T1_1mm_brain.nii.gz', ####### KW DOCUMENT
                        dpiRes=dpi,
                        suffix=image_format,
                        show_title=show_title)

    # Create CSV output
    if create_CSV:
        header = 'X,Y,Z,Size,Max,Min,Mean,Std'
        np.savetxt(
            opj('figures', filename, 'cluster_info.csv'), clusterInfo,
            delimiter=',', fmt='%.8f', header=header, comments='')

        # Print cluster info in terminal
        row_format = "{:>8}{:>8}{:>8}{:>10}{:>16}{:>16}{:>16}{:>16}"
        print(row_format.format(
            *['X', 'Y', 'Z', 'Size', 'Max', 'Min', 'Mean', 'Std']))
        for c in clusterInfo:
            print(row_format.format(*c))
        print('\n')

#===============================================================================
# Save the figure
#===============================================================================
output_folder = '{}_CLUSTERS'.format(stats_file.rsplit('.nii', 1)[0])

if not os.isdir(output_folder):
    os.path.makedirs(output_folder)

if __name__ == "__main__":

    cluster_extend = int(sys.argv[1])
    threshold = float(sys.argv[2])
    template = str(sys.argv[3])
    create_CSV = bool(sys.argv[4])
    show_cross = bool(sys.argv[5])
    annotate_figure = bool(sys.argv[6])
    show_colorbar = bool(sys.argv[7])
    colorbar_orientation = str(sys.argv[8])
    show_title = bool(sys.argv[9])
    dpi = int(sys.argv[10])
    imageType = str(sys.argv[11])
    prefix = str(sys.argv[12])

    #=========================================================================
    # SET SOME VARIABLES
    #=========================================================================
    # Read in the arguments from argparse
    arguments, parser = setup_argparser()

    stats_file = arguments.stats_file
    cluster_extent = arguments.cluster_extent
    cluster_thr = arguments.cluster_thr
    store_csv = arguments.csv
    cluster_title = arguments.cluster_title
    cmap = arguments.cmap
    show_colorbar = arguments.cbar
    #thr_abs = arguments.thr_abs
    #thr_pos = arguments.thr_pos
    #black_bg = arguments.black_bg
    #lower_thresh = arguments.lower
    #upper_thresh = arguments.upper
    dpi = arguments.dpi
    image_format = arguments.format

    #===============================================================================
    # Get the colormap from nilearn
    #===============================================================================
    if hasattr(cm, cmap):
        cmap = getattr(cm, cmap)

    #===============================================================================
    # Create the output folder
    #===============================================================================
    output_folder = '{}_CLUSTERS'.format(stats_file.rsplit('.nii', 1)[0])

    if not os.isdir(output_folder):
        os.path.makedirs(output_folder)

    #===============================================================================
    # Create the figures and CSV output
    #===============================================================================
    create_output(stats_file, cluster_extent, threshold, template, create_CSV,
                      show_cross, annotate_figure, cmap, show_colorbar,
                      show_title, dpi, imageType)