# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'C:\Users\gwcueff\Documents\Bioinfo\outils_perso\python_germination\PyG_interface_2\interface_v2_2.ui'
#
# Created by: PyQt5 UI code generator 5.15.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.

import sys
import rc_rc
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtGui import QPixmap, QFont
from PyQt5.QtWidgets import (QMainWindow, QFileDialog)
from PyQt5.QtCore import QDir, Qt, QFile, pyqtSlot
from PyQt5.QtWebEngineWidgets import QWebEngineView

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt

from scipy.optimize import curve_fit
from scipy.interpolate import interp1d
from scipy.integrate import quad

import seaborn as sns

import pingouin as pg


app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')

from pygui import Ui_MainWindow
from DataFrameModel import DataFrameModel
from styleSheet import styleSheet


class MyMainWindow(QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.setupUi(self)

        self.setStyleSheet(styleSheet)

    # méthodes nécessaires à l'application

    # méthodes de changement de pages sur clic boutons latéraux de la VBoxLayout

    @pyqtSlot()
    def on_pushButton_1_clicked(self):
        self.stackedWidget.setCurrentIndex(0)

    @pyqtSlot()
    def on_pushButton_2_clicked(self):
        self.stackedWidget.setCurrentIndex(1)

    @pyqtSlot()
    def on_pushButton_3_clicked(self):
        self.stackedWidget.setCurrentIndex(2)

    @pyqtSlot()
    def on_pushButton_4_clicked(self):
        self.stackedWidget.setCurrentIndex(3)

    @pyqtSlot()
    def on_pushButton_5_clicked(self):
        self.stackedWidget.setCurrentIndex(4)

    @pyqtSlot()
    def on_pushButton_6_clicked(self):
        self.stackedWidget.setCurrentIndex(5)

    @pyqtSlot()
    def on_pushButton_7_clicked(self):
        self.stackedWidget.setCurrentIndex(6)

#1_p
    # méthode import bouton import_page1

    def update(self):
        self.label_page1.adjustSize()

    @pyqtSlot()
    def on_import_page1_clicked(self):
        '''
        méthode pour importer des données brutes de germination
        et pour leur affichage dans un objet tableView
        :return: self.data
        '''

        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setFilter(QDir.Files)

        if dialog.exec_():
            self.file_name = dialog.selectedFiles()[0]

        self.label_page1.setText(self.file_name)
        self.update()

        self.data = pd.read_csv(self.file_name, sep=";")

        model_brut = DataFrameModel(self.data)
        self.tableView_page1.setModel(model_brut)

#2_p

    # méthode de calcul des pourcentages

    @pyqtSlot()
    def on_calcul_page2_clicked(self):

        self.data2 = self.data.drop(['echantillon', 'groupe', 'total'], 1)

        self.total= self.data['total']

        self.data3 = pd.DataFrame()

        for i in range(0, self.data2.shape[0]):
            vec = self.data2.iloc[i, :]
            vec2 = round((vec / self.total[i]) * 100, 1)
            vec2 = pd.DataFrame(vec2).transpose()
            self.data3 = pd.concat([self.data3, vec2])

        self.data4 = pd.concat([self.data[["echantillon","groupe"]],self.data3], axis=1)

        model_pourcentage = DataFrameModel(self.data4)
        self.tableView_page2.setModel(model_pourcentage)

        #création très artificielle de la série temporelle : trouver une solution pour l'extraire auto des donnés brutes

        self.ts=[0,8,24,26,28,30,32,34,50,54]

    # méthode d'export d'un tableau affiché dans une TableView

    @pyqtSlot()
    def on_export_page2_clicked(self):

        self.data4.to_csv("tableau_pourcentages.csv", sep=";", decimal=".", index=False)

    # méthode de génération des courbes de germination individuelles

# 3_p

    @pyqtSlot()
    def on_courbe_ind_page3_clicked(self):

        self.titre1_page3 = self.textEdit1_page3.toPlainText()

        curves=[]

        for i in range(0, self.data3.transpose().shape[1]):
            x = np.array(self.ts)
            y = self.data3.transpose().iloc[:, i]
            curves += plt.plot(x, y)


        # plt.pause(0.001)
        plt.title(self.titre1_page3)
        plt.xlabel("temps (heures)")
        plt.ylabel("% germination")
        plt.legend(curves, self.data4['echantillon'], loc=0)
        plt.savefig("courbes_ind.tiff")

        plt.show()
        plt.figure()

        self.image_courbe_ind = QPixmap("courbes_ind.tiff")
        self.image_courbe_ind_2 = self.image_courbe_ind.scaled(450, 500, Qt.KeepAspectRatio, transformMode=QtCore.Qt.SmoothTransformation)
        self.label1_page3.setPixmap(self.image_courbe_ind_2)

    # méthode de génération de courbes de germination groupées

    @pyqtSlot()
    def on_courbe_groupe_page3_clicked(self):

        self.titre2_page3 = self.textEdit2_page3.toPlainText()

        self.data4_mean = pd.DataFrame()

        for name in self.data4.columns[2:]:
            vec = self.data4.groupby('groupe')[name].mean().values
            vec = pd.DataFrame(vec)
            self.data4_mean = pd.concat([self.data4_mean, vec], axis=1, ignore_index=True)

        self.data4_sd = pd.DataFrame()

        for name in self.data4.columns[2:]:
            vec = self.data4.groupby('groupe')[name].std().values
            vec = pd.DataFrame(vec)
            self.data4_sd = pd.concat([self.data4_sd, vec], axis=1, ignore_index=True)

        curves=[]

        for i in range(0, self.data4_mean.shape[0]):
            texte_legend_groupe=self.data4['groupe'].unique().tolist()[i]
            curves += plt.errorbar(np.array(self.ts), self.data4_mean.iloc[i, :], self.data4_sd.iloc[i, :], linestyle='solid',
                                   marker='.', label="{}".format(texte_legend_groupe))
        # plt.pause(0.001)
        plt.title(self.titre2_page3)
        plt.xlabel("temps (heures)")
        plt.ylabel("% germination")
        plt.legend(loc=0)
        plt.savefig("courbes_groupe.tiff")

        plt.show()
        plt.figure()

        self.image_courbe_groupe = QPixmap("courbes_groupe.tiff")
        self.image_courbe_groupe_2 = self.image_courbe_groupe.scaled(450, 500, Qt.KeepAspectRatio, transformMode=QtCore.Qt.SmoothTransformation)
        self.label2_page3.setPixmap(self.image_courbe_groupe_2)

#4_p

    # méthode d'ajustement

    @pyqtSlot()
    def on_calcul_page4_clicked(self):

        def hill_function(x, a, b, c, yo):
            return yo + (a * np.power(x, b) / (np.power(c, b) + np.power(x, b)))

        self.xData = self.ts

        self.xmax = float(self.textEdit5_page4.toPlainText())

        self.x_new = np.linspace(0, self.xmax, 100)

        self.initialParameters = np.array([float(self.textEdit1_page4.toPlainText()),
                                           float(self.textEdit2_page4.toPlainText()),
                                           float(self.textEdit3_page4.toPlainText()),
                                           float(self.textEdit4_page4.toPlainText())])


        # plutôt que d'afficher simplement les données y d'ajustement pour les points de temps d'observation avec des cassures
        # on préfère représenter des courbes lissées = par interpolation

        curves = []

        for i in range(0, self.data3.shape[0]):

            yData = np.array(self.data3.iloc[i, :])

            self.fittedParameters, self.pcov = curve_fit(hill_function, self.xData, yData, self.initialParameters)

            f_new = interp1d(self.xData, hill_function(self.xData, *self.fittedParameters),kind="slinear")

            y_new= f_new(self.x_new)

            curves += plt.plot(self.x_new, y_new)


        plt.title("ajustements")
        plt.xlabel("temps (heures)")
        plt.ylabel("% germination")
        plt.legend(curves, self.data4['echantillon'], loc=0)

        plt.savefig("courbes_ajustement.tiff")

        self.image_courbe_ajustement = QPixmap("courbes_ajustement.tiff")
        self.image_courbe_ajustement_2 = self.image_courbe_ajustement.scaled(451, 391, Qt.KeepAspectRatio,transformMode=QtCore.Qt.SmoothTransformation)
        self.label6_page4.setPixmap(self.image_courbe_ajustement_2)

    @pyqtSlot()
    def on_courbe_page4_clicked(self):

        def hill_function(x, a, b, c, yo):
            return yo + (a * np.power(x, b) / (np.power(c, b) + np.power(x, b)))

        self.xData = self.ts

        self.xmax = float(self.textEdit5_page4.toPlainText())

        self.x_new = np.linspace(0, self.xmax, 100)

        self.initialParameters = np.array(
            [float(self.textEdit1_page4.toPlainText()), float(self.textEdit2_page4.toPlainText()),
             float(self.textEdit3_page4.toPlainText()), float(self.textEdit4_page4.toPlainText())])

        # plutôt que d'afficher simplement les données y d'ajustement pour les points de temps d'observation avec des cassures
        # on préfère représenter des courbes lissées = par interpolation

        curves = []

        for i in range(0, self.data3.shape[0]):
            yData = np.array(self.data3.iloc[i, :])

            self.fittedParameters, self.pcov = curve_fit(hill_function, self.xData, yData, self.initialParameters)

            f_new = interp1d(self.xData, hill_function(self.xData, *self.fittedParameters), kind="slinear")

            y_new = f_new(self.x_new)

            curves += plt.plot(self.x_new, y_new)

        plt.title("ajustements")
        plt.xlabel("temps (heures)")
        plt.ylabel("% germination")
        plt.legend(curves, self.data4['echantillon'], loc=0)
        plt.show()
        plt.figure()

    # méthode de calcul des paramètres de germination après ajustement

    @pyqtSlot()
    def on_param_ind_page4_clicked(self):

        def hill_function(x, a, b, c, yo):
            return yo + (a * np.power(x, b) / (np.power(c, b) + np.power(x, b)))

        def optimized_hill_function(x):
            return self.fittedParameters[3] + (self.fittedParameters[0] * np.power(x, self.fittedParameters[1]) / (
                    np.power(self.fittedParameters[2], self.fittedParameters[1]) + np.power(x, self.fittedParameters[1])))

        self.data6 = pd.DataFrame()

        for i in range(0, self.data3.shape[0]):

            yData = np.array(self.data3.iloc[i, :])

            self.fittedParameters, self.pcov = curve_fit(hill_function, self.xData, yData, self.initialParameters)

            self.xmin = 0

            self.xmax = float(self.textEdit5_page4.toPlainText())

            self.res_integrale, self.err_integrale = quad(optimized_hill_function, self.xmin, self.xmax)

            self.Gmax, self.t50, self.AUC = round(self.fittedParameters[0], 2), round(self.fittedParameters[2], 2), round(
                self.res_integrale, 2)

            self.valeurs_parametres = [self.Gmax, self.t50, self.AUC]

            self.valeurs_parametres = pd.DataFrame(self.valeurs_parametres).transpose()

            self.data6 = self.data6.append(self.valeurs_parametres, ignore_index=True)

        self.data6.columns = ['Gmax', 't50', 'AUC']

        # pour insérer une nelle colonne dans le tableau en définissant sa position (ici en 1ere place)
        # et son intitulé : méthode insert() sur des pandas dataframe : très intéressant !!!

        self.data6.insert(0, 'echantillon', self.data['echantillon'])

        self.model_germination_ind = DataFrameModel(self.data6)
        self.tableView_page4.setModel(self.model_germination_ind)
        # self.tableView_page4.resizeColumnsToContents()

    # méthode de calcul des paramètres de germination par groupe

    @pyqtSlot()
    def on_param_groupe_page4_clicked(self):

        self.data6.insert(1, 'groupe', self.data['groupe'])

        self.data6_mean=pd.DataFrame()

        for name in self.data6.columns[2:]:
            vec = self.data6.groupby('groupe')[name].mean().values
            vec = (round(num,2) for num in vec)
            vec = pd.DataFrame(vec)
            self.data6_mean = pd.concat([self.data6_mean, vec], axis=1, ignore_index=True)

        self.data6_mean.insert(0, 'groupe', self.data['groupe'].unique().tolist())

        self.data6_mean.columns = ['groupe', 'Gmax', 't50', 'AUC']

        self.model_germination_groupe = DataFrameModel(self.data6_mean)
        self.tableView_page4.setModel(self.model_germination_groupe)
        # self.tableView_page4.resizeColumnsToContents()

    # méthode pour export des tableaux de paramètres de germination individuels ou groupés

    @pyqtSlot()
    def on_export_page4_clicked(self):

        self.modele_tableView_page4 = self.tableView_page4.model()

        if self.modele_tableView_page4 is self.model_germination_ind:
            self.data6.to_csv("tableau_parametres_germination_ind.csv", sep=";", decimal=".", index=False)

        else:
            self.data6_mean.to_csv("tableau_parametres_germination_groupe.csv", sep=";", decimal=".", index=False)

# 5_p

    # méthode pour afficher les boxplots des paramètres de germination en fonction du paramètre choisi dans le comboBox (liste déroulante)

    @pyqtSlot()
    def on_pushButton_page5_clicked(self):

        # important : pour éviter la contamination sur le 1er graphe généré, par des données précédentes
        # qui trainent, on commence dans la méthode de création de graphes par un plt.clf() pour nettoyer
        # le contenu matplotlib !!!

        plt.clf()

        # pour n'utiliser le style "whitegrid" de seaborn (quadrillage gris léger en trame de fond)
        # uniquement pour ces boxplots, sans que ça ne se répercute aus fenêtres graphiques suivantes
        # on inclut nos commandes boxplot dans un bloc with: !!!

        with sns.axes_style("whitegrid"):

            self.data7 = pd.concat([self.data6, self.data['groupe']])

            self.titre_boxplot_germination = self.textEdit_page5.toPlainText()

            if self.comboBox_page5.currentText() == "Gmax":


                boxplot = sns.boxplot(x='groupe', y='Gmax', data=self.data7,palette="Set1",linewidth=1,saturation = 2)
                plt.title(self.titre_boxplot_germination)
                plt.ylabel(self.comboBox_page5.currentText())
                plt.show()
                plt.figure()
                boxplot.get_figure().savefig("boxplot_Gmax.tiff")

                self.image_boxplot_Gmax = QPixmap("boxplot_Gmax.tiff")
                self.image_image_Gmax_2 = self.image_boxplot_Gmax.scaled(471, 431, Qt.KeepAspectRatio,
                                                                         transformMode=QtCore.Qt.SmoothTransformation)
                self.label_page5.setPixmap(self.image_image_Gmax_2)


            elif self.comboBox_page5.currentText() == "t50":


                boxplot = sns.boxplot(x='groupe', y='t50', data=self.data7,palette="Set1", linewidth=1, saturation = 2)

                plt.title(self.titre_boxplot_germination)
                plt.ylabel(self.comboBox_page5.currentText())
                plt.show()
                plt.figure()
                boxplot.get_figure().savefig("boxplot_t50.tiff")

                self.image_boxplot_t50 = QPixmap("boxplot_t50.tiff")
                self.image_image_t50_2 = self.image_boxplot_t50.scaled(471, 431, Qt.KeepAspectRatio,
                                                                       transformMode=QtCore.Qt.SmoothTransformation)
                self.label_page5.setPixmap(self.image_image_t50_2)

            elif self.comboBox_page5.currentText() == "AUC":


                boxplot = sns.boxplot(x='groupe', y='AUC', data=self.data7,palette="Set1", linewidth=1, saturation = 2)
                plt.title(self.titre_boxplot_germination)
                plt.ylabel(self.comboBox_page5.currentText())
                plt.show()
                plt.figure()
                boxplot.get_figure().savefig("boxplot_AUC.tiff")

                self.image_boxplot_AUC = QPixmap("boxplot_AUC.tiff")
                self.image_image_AUC_2 = self.image_boxplot_AUC.scaled(471, 431, Qt.KeepAspectRatio,
                                                                       transformMode=QtCore.Qt.SmoothTransformation)
                self.label_page5.setPixmap(self.image_image_AUC_2)

#6_p

    @pyqtSlot()
    def on_anova_page6_clicked(self):

        self.data8=self.data7.drop(labels='echantillon', axis=1)

        aov = pg.anova(data=self.data8, dv='Gmax', between='groupe', detailed=True).round(6)
        self.aov_res_Gmax = pd.DataFrame(aov.T).transpose()
        self.model_anova_Gmax = DataFrameModel(self.aov_res_Gmax)

        aov = pg.anova(data=self.data8, dv='t50', between='groupe', detailed=True).round(6)
        self.aov_res_t50 = pd.DataFrame(aov.T).transpose()
        self.model_anova_t50 = DataFrameModel(self.aov_res_t50)

        aov = pg.anova(data=self.data8, dv='AUC', between='groupe', detailed=True).round(6)
        self.aov_res_AUC = pd.DataFrame(aov.T).transpose()
        self.model_anova_AUC = DataFrameModel(self.aov_res_AUC)

        posthoc = pg.pairwise_ttests(data=self.data8, dv='Gmax', between='groupe', parametric=True, padjust='fdr_bh',
                                     effsize='hedges').round(6)
        self.posthoc_res_Gmax = pd.DataFrame(posthoc.T).transpose()
        self.model_multcomp_Gmax = DataFrameModel(self.posthoc_res_Gmax)

        posthoc = pg.pairwise_ttests(data=self.data8, dv='t50', between='groupe', parametric=True, padjust='fdr_bh',
                                     effsize='hedges').round(6)
        self.posthoc_res_t50 = pd.DataFrame(posthoc.T).transpose()
        self.model_multcomp_t50 = DataFrameModel(self.posthoc_res_t50)
        self.tableView_page6.setModel(self.model_multcomp_t50)

        posthoc = pg.pairwise_ttests(data=self.data8, dv='AUC', between='groupe', parametric=True, padjust='fdr_bh',
                                     effsize='hedges').round(6)
        self.posthoc_res_AUC = pd.DataFrame(posthoc.T).transpose()
        self.model_multcomp_AUC = DataFrameModel(self.posthoc_res_AUC)

        if self.comboBox_page6.currentText() == "Gmax":

            aov = pg.anova(data=self.data8, dv='Gmax', between='groupe', detailed=True).round(6)
            self.aov_res_Gmax = pd.DataFrame(aov.T).transpose()
            self.model_anova_Gmax = DataFrameModel(self.aov_res_Gmax)
            self.tableView_page6.setModel(self.model_anova_Gmax)

        elif self.comboBox_page6.currentText() == "t50":

            aov = pg.anova(data=self.data8, dv='t50', between='groupe', detailed=True).round(6)
            self.aov_res_t50 = pd.DataFrame(aov.T).transpose()
            self.model_anova_t50 = DataFrameModel(self.aov_res_t50)
            self.tableView_page6.setModel(self.model_anova_t50)

        else:

            aov = pg.anova(data=self.data8, dv='AUC', between='groupe', detailed=True).round(6)
            self.aov_res_AUC = pd.DataFrame(aov.T).transpose()
            self.model_anova_AUC = DataFrameModel(self.aov_res_AUC)
            self.tableView_page6.setModel(self.model_anova_AUC)

    @pyqtSlot()
    def on_multcomp_page6_clicked(self):

        self.data8 = self.data7.drop(labels="echantillon",axis=1)

        aov = pg.anova(data=self.data8, dv='Gmax', between='groupe', detailed=True).round(6)
        self.aov_res_Gmax = pd.DataFrame(aov.T).transpose()
        self.model_anova_Gmax = DataFrameModel(self.aov_res_Gmax)

        aov = pg.anova(data=self.data8, dv='t50', between='groupe', detailed=True).round(6)
        self.aov_res_t50 = pd.DataFrame(aov.T).transpose()
        self.model_anova_t50 = DataFrameModel(self.aov_res_t50)

        aov = pg.anova(data=self.data8, dv='AUC', between='groupe', detailed=True).round(6)
        self.aov_res_AUC = pd.DataFrame(aov.T).transpose()
        self.model_anova_AUC = DataFrameModel(self.aov_res_AUC)

        posthoc = pg.pairwise_ttests(data=self.data8, dv='Gmax', between='groupe', parametric=True, padjust='fdr_bh',
                                     effsize='hedges').round(6)
        self.posthoc_res_Gmax = pd.DataFrame(posthoc.T).transpose()
        self.model_multcomp_Gmax = DataFrameModel(self.posthoc_res_Gmax)

        posthoc = pg.pairwise_ttests(data=self.data8, dv='t50', between='groupe', parametric=True, padjust='fdr_bh',
                                     effsize='hedges').round(6)
        self.posthoc_res_t50 = pd.DataFrame(posthoc.T).transpose()
        self.model_multcomp_t50 = DataFrameModel(self.posthoc_res_t50)
        self.tableView_page6.setModel(self.model_multcomp_t50)

        posthoc = pg.pairwise_ttests(data=self.data8, dv='AUC', between='groupe', parametric=True, padjust='fdr_bh',
                                     effsize='hedges').round(6)
        self.posthoc_res_AUC = pd.DataFrame(posthoc.T).transpose()
        self.model_multcomp_AUC = DataFrameModel(self.posthoc_res_AUC)

        if self.comboBox_page6.currentText() == "Gmax":

            posthoc = pg.pairwise_ttests(data=self.data8, dv='Gmax', between='groupe', parametric=True, padjust='fdr_bh',effsize='hedges').round(6)
            self.posthoc_res_Gmax = pd.DataFrame(posthoc.T).transpose()
            self.model_multcomp_Gmax = DataFrameModel(self.posthoc_res_Gmax)
            self.tableView_page6.setModel(self.model_multcomp_Gmax)

        elif self.comboBox_page6.currentText() == "t50":

            posthoc = pg.pairwise_ttests(data=self.data8, dv='t50', between='groupe', parametric=True, padjust='fdr_bh',effsize='hedges').round(6)
            self.posthoc_res_t50 = pd.DataFrame(posthoc.T).transpose()
            self.model_multcomp_t50 = DataFrameModel(self.posthoc_res_t50)
            self.tableView_page6.setModel(self.model_multcomp_t50)
            # self.tableView_page6.resizeColumnsToContents()

        else:

            posthoc = pg.pairwise_ttests(data=self.data8, dv='AUC', between='groupe', parametric=True, padjust='fdr_bh',effsize='hedges').round(6)
            self.posthoc_res_AUC = pd.DataFrame(posthoc.T).transpose()
            self.model_multcomp_AUC = DataFrameModel(self.posthoc_res_AUC)
            self.tableView_page6.setModel(self.model_multcomp_AUC)
            # self.tableView_page6.resizeColumnsToContents()

    @pyqtSlot()
    def on_export_page6_clicked(self):


        if self.tableView_page6.model() is self.model_anova_Gmax :
            self.aov_res_Gmax.to_csv("tableau_anova_Gmax.csv", sep=";", decimal=".", index=False)


        elif self.tableView_page6.model() is self.model_anova_t50:
            self.aov_res_t50.to_csv("tableau_anova_t50.csv", sep=";", decimal=".", index=False)


        elif self.tableView_page6.model() is self.model_anova_AUC:
            self.aov_res_AUC.to_csv("tableau_anova_AUC.csv", sep=";", decimal=".", index=False)


        elif self.tableView_page6.model() is self.model_multcomp_Gmax:
            self.posthoc_res_Gmax.to_csv("tableau_multcomp_Gmax.csv", sep=";", decimal=".", index=False)



        elif self.tableView_page6.model() is self.model_multcomp_t50:
            self.posthoc_res_t50.to_csv("tableau_multcomp_t50.csv", sep=";", decimal=".", index=False)


        else:
            self.posthoc_res_AUC.to_csv("tableau_multcomp_AUC.csv", sep=";", decimal=".", index=False)

# bloc d'exécution

ui = MyMainWindow()
ui.show()
sys.exit(app.exec_())

