# Path: PyContact/gui/Plotters.py
# class ContactPlotter(MplPlotter):
#     """Plots a frame-score plot with lines."""
# 
#     def plot_contact_figure(self, contact, nsPerFrame):
#         frames = np.arange(0, len(contact.scoreArray), 1) * nsPerFrame
#         self.axes.plot(frames, contact.scoreArray)
#         self.axes.set_xlabel("time [ns]")
#         self.axes.set_ylabel("score")
# 
#     def plot_all_contacts_figure(self, contacts, smooth, nsPerFrame):
#         values = []
# 
#         for frame in range(len(contacts[0].scoreArray)):
#             current = 0
#             for c in contacts:
#                 current += c.scoreArray[frame]
#             values.append(current)
#         frames = np.arange(0, len(values), 1) * nsPerFrame
#         if smooth:
#             val = self.savitzky_golay(np.array(values), smooth, 2)
#             smaller = np.where(val < 0)
#             val[smaller] = 0
#             self.axes.plot(val)
#         else:
#             self.axes.plot(values)
#         self.axes.set_xlabel("time [ns]")
#         self.axes.set_ylabel("score")
# 
#     def plot_hbondNumber(self, contacts, smooth, nsPerFrame):
#         values = []
#         for c in contacts:
#             c.hbondFramesScan()
# 
#         for frame in range(len(contacts[0].scoreArray)):
#             current = 0
#             for c in contacts:
#                 current += c.hbondFrames[frame]
#             values.append(current)
#         frames = np.arange(0, len(values), 1) * nsPerFrame
#         if smooth:
#             val = self.savitzky_golay(np.array(values), smooth, 2)
#             smaller = np.where(val < 0)
#             val[smaller] = 0
#             self.axes.plot(frames, val)
#         else:
#             self.axes.plot(frames, values)
#         self.axes.set_xlabel("time [ns]")
#         self.axes.set_ylabel("hbond number")
# 
#     # from http://scipy.github.io/old-wiki/pages/Cookbook/SavitzkyGolay
#     def savitzky_golay(self, y, window_size, order, deriv=0, rate=1):
# 
#         try:
#             window_size = np.abs(np.int(window_size))
#             order = np.abs(np.int(order))
#         except ValueError:
#             raise ValueError("window_size and order have to be of type int")
#         if window_size % 2 != 1 or window_size < 1:
#             raise TypeError("window_size size must be a positive odd number")
#         if window_size < order + 2:
#             raise TypeError("window_size is too small for the polynomials order")
#         order_range = range(order+1)
#         half_window = (window_size -1) // 2
#         # precompute coefficients
#         b = np.mat([[k**i for i in order_range] for k in range(-half_window, half_window+1)])
#         m = np.linalg.pinv(b).A[deriv] * rate**deriv * factorial(deriv)
#         # pad the signal at the extremes with
#         # values taken from the signal itself
#         firstvals = y[0] - np.abs( y[1:half_window+1][::-1] - y[0] )
#         lastvals = y[-1] + np.abs(y[-half_window-1:-1][::-1] - y[-1])
#         y = np.concatenate((firstvals, y, lastvals))
#         return np.convolve( m[::-1], y, mode='valid')
# 
#     def saveFigure(self, path, outputFormat):
#         self.fig.savefig(path + "." + outputFormat, format=outputFormat)
# 
# Path: PyContact/gui/ErrorBox.py
# class ErrorBox(QMessageBox):
#     """Creates an Error dialog which displays the corresponding error message 'msg'."""
#     def __init__(self, msg):
#         super(ErrorBox, self).__init__()
#         self.msg = msg
#         self.setIcon(QMessageBox.Warning)
#         self.setText(self.msg)
#         self.setWindowTitle("Error")
#         self.setStandardButtons(QMessageBox.Ok)
# 
# Path: PyContact/core/Biochemistry.py
# def mean_score_of_contactArray(contacts):
#     """Computes the mean score using the contacts array."""
#     meanList = []
#     for c in contacts:
#         meanList = np.concatenate((meanList, c.scoreArray), axis=0)
#     return np.mean(meanList)
# 
# def median_score_of_contactArray(contacts):
#     """Computes the mean score using the contacts array."""
#     medianList = []
#     for c in contacts:
#         medianList = np.concatenate((medianList, c.scoreArray), axis=0)
#     return np.median(medianList)


import sip
import os
from PyQt5.QtWidgets import QWidget, QFileDialog
from PyQt5.QtGui import QIntValidator
from .Plotters import ContactPlotter
from .statistics_ui import *
from ..core.LogPool import *
from .ErrorBox import ErrorBox
from ..core.Biochemistry import mean_score_of_contactArray, median_score_of_contactArray




class Statistics(QWidget, Ui_Statistics):
    def __init__(self, data, nspf, parent=None):
        super(QWidget, self).__init__(parent)
        self.setupUi(self)
        self.contacts = data
        self.nsPerFrame = nspf

        self.labelNumFrames.setText(str(len(self.contacts[0].scoreArray)))
        self.labelTotalContacts.setText(str(len(self.contacts)))
        self.labelMeanScore.setText(str(mean_score_of_contactArray(self.contacts)))
        self.labelMedianScore.setText(str(median_score_of_contactArray(self.contacts)))
        self.savePlotButton.clicked.connect(self.savePlot)
        self.plotButton.clicked.connect(self.plotAttribute)

        posIntValidator = QIntValidator()
        posIntValidator.setBottom(3)
        self.smoothStrideField.setValidator(posIntValidator)


# Path: PyContact/gui/Plotters.py
# class ContactPlotter(MplPlotter):
#     """Plots a frame-score plot with lines."""
# 
#     def plot_contact_figure(self, contact, nsPerFrame):
#         frames = np.arange(0, len(contact.scoreArray), 1) * nsPerFrame
#         self.axes.plot(frames, contact.scoreArray)
#         self.axes.set_xlabel("time [ns]")
#         self.axes.set_ylabel("score")
# 
#     def plot_all_contacts_figure(self, contacts, smooth, nsPerFrame):
#         values = []
# 
#         for frame in range(len(contacts[0].scoreArray)):
#             current = 0
#             for c in contacts:
#                 current += c.scoreArray[frame]
#             values.append(current)
#         frames = np.arange(0, len(values), 1) * nsPerFrame
#         if smooth:
#             val = self.savitzky_golay(np.array(values), smooth, 2)
#             smaller = np.where(val < 0)
#             val[smaller] = 0
#             self.axes.plot(val)
#         else:
#             self.axes.plot(values)
#         self.axes.set_xlabel("time [ns]")
#         self.axes.set_ylabel("score")
# 
#     def plot_hbondNumber(self, contacts, smooth, nsPerFrame):
#         values = []
#         for c in contacts:
#             c.hbondFramesScan()
# 
#         for frame in range(len(contacts[0].scoreArray)):
#             current = 0
#             for c in contacts:
#                 current += c.hbondFrames[frame]
#             values.append(current)
#         frames = np.arange(0, len(values), 1) * nsPerFrame
#         if smooth:
#             val = self.savitzky_golay(np.array(values), smooth, 2)
#             smaller = np.where(val < 0)
#             val[smaller] = 0
#             self.axes.plot(frames, val)
#         else:
#             self.axes.plot(frames, values)
#         self.axes.set_xlabel("time [ns]")
#         self.axes.set_ylabel("hbond number")
# 
#     # from http://scipy.github.io/old-wiki/pages/Cookbook/SavitzkyGolay
#     def savitzky_golay(self, y, window_size, order, deriv=0, rate=1):
# 
#         try:
#             window_size = np.abs(np.int(window_size))
#             order = np.abs(np.int(order))
#         except ValueError:
#             raise ValueError("window_size and order have to be of type int")
#         if window_size % 2 != 1 or window_size < 1:
#             raise TypeError("window_size size must be a positive odd number")
#         if window_size < order + 2:
#             raise TypeError("window_size is too small for the polynomials order")
#         order_range = range(order+1)
#         half_window = (window_size -1) // 2
#         # precompute coefficients
#         b = np.mat([[k**i for i in order_range] for k in range(-half_window, half_window+1)])
#         m = np.linalg.pinv(b).A[deriv] * rate**deriv * factorial(deriv)
#         # pad the signal at the extremes with
#         # values taken from the signal itself
#         firstvals = y[0] - np.abs( y[1:half_window+1][::-1] - y[0] )
#         lastvals = y[-1] + np.abs(y[-half_window-1:-1][::-1] - y[-1])
#         y = np.concatenate((firstvals, y, lastvals))
#         return np.convolve( m[::-1], y, mode='valid')
# 
#     def saveFigure(self, path, outputFormat):
#         self.fig.savefig(path + "." + outputFormat, format=outputFormat)
# 
# Path: PyContact/gui/ErrorBox.py
# class ErrorBox(QMessageBox):
#     """Creates an Error dialog which displays the corresponding error message 'msg'."""
#     def __init__(self, msg):
#         super(ErrorBox, self).__init__()
#         self.msg = msg
#         self.setIcon(QMessageBox.Warning)
#         self.setText(self.msg)
#         self.setWindowTitle("Error")
#         self.setStandardButtons(QMessageBox.Ok)
# 
# Path: PyContact/core/Biochemistry.py
# def mean_score_of_contactArray(contacts):
#     """Computes the mean score using the contacts array."""
#     meanList = []
#     for c in contacts:
#         meanList = np.concatenate((meanList, c.scoreArray), axis=0)
#     return np.mean(meanList)
# 
# def median_score_of_contactArray(contacts):
#     """Computes the mean score using the contacts array."""
#     medianList = []
#     for c in contacts:
#         medianList = np.concatenate((medianList, c.scoreArray), axis=0)
#     return np.median(medianList)


# Path: PyContact/gui/Statistics.py
import sip
import os
from PyQt5.QtWidgets import QWidget, QFileDialog
from PyQt5.QtGui import QIntValidator
from .Plotters import ContactPlotter
from .statistics_ui import *
from ..core.LogPool import *
from .ErrorBox import ErrorBox
from ..core.Biochemistry import mean_score_of_contactArray, median_score_of_contactArray





class Statistics(QWidget, Ui_Statistics):
    def __init__(self, data, nspf, parent=None):
        super(QWidget, self).__init__(parent)
        self.setupUi(self)
        self.contacts = data
        self.nsPerFrame = nspf

        self.labelNumFrames.setText(str(len(self.contacts[0].scoreArray)))
        self.labelTotalContacts.setText(str(len(self.contacts)))
        self.labelMeanScore.setText(str(mean_score_of_contactArray(self.contacts)))
        self.labelMedianScore.setText(str(median_score_of_contactArray(self.contacts)))
        self.savePlotButton.clicked.connect(self.savePlot)
        self.plotButton.clicked.connect(self.plotAttribute)

        posIntValidator = QIntValidator()
        posIntValidator.setBottom(3)
        self.smoothStrideField.setValidator(posIntValidator)


        self.contactPlotter = ContactPlotter(None, width=4, height=2, dpi=70)