from DataVisualization import DataVisualization
from Header import Header
from Navigation import Navigation
from PetrophysicsTopBar import PetrophysicsTopBar
from PetrophysicsOptions import PetrophysicsOptions
from PlotViewer import PlotViewer
from Spreadsheet import Spreadsheet, SpreadsheetControls
from StatisticsOptions import StatisticsOptions
from StatisticsTopBar import StatisticsTopBar
from PySide2.QtWidgets import QMainWindow, QStackedLayout, QWidget, QDockWidget, QVBoxLayout, QApplication, QSizePolicy, \
    QScrollArea, QFileDialog, QMessageBox, QLabel, QStatusBar
from PySide2.QtCore import Qt, Signal
from PySide2.QtGui import QIcon
import Data
import sys
from HandlerThread import HandlerThread
from Regressions import regressionManifold
from Statistics import statisticsManifold
from Boxplot import boxplotManifold
from Histogram import histogramManifold
from DockWidgetRibbon import DockWidgetRibbon
from KozenyCarman import kCarmanManifold
from Lucia import luciaManifold
from FlowZones import fzManifold
from Winland import winlandManifold
from DykstraParsons import dParsonsManifold
from TimurCoates import tCoatesManifold
from PlotControls import PlotControls
from PlotControleEngine import pceManifold

class MainWindow(QMainWindow):
    changePage = Signal(bool)
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Petro-Explorer v1.0')
        win_icon = QIcon('icons/Logo.ico')
        self.setWindowIcon(win_icon)
        self.setStyleSheet('background-color: #363f49;')

        self.header = Header()
        self.navigation = Navigation()
        self.p_top_bar = PetrophysicsTopBar()
        self.s_top_bar = StatisticsTopBar()
        self.p_options_1 = PetrophysicsOptions(_mode='KCarman')
        self.p_options_2 = PetrophysicsOptions(_mode='TCoates')
        self.p_options_3 = PetrophysicsOptions(_mode='Winland')
        self.p_options_4 = PetrophysicsOptions(_mode='RQIFZI')
        self.p_options_5 = PetrophysicsOptions(_mode='Lucia')
        self.p_options_6 = PetrophysicsOptions(_mode='DParsons')
        self.s_options_1 = StatisticsOptions(_mode='Regression')
        self.s_options_2 = StatisticsOptions(_mode='Statistics')
        self.s_options_3 = StatisticsOptions(_mode='Histogram')
        self.s_options_4 = StatisticsOptions(_mode='Boxplot')
        self.sp_controls = SpreadsheetControls()
        self.plot_controls = PlotControls()
        self.plot_viewer = PlotViewer()
        self.spreadsheet = Spreadsheet()
        self.status_bar = QStatusBar()

        self.scroll_area_1 = QScrollArea()
        self.scroll_area_1.setWidget(self.spreadsheet)
        self.scroll_area_1.setWidgetResizable(True)

        self.scroll_area_2 = QScrollArea()
        self.scroll_area_2.setWidget(self.plot_viewer)
        self.scroll_area_2.setWidgetResizable(True)

        self.bar_widget = QWidget()
        self.bar_widget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum)

        self.central_widget = QWidget()
        self.options_widget = QWidget()

        self.docking_options = QDockWidget()
        self.docking_options.setWidget(self.options_widget)
        self.docking_options.setTitleBarWidget(DockWidgetRibbon(' Opções de cálculo'))

        self.docking_options2 = QDockWidget()
        self.docking_options2.setWidget(self.sp_controls)
        self.docking_options2.setTitleBarWidget(DockWidgetRibbon(' Controles de visualização'))

        self.setCentralWidget(self.central_widget)
        self.setStatusBar(self.status_bar)
        self.addToolBar(self.navigation)
        self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.docking_options)
        self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.docking_options2)
        self.connections()
        self.buildLayout()

        self.centralWidget().setStyleSheet('background-color: #2e3843')
        self.spreadsheet.setStyleSheet('background-color: white')
        self.status_bar.setStyleSheet('color: white')

    def buildLayout(self):
        stacked_layout_1 = QStackedLayout()
        # stacked_layout_1.addWidget(QWidget())
        stacked_layout_1.addWidget(self.p_top_bar)
        stacked_layout_1.addWidget(self.s_top_bar)

        stacked_layout_2 = QStackedLayout()
        # stacked_layout_2.addWidget(QWidget())
        stacked_layout_2.addWidget(self.p_options_1)
        stacked_layout_2.addWidget(self.p_options_2)
        stacked_layout_2.addWidget(self.p_options_3)
        stacked_layout_2.addWidget(self.p_options_4)
        stacked_layout_2.addWidget(self.p_options_5)
        stacked_layout_2.addWidget(self.p_options_6)
        stacked_layout_2.addWidget(self.s_options_1)
        stacked_layout_2.addWidget(self.s_options_2)
        stacked_layout_2.addWidget(self.s_options_3)
        stacked_layout_2.addWidget(self.s_options_4)

        self.stacked_layout_3 = QStackedLayout()
        self.stacked_layout_3.addWidget(self.scroll_area_1)
        self.stacked_layout_3.addWidget(self.scroll_area_2)

        central_widget_layout = QVBoxLayout()
        central_widget_layout.addWidget(self.bar_widget)
        central_widget_layout.addLayout(self.stacked_layout_3)

        self.central_widget.setLayout(central_widget_layout)
        self.bar_widget.setLayout(stacked_layout_1)
        self.options_widget.setLayout(stacked_layout_2)

    def connections(self):
        self.navigation.PetroAnalysis.connect(lambda: self.bar_widget.layout().setCurrentIndex(0))
        self.navigation.StatsAnalysis.connect(lambda: self.bar_widget.layout().setCurrentIndex(1))
        self.navigation.Save.connect(lambda: self.saveDialog())
        self.navigation.Import.connect(lambda: self.importDialog())
        self.navigation.About.connect(lambda: self.aboutDialog())
        self.navigation.Help.connect(lambda: self.helpDialog())
        self.navigation.header.HomePage.connect(lambda: self.changePage.emit(True))
        self.navigation.ViewSheet.connect(lambda: self.displaySheet())
        self.navigation.ViewPlot.connect(lambda: self.displayPltE())
        self.navigation.New.connect(lambda: self.spreadsheet.addBlankSheet())

        self.p_top_bar.KCarman.connect(lambda: self.options_widget.layout().setCurrentIndex(0))
        self.p_top_bar.TCoates.connect(lambda: self.options_widget.layout().setCurrentIndex(1))
        self.p_top_bar.Winland.connect(lambda: self.options_widget.layout().setCurrentIndex(2))
        self.p_top_bar.DParsons.connect(lambda: self.options_widget.layout().setCurrentIndex(5))
        self.p_top_bar.Lucia.connect(lambda: self.options_widget.layout().setCurrentIndex(4))
        self.p_top_bar.RF.connect(lambda: self.options_widget.layout().setCurrentIndex(3))

        self.s_top_bar.Regr.connect(lambda: self.options_widget.layout().setCurrentIndex(6))
        self.s_top_bar.StatDesc.connect(lambda: self.options_widget.layout().setCurrentIndex(7))
        self.s_top_bar.Boxplt.connect(lambda: self.options_widget.layout().setCurrentIndex(9))
        self.s_top_bar.Hist.connect(lambda: self.options_widget.layout().setCurrentIndex(8))

        self.s_options_1.run_button.clicked.connect(self.startRegr)
        self.s_options_2.run_button.clicked.connect(self.startStat)
        self.s_options_3.run_button.clicked.connect(self.startHist)
        self.s_options_4.run_button.clicked.connect(self.startBxpl)

        self.p_options_1.run.clicked.connect(self.startKCoz)
        self.p_options_2.run.clicked.connect(self.startTCoa)
        self.p_options_3.run.clicked.connect(self.startWinl)
        self.p_options_4.run.clicked.connect(self.startFZIR)
        self.p_options_5.run.clicked.connect(self.startLuci)
        self.p_options_6.run.clicked.connect(self.startDyks)

        self.sp_controls.AddColumn.connect(lambda: self.spreadsheet.addColumn())
        self.sp_controls.AddRow.connect(lambda: self.spreadsheet.addRow())
        self.sp_controls.DeleteRow.connect(lambda: self.spreadsheet.deleteRow())
        self.sp_controls.DeleteColumn.connect(lambda: self.spreadsheet.deleteColumn())

        self.plot_controls.run_button.clicked.connect(lambda: self.startPltE())
        self.plot_controls.erasePlot.connect(lambda: self.plot_viewer.erasePlot())

        self.plot_viewer.feedPlotControls.connect(self.plot_controls.fillFromJson)

    def startPltE(self):
        old_json = self.plot_viewer.json_data
        title = self.plot_controls.modify_title.text()
        xtype = self.plot_controls.modify_x_axis_type.currentText()
        ytype = self.plot_controls.modify_y_axis_type.currentText()
        xlabel = self.plot_controls.modify_x_axis_label.text()
        ylabel = self.plot_controls.modify_y_axis_label.text()

        if len(self.plot_controls.modify_lower_x_range.text()) > 0:
            lxrange = float(self.plot_controls.modify_lower_x_range.text())
        else:
            lxrange = None
        if len(self.plot_controls.modify_upper_x_range.text()) > 0:
            uxrange = float(self.plot_controls.modify_upper_x_range.text())
        else:
            uxrange = None
        if len(self.plot_controls.modify_lower_y_range.text()) > 0:
            lyrange = float(self.plot_controls.modify_lower_y_range.text())
        else:
            lyrange = None
        if len(self.plot_controls.modify_upper_y_range.text()) > 0:
            uyrange = float(self.plot_controls.modify_upper_y_range.text())
        else:
            uyrange = None

        if len(self.plot_controls.add_x_trace.text()) > 0 and len(self.plot_controls.add_y_trace.text()):
            trace_type = self.plot_controls.type_of_trace.currentText()
            x_trace = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.plot_controls.add_x_trace.text())]
            y_trace = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.plot_controls.add_y_trace.text())]
            trace_name = self.plot_controls.trace_name.text()
        else:
            trace_type = None
            x_trace = None
            y_trace = None
            trace_name = None

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.loadPltE(io_operations_handler.results))
        io_operations_handler.loadParameters(f=pceManifold, _args=[old_json, title, xtype, ytype, xlabel, ylabel, lxrange, uxrange, lyrange, uyrange, trace_type, x_trace, y_trace, trace_name])
        io_operations_handler.start()

    def loadPltE(self, results, typ='Regressão'):
        self.plot_viewer.loadPlot(results[0], results[1], _type=typ)
        self.displayPltE()

    def displayPltE(self):
        self.stacked_layout_3.setCurrentIndex(1)
        self.docking_options2.setWidget(self.plot_controls)
        #self.removeDockWidget(self.docking_options3)
        #self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.docking_options2)

    def loadSheet(self, df):
        self.spreadsheet.changeModel(data=df, header=list(df.keys()))
        self.displaySheet()

    def displaySheet(self):
        self.stacked_layout_3.setCurrentIndex(0)
        self.docking_options2.setWidget(self.sp_controls)
        self.status_bar.clearMessage()
        #self.removeDockWidget(self.docking_options2)
        #self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.docking_options3)

    def importDialog(self):
        func = None
        file_settings = QFileDialog().getOpenFileName(self, 'Importar Arquivo',
                                                      filter="Todos os arquivos (*);; Arquivo de Texto (*.txt);; Arquivo CSV (*.csv);; "
                                                             "Planilha Excel (*.xlsx)")
        if ".txt" in file_settings[0]:
            func = Data.readTXT
        if ".csv" in file_settings[0]:
            func = Data.readCSV
        if ".xlsx" in file_settings[0]:
            func = Data.readExcel

        self.status_bar.showMessage('Importando arquivo. Aguarde.')
        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.loadSheet(io_operations_handler.results))
        io_operations_handler.loadParameters(f=func, _args=[file_settings[0],])
        io_operations_handler.start()

    def saveDialog(self):
        func = None
        file_settings = QFileDialog().getSaveFileName(self, "Salvar Arquivo",
                                                      filter="Arquivo de Texto (*.txt);; Arquivo CSV (*.csv);; "
                                                             "Planilha Excel (*.xlsx)")
        if ".txt" in file_settings[0]:
            func = Data.toTXT
        if ".csv" in file_settings[0]:
            func = Data.toCSV
        if ".xlsx" in file_settings[0]:
            func = Data.toExcel

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.loadParameters(f=func, _args=[self.spreadsheet.retrieveModel(), file_settings[0]])
        io_operations_handler.start()

    def aboutDialog(self):
        icon = QIcon(r'icons/sobre.png')
        text = "O Petro-Explorer é um software desenvolvido no Laboratório de Exploração e Produção de Petróleo (" \
               "LENEP) da UENF para análises petrofísicas e estatísticas de dados de rocha. "
        msg = QMessageBox()
        msg.setWindowTitle('Sobre Petro-Explorer')
        msg.setWindowIcon(icon)
        msg.setText(text)
        msg.exec_()

    def helpDialog(self):
        icon = QIcon(r'icons/ajuda.png')
        text = r"Para utilizar o Petro-Explorer de maneira correta siga os seguintes passos:" \
               "\n1 - Clique no botão Novo na barra de navegação, isto irá limpar quaisquer dados de antigas análises.\n" \
               "2 - Para começar a sua análise é preciso importar os dados, assim, clique no botão Importar para escolher o seu arquivo. Atente para o fato que somente três tipos de arquivo são suportados (i.e. *.txt, *.csv, *.xlsx). Depois da sua escolha, os dados devem aparecer na planilha do software.\n" \
               "3 - Se você desejar realizar uma análise petrofísica, clique no botão de Análise Petrofísica na barra de navegação. Caso queira realizar uma análise estatística, clique no botão de Análise Estatística na barra de navegação.\n" \
               "4 - Selecione na barra superior à planilha, a análise que desejas realizar sobre seus dados.\n" \
               "5 - No canto direito da janela, selecione os parâmetros de sua análise assim como o destino de seus resultados. Clique no botão 'Começar Análise' para continuar.\n" \
               "6 - Analise seus resultados na planilha, e, quando disponível, no gráfico também.\n" \
               "7 - Quando terminar, clique no botão Salvar para salvar os resultados de suas análises no disco.\n" \
               "8 - Caso queira realizar outra análise, clique no botão \"Novo\" e comece novamente.\n"
        msg = QMessageBox()
        msg.setWindowTitle('Ajuda')
        msg.setWindowIcon(icon)
        msg.setText(text)
        msg.exec_()

    def startRegr(self):
        xdata = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.s_options_1.payload['x_column'])]
        ydata = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.s_options_1.payload['y_column'])]
        _type = self.s_options_1.payload['calculate']
        dgr = self.s_options_1.degree.value()

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.displayRegr(self.s_options_1.payload['output_column'], io_operations_handler.results))
        io_operations_handler.loadParameters(f=regressionManifold, _args=[xdata, ydata, dgr, _type])
        io_operations_handler.start()

    def startStat(self):
        xdata = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.s_options_2.payload['x_column'])]
        mthd = self.s_options_2.payload['calculate']
        qtl = self.s_options_2.quartile.value()
        pctl = self.s_options_2.percentile.value()

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.displayStat(self.s_options_2.payload['output_column'], io_operations_handler.results))
        io_operations_handler.loadParameters(f=statisticsManifold, _args=[xdata, mthd, qtl, pctl])
        io_operations_handler.start()

    def startHist(self):
        xdata = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.s_options_3.payload['x_column'])]
        nbins = self.s_options_3.payload['y_column']

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.displayHist(io_operations_handler.results))
        io_operations_handler.loadParameters(f=histogramManifold, _args=[xdata, nbins])
        io_operations_handler.start()

    def startBxpl(self):
        indexes = []
        columns = self.s_options_4.payload['column_range']
        for col in columns:
            indexes.append(self.spreadsheet.model.header_info.index(col))
        xdata = self.spreadsheet.model.input_data[:, indexes]
        box_orientation = self.s_options_4.payload['y_column']

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.displayBxpl(io_operations_handler.results))
        io_operations_handler.loadParameters(f=boxplotManifold, _args=[xdata, box_orientation])
        io_operations_handler.start()

    def startKCoz(self):
        #you need to ascertain if x corresponds to Permeability, y to Porosity and z to Swir/Svgr

        k = None
        phi = None
        svgr = None

        prp = self.p_options_1.payload['calculate']

        if prp == 'Permeabilidade (mD)':
            phi = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.p_options_1.payload['x_column'])]
            svgr = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.p_options_1.payload['y_column'])]
        elif prp == 'SVgr (cm-1)':
            k = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.p_options_1.payload['x_column'])]
            phi = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.p_options_1.payload['y_column'])]
        else:
            k = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.p_options_1.payload['x_column'])]
            phi = self.spreadsheet.model.input_data[:, self.spreadsheet.model.header_info.index(self.p_options_1.payload['y_column'])]

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.displayKCoz(io_operations_handler.results))
        io_operations_handler.loadParameters(f=kCarmanManifold, _args=[k, phi, svgr, prp])
        io_operations_handler.start()

    def startTCoa(self):
        #you need to ascertain if x corresponds to Permeability, y to Porosity and z to Swir/Svgr
        prp = self.p_options_2.payload['calculate']

        if prp == "Swir (%)":
            xdata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_2.payload['x_column'])]
            ydata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_2.payload['y_column'])]
            zdata = None
        else:
            xdata = None
            ydata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_2.payload['y_column'])]
            zdata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_2.payload['x_column'])]

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.displayTCoa(io_operations_handler.results))
        io_operations_handler.loadParameters(f=tCoatesManifold, _args=[xdata, ydata, zdata, prp])
        io_operations_handler.start()

    def startWinl(self):
        #you need to ascertain if x corresponds to Permeability, y to Porosity and z to Swir/Svgr
        if self.p_options_3.payload['x_column'] != '':
            xdata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_3.payload['x_column'])]
        else:
            xdata = []
        if self.p_options_3.payload['y_column'] != '':
            ydata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_3.payload['y_column'])]
        else:
            ydata = []

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.displayWinl(io_operations_handler.results))
        io_operations_handler.loadParameters(f=winlandManifold, _args=[xdata, ydata])
        io_operations_handler.start()

    def startFZIR(self):
        # you need to ascertain if x corresponds to Permeability, y to Porosity and z to Swir/Svgr
        if self.p_options_4.payload['x_column'] != '':
            xdata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_4.payload['x_column'])]
        else:
            xdata = None
        if self.p_options_4.payload['y_column'] != '':
            ydata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_4.payload['y_column'])]
        else:
            ydata = None
        if self.p_options_4.payload['z_column'] != '':
            zdata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_4.payload['z_column'])]
        else:
            zdata = None

        prp = self.p_options_4.payload['calculate']
        un = self.p_options_4.payload['column_range']

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.displayFZIR(io_operations_handler.results))
        io_operations_handler.loadParameters(f=fzManifold, _args=[xdata, ydata, zdata, un, prp])
        io_operations_handler.start()

    def startLuci(self):
        #you need to ascertain if x corresponds to Permeability, y to Porosity and z to Swir/Svgr
        if self.p_options_5.payload['x_column'] != '':
            xdata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_5.payload['x_column'])]
        else:
            xdata = []
        if self.p_options_5.payload['y_column'] != '':
            ydata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_5.payload['y_column'])]
        else:
            ydata = []

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.displayLuci(io_operations_handler.results))
        io_operations_handler.loadParameters(f=luciaManifold, _args=[xdata, ydata])
        io_operations_handler.start()

    def startDyks(self):
        #you need to ascertain if x corresponds to Permeability, y to Porosity and z to Swir/Svgr
        if self.p_options_6.payload['x_column'] != '':
            xdata = self.spreadsheet.model.input_data[:,
                    self.spreadsheet.model.header_info.index(self.p_options_6.payload['x_column'])]
        else:
            xdata = []
        prp = self.p_options_6.payload['calculate']

        io_operations_handler = HandlerThread()
        io_operations_handler.messageSent.connect(self.status_bar.showMessage)
        io_operations_handler.daemon = True
        io_operations_handler.hasFinished.connect(lambda: self.displayDyks(io_operations_handler.results))
        io_operations_handler.loadParameters(f=dParsonsManifold, _args=[xdata, prp])
        io_operations_handler.start()

    def displayKCoz(self, content):
        content = list(content)
        content.insert(0, 'Resultados - Kozeny-Carman')
        self.spreadsheet.addColumn(content)

    def displayWinl(self, content):
        self.loadPltE(content[:2])
        content[2].insert(0, 'R35 - Winland')
        content[3].insert(0, 'Ports - Winland')
        self.spreadsheet.addColumn(content[2])
        self.spreadsheet.addColumn(content[3])

    def displayTCoa(self, content):
        content.insert(0, 'Resultados - Timur Coates')
        self.spreadsheet.addColumn(content)

    def displayDyks(self, content):
        content.insert(0, 'Resultados - Dykstra-Parsons')
        self.spreadsheet.addColumn(content)
        self.p_options_6.results.setText('Atenção! Resultado pode ser diferente do coeficiente calculado através do gráfico de probabilidade. \n' + str(content[0]) + ': ' + str(content[1]))

    def displayLuci(self, results):
        self.loadPltE(results[:2])
        results[2].insert(0, 'Resultados - RFN/Lucia')
        self.spreadsheet.addColumn(results[2])

    def displayFZIR(self, results):
        results[0].insert(0, 'Resultados - RQI (μm)')
        self.spreadsheet.addColumn(results[0])
        results[1].insert(0, 'Resultados - PhiZ')
        self.spreadsheet.addColumn(results[1])
        self.loadPltE(results[2:])

    def displayRegr(self, display_name, results):
        self.s_options_1.results.setText(str(results[0]))
        self.loadPltE(results[-2:])

    def displayStat(self, display_name, results):
        self.s_options_2.results.setText(str(results))

    def displayHist(self, results):
        self.loadPltE(results, 'Histograma')

    def displayBxpl(self, results):
        self.loadPltE(results, 'Boxplot')

def test():
    app = QApplication(sys.argv)
    app.setWindowIcon(QIcon('icons/Logo.ico'))
    app.setStyle('Fusion')
    win = MainWindow()
    win.showMaximized()
    win.setWindowIcon(QIcon('icons/Logo.ico'))
    sys.exit(app.exec_())

if __name__ == "__main__":
    test()


# https://programmers.co.kr/learn/courses/57/lessons/13781
# (09) dummy head 를 가지는 연결 리스트 노드 삭제
# 인덱스 범위나, 작동방식을 insert의 경우와 비슷할 거라 생각한게 잘못
# 유일 노드 여부를 Tail 관점에서 생각해야함

class Node:

    def __init__(self, item):
        self.data = item
        self.next = None

class LinkedList:

    def __init__(self):
        self.nodeCount = 0
        self.head = Node(None)
        self.tail = None
        self.head.next = self.tail

    def traverse(self):
        result = []
        curr = self.head
        while curr.next:
            curr = curr.next
            result.append(curr.data)
        return result

    def getAt(self, pos):
        if pos < 0 or pos > self.nodeCount:
            return None

        i = 0
        curr = self.head
        while i < pos:
            curr = curr.next
            i += 1

        return curr

    def insertAfter(self, prev, newNode):
        newNode.next = prev.next
        if prev.next is None:
            self.tail = newNode
        prev.next = newNode
        self.nodeCount += 1
        return True

    def insertAt(self, pos, newNode):
        if pos < 1 or pos > self.nodeCount + 1:
            return False

        if pos != 1 and pos == self.nodeCount + 1:
            prev = self.tail
        else:
            prev = self.getAt(pos - 1)
        return self.insertAfter(prev, newNode)

    def popAfter(self, prev):
        curr = prev.next
        # prev 다음 노드가
        # 1. 삭제할 노드가 없는 경우
        if prev.next == None:
            return None

        # 2. Tail Node인 경우
        if curr.next == None:
            # 유일한 노드일 떄
            if self.nodeCount == 1:
                self.tail = None
            # 유일한 노드가 아닐 때
            else:
                self.tail = prev

        # 링크 조정
        prev.next = curr.next
        self.nodeCount -= 1
        return curr.data

    def popAt(self, pos):
        # pos 범위 조건 확인
        if pos < 1 or pos > self.nodeCount:
            raise IndexError

        prev = self.getAt(pos-1)

        return self.popAfter(prev)

def solution(x):
    return 0


"""
Run setup
"""

from os import path
from setuptools import setup, find_packages
from scikit_ext import __version__

try:
    here = path.abspath(path.dirname(__file__))
    with open(path.join(here, 'README.rst')) as f:
        long_description = f.read()
except:
    long_description = ""

setup(name='scikit-ext',
      version=__version__,
      description='Various scikit-learn extensions',
      long_description=long_description,
      classifiers=[
        'Development Status :: 4 - Beta',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python',
        'Topic :: Scientific/Engineering :: Artificial Intelligence'
      ],
      url='https://github.com/denver1117/scikit-ext',
      download_url='https://pypi.org/project/scikit-ext/#files',
      author='Evan Harris',
      author_email='emitchellh@gmail.com',
      license='MIT',
      packages=find_packages(),
      python_requires=">=3.5",
      install_requires=[
          'pandas',
          'numpy>=1.17.0',
          'scipy>=1.3.1',
          'scikit-learn>=0.22.0,<0.24'
      ])


"""Web endpoint showing graph of running :pypi:`mode` services."""
import io
from faust import web

__all__ = ['Graph', 'blueprint']

blueprint = web.Blueprint('graph')

@blueprint.route('/', name='detail')
class Graph(web.View):
    """Render image from graph of running services."""

    async def get(self, request: web.Request) -> web.Response:
        """Draw image of the services running in this worker."""
        try:
            import pydot
        except ImportError:
            return self.text('Please install pydot: pip install pydot',
                             status=500)
        o = io.StringIO()
        beacon = self.app.beacon.root or self.app.beacon
        beacon.as_graph().to_dot(o)
        graph, = pydot.graph_from_dot_data(o.getvalue())
        return self.bytes(graph.create_png(), content_type='image/png')


################################################################################
##
## BY: WANDERSON M.PIMENTA
## PROJECT MADE WITH: Qt Designer and PySide2
## V: 1.0.0
##
################################################################################

import sys
import platform
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import (QCoreApplication, QPropertyAnimation, QDate, QDateTime, QMetaObject, QObject, QPoint, QRect, QSize, QTime, QUrl, Qt, QEvent)
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter, QPixmap, QRadialGradient)
from PySide2.QtWidgets import *

# GUI FILE
from ui_splash_screen import Ui_SplashScreen
from ui_main import Ui_MainWindow

# GLOBALS
counter = 0
jumper = 10

## ==> YOUR APPLICATION WINDOW
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        ## ==> SET VALUES TO DEF progressBarValue
        def setValue(self, slider, labelPercentage, progressBarName, color):

            # GET SLIDER VALUE
            value = slider.value()

            # CONVERT VALUE TO INT
            sliderValue = int(value)

            # HTML TEXT PERCENTAGE
            htmlText = """
{VALUE}%
"""
            labelPercentage.setText(htmlText.replace("{VALUE}", str(sliderValue)))

            # CALL DEF progressBarValue
            self.progressBarValue(sliderValue, progressBarName, color)

        ## ==> APPLY VALUES TO PROGREESBAR
        self.ui.sliderCPU.valueChanged.connect(lambda: setValue(self, self.ui.sliderCPU, self.ui.labelPercentageCPU, self.ui.circularProgressCPU, "rgba(85, 170, 255, 255)"))
        self.ui.sliderGPU.valueChanged.connect(lambda: setValue(self, self.ui.sliderGPU, self.ui.labelPercentageGPU, self.ui.circularProgressGPU, "rgba(85, 255, 127, 255)"))
        self.ui.sliderRAM.valueChanged.connect(lambda: setValue(self, self.ui.sliderRAM, self.ui.labelPercentageRAM, self.ui.circularProgressRAM, "rgba(255, 0, 127, 255)"))

        ## ==> DEF START VALUES
        self.ui.sliderCPU.setValue(25)
        self.ui.sliderGPU.setValue(65)
        self.ui.sliderRAM.setValue(45)

    ## DEF PROGRESS BAR VALUE
    ########################################################################
    def progressBarValue(self, value, widget, color):

        # PROGRESSBAR STYLESHEET BASE
        styleSheet = """
        QFrame{
        	border-radius: 110px;
        	background-color: qconicalgradient(cx:0.5, cy:0.5, angle:90, stop:{STOP_1} rgba(255, 0, 127, 0), stop:{STOP_2} {COLOR});
        }
        """

        # GET PROGRESS BAR VALUE, CONVERT TO FLOAT AND INVERT VALUES
        # stop works of 1.000 to 0.000
        progress = (100 - value) / 100.0

        # GET NEW VALUES
        stop_1 = str(progress - 0.001)
        stop_2 = str(progress)

        # FIX MAX VALUE
        if value == 100:
            stop_1 = "1.000"
            stop_2 = "1.000"

        # SET VALUES TO NEW STYLESHEET
        newStylesheet = styleSheet.replace("{STOP_1}", stop_1).replace("{STOP_2}", stop_2).replace("{COLOR}", color)

        # APPLY STYLESHEET WITH NEW VALUES
        widget.setStyleSheet(newStylesheet)

## ==> SPLASHSCREEN WINDOW
class SplashScreen(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_SplashScreen()
        self.ui.setupUi(self)

        ## ==> SET INITIAL PROGRESS BAR TO (0) ZERO
        self.progressBarValue(0)

        ## ==> REMOVE STANDARD TITLE BAR
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint) # Remove title bar
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # Set background to transparent

        ## ==> APPLY DROP SHADOW EFFECT
        self.shadow = QGraphicsDropShadowEffect(self)
        self.shadow.setBlurRadius(20)
        self.shadow.setXOffset(0)
        self.shadow.setYOffset(0)
        self.shadow.setColor(QColor(0, 0, 0, 120))
        self.ui.circularBg.setGraphicsEffect(self.shadow)

        ## QTIMER ==> START
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.progress)
        # TIMER IN MILLISECONDS
        self.timer.start(15)

        ## SHOW ==> MAIN WINDOW
        ########################################################################
        self.show()
        ## ==> END ##

    ## DEF TO LOANDING
    ########################################################################
    def progress (self):
        global counter
        global jumper
        value = counter

        # HTML TEXT PERCENTAGE
        htmlText = """
{VALUE}%
"""

        # REPLACE VALUE
        newHtml = htmlText.replace("{VALUE}", str(jumper))

        if(value > jumper):
            # APPLY NEW PERCENTAGE TEXT
            self.ui.labelPercentage.setText(newHtml)
            jumper += 10

        # SET VALUE TO PROGRESS BAR
        # fix max value error if > than 100
        if value >= 100: value = 1.000
        self.progressBarValue(value)

        # CLOSE SPLASH SCREE AND OPEN APP
        if counter > 100:
            # STOP TIMER
            self.timer.stop()

            # SHOW MAIN WINDOW
            self.main = MainWindow()
            self.main.show()

            # CLOSE SPLASH SCREEN
            self.close()

        # INCREASE COUNTER
        counter += 0.5

    ## DEF PROGRESS BAR VALUE
    ########################################################################
    def progressBarValue(self, value):

        # PROGRESSBAR STYLESHEET BASE
        styleSheet = """
        QFrame{
        	border-radius: 150px;
        	background-color: qconicalgradient(cx:0.5, cy:0.5, angle:90, stop:{STOP_1} rgba(255, 0, 127, 0), stop:{STOP_2} rgba(85, 170, 255, 255));
        }
        """

        # GET PROGRESS BAR VALUE, CONVERT TO FLOAT AND INVERT VALUES
        # stop works of 1.000 to 0.000
        progress = (100 - value) / 100.0

        # GET NEW VALUES
        stop_1 = str(progress - 0.001)
        stop_2 = str(progress)

        # SET VALUES TO NEW STYLESHEET
        newStylesheet = styleSheet.replace("{STOP_1}", stop_1).replace("{STOP_2}", stop_2)

        # APPLY STYLESHEET WITH NEW VALUES
        self.ui.circularProgress.setStyleSheet(newStylesheet)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = SplashScreen()
    sys.exit(app.exec_())


from pyimagesearch.utils.conf import *
from scipy import io
import numpy as np
import argparse
import glob

ap = argparse.ArgumentParser()
ap.add_argument("-c", "--conf", required = True, help = "path to the configuration file")
args = vars(ap.parse_args())

conf = Conf(args["conf"])
widths = []
heights = []

for p in glob.glob(conf["image_annotations"] +"/*.mat"):
    (y, h, x, w) = io.loadmat(p)["box_coord"][0]
    widths.append(w-x)
    heights.append(h-y)

(avgWidth, avgHeight) = (np.mean(widths), np.mean(heights))

print ("avgWidth : {}".format(avgWidth))
print ("avgHeight : {}".format(avgHeight))
print ("aspect_ratio : {}".format(avgWidth / avgHeight))


class Solution:
    def myAtoi(self, s: str) -> int:
        s = s.strip()

        result = 0  # Stores and returns the integer converted value for str
        i = 0  # just a current character pointer for string
        sign = 1  # multiplied at the end to result to determine if the string is +ve or -ve
        if i < len(s) and s[i] in ['-', '+']:  # Check the sign of string (+ or -)
            if s[i] == '-':
                sign = -1
            i += 1

        # Now traverse the entire string and convert it into integer
        while i < len(s) and '0' <= s[i] <= '9':
            digit = ord(s[i]) - ord('0')

            result = result * 10 + digit
            i += 1

        value = result * sign
        #check for integer overflow or underflow
        value = min(value, 2 ** 31 - 1)
        value = max(-(2 ** 31), value)
        return value

print(Solution().myAtoi(" -123a"))


# this is the Code for 3rd part of the Assignment

import random
import matplotlib.pyplot as plt
import numpy as np

def RC_Multiply(a,b):
	sum = int("0",10)
	for i in range(3):
		sum += a[i]*b[i]
	return sum;

Data = []
plt_dt = []
a = 0
for i in range(100):
	r_fra1 = random.randint(-1000,1000)/1000;
	r_fra2 = random.randint(-1000,1000)/1000;
	dat_plt = [r_fra1, r_fra2]
	plt_dt.append(dat_plt)
	a = [r_fra1, r_fra2,1]
	if(i < 50):
		clas = "A"
	else:
		clas = "B"
	Data.append([a,clas])

w1 = [1,1,0]  #plot this line
w2 = [-1,-1,0]
w3 = [0,0.5,0]
w4 = [1, -1,5] # plot this line
w5 = [1,1,0.3] # plot this line

acc_w1 = 0;
acc_w2 = 0;
acc_w3 = 0;
acc_w4 = 0;
acc_w5 = 0;
for i in range(100):
	if(RC_Multiply(w1,Data[i][0]) > 0 and Data[i][1]=="A"):
		acc_w1 += 1;
	elif(RC_Multiply(w1,Data[i][0]) <= 0 and Data[i][1]=="B"):
		acc_w1 += 1;
	if(RC_Multiply(w1,Data[i][0]) > 0 and Data[i][1]=="A"):
		acc_w2 += 1;
	elif(RC_Multiply(w2,Data[i][0]) <= 0 and Data[i][1]=="B"):
		acc_w2 += 1;
	if(RC_Multiply(w3,Data[i][0]) > 0 and Data[i][1]=="A"):
		acc_w3 += 1;
	elif(RC_Multiply(w3,Data[i][0]) <= 0 and Data[i][1]=="B"):
		acc_w3 += 1;
	if(RC_Multiply(w4,Data[i][0]) > 0 and Data[i][1]=="A"):
		acc_w4 += 1;
	elif(RC_Multiply(w4,Data[i][0]) <= 0 and Data[i][1]=="B"):
		acc_w4 += 1;
	if(RC_Multiply(w5,Data[i][0]) > 0 and Data[i][1]=="A"):
		acc_w5 += 1;
	elif(RC_Multiply(w5,Data[i][0]) <= 0 and Data[i][1]=="B"):
		acc_w5 += 1;

print("PART (i)")
print("Accuracy of a : "+str(acc_w1)+"%")
print("Accuracy of b : "+str(acc_w2)+"%")
print("Accuracy of c : "+str(acc_w3)+"%")
print("Accuracy of d : "+str(acc_w4)+"%")
print("Accuracy of e : "+str(acc_w5)+"%")

print("PART (ii)")
fig, ax = plt.subplots()
data_plot = np.array(plt_dt);
x,y = data_plot.T
ax.scatter(x,y)
x = np.array(range(-1,2))
y = (w1[0]/-w1[1])*x + (w1[2]/-w1[1])
la = ax.plot(x,y,label='line for a')
ax.set_title('With Boundry a')

fig,bx = plt.subplots()
data_plot = np.array(plt_dt);
x,y = data_plot.T
bx.scatter(x,y)
x = np.array(range(-1,2))
y = (w4[0]/-w4[1])*x + (w4[2]/-w4[1])
bx.plot(x,y,label='line for d')
bx.set_title('With Boundry b')

fig,cx = plt.subplots()
data_plot = np.array(plt_dt);
x,y = data_plot.T
cx.scatter(x,y)
x = np.array(range(-1,2))
y = (w5[0]/-w5[1])*x + (w5[2]/-w5[1])
le = cx.plot(x,y,label='line for e')
cx.set_title('With Boundry c')
plt.show()


# !/usr/bin python3
# encoding: utf-8 -*-
# @author: 沙陌 微信：Matongxue_2
# @Time: 2021-12-26 16:52
# @Copyright：北京码同学

s = 'shamo'
# 逐个输出s这个字符串里的每一个字符
# print('s')
# print('h')
# print('a')
# in后面跟的是一个序列，序列最简单的理解就是一个有序的排列
# c在这里是一个临时的变量，他用来在每次循环时接收s里边的字符
for c in s:
    print(c)

#使用for循环来实现1-100之间的数字和
# range(100) #这会生成0-100之间的序列，不包括100
sum = 0
# for i in range(100):
#     sum =sum+i
# print(sum)
#使用for循环来实现88-198,包括198,之间的数字和
for i in range(88,199):
    if i == 133:
        break
    sum = sum + i
else:
    # 如果循环被break终止了，那么else里的代码不会被执行
    # 但是如果是continue，else里的代码是会被执行的
    print(f'循环正常结束之后结果是:{sum}')
print('不管上面的循环是否正常结束，我都会执行sum的结果:{}'.format(sum))

like_star = ['赵丽颖','高圆圆','白露']
for name in like_star:
    print(name)
# print(name)

# 今天的作业:
# 1. 从控制台输入年、月、日，计算输入的日期，是这一年的第几天
# 比如2021.2.18 ,是2021年的第49天
# 比如2021.4.7,是2021年的第97天


from sys import (stdout, stderr)
from argparse import (ArgumentParser, ArgumentError)

from .color_display import ColorDisplay

########################################################################
# Command-line arguments

timeout_dft = -1

parser = ArgumentParser(
        description="Python script to show off terminal colors.",
        epilog="Run this script from the terminal whose colors " +
               "you want to showcase. " +
               "Only xterm-like terminals are supported " +
               "(see the README).")

mode_group = parser.add_mutually_exclusive_group()

p_choices = [16, 88, 256]

arg_p = mode_group.add_argument(
        '-p', '--pretty',
        action='store_true', default=False,
        help="show colors 0 through N-1 in a pretty format.  " +
             ("N must belong to %r.  " % p_choices) +
             "If N > 16, it should be the actual number of colors " +
             "supported by the terminal, or the output will almost " +
             "certainly not be pretty.")

mode_group.add_argument(
        '-f', '--flat',
        action='store_true', default=False,
        help="show a simple table with colors 0 through N-1.  ")

parser.add_argument(
        'n', nargs='?', metavar='N',
        type=int, default=16,
        help="number of colors to show.  " +
             "Unless you explicitly supply -p/--pretty or -f/--flat, " +
             "--pretty is used if possible and --flat is used " +
             "otherwise.  " +
             "N defaults to 16, showing the ANSI colors 0-15.  " +
             "If N is 0, the script will attempt to determine the " +
             "maximum number of colors automatically " +
             "(which may be slow).")

parser.add_argument(
        '--no-fgbg',
        action='store_false', dest='fgbg', default=True,
        help="suppress display of foreground/background colors.")

parser.add_argument(
        '--no-query',
        action='store_false', dest='do_query', default=True,
        help="don't try to query any RGB values from the terminal " +
             "and just use placeholders.")

parser.add_argument(
        '-t', '--timeout', metavar='T',
        type=int, default=timeout_dft,
        help="how long to wait for the terminal to "
             "respond to a query, in milliseconds  " +
             "[default: {0}].  ".format(timeout_dft) +
             "If your output has '?' characters " +
             "instead of RGB values " +
             "or junk printed after the script runs, " +
             "increasing this value may or may not " +
             "help, depending on the terminal.  " +
             "A negative T will behave like infinity.")

parser.add_argument(
        '-l', '--level', metavar='L',
        type=int, default=3,
        help="choose how much color to use in the output.  " +
             "(0 = no color; 3 = most color [default])")

parser.add_argument(
        '--screen-forward', '--tmux-forward',
        action='store_true', default=False,
        help="attempt to pass terminal queries through a tmux " +
             "session (ignored if this is not a tmux session)")

########################################################################

def main():
    args = parser.parse_args()

    assert not (args.pretty and args.flat)

    if args.pretty:
        if args.n not in p_choices:
            raise ArgumentError(
                    arg_p,
                    "N must belong to %r" % p_choices)

    with ColorDisplay(0, args.timeout, args.level, args.do_query,
                      args.screen_forward) as C:

        if args.n == 0:
            args.n = C.get_num_colors(args.timeout)

        if not (args.pretty or args.flat):
            if args.n in p_choices:
                args.pretty = True
            else:
                args.flat = True

        if args.level >= 1:
            stdout.write(C.reset)

        if args.fgbg:
            C.show_fgbg()

        if args.pretty:
            assert args.n in p_choices

            stdout.write('\n    ANSI colors:\n\n')
            C.show_ansi()

            if args.n > 16:
                stdout.write('\n    RGB cube:\n\n')
                C.show_color_cube(args.n)

                stdout.write('    Grayscale ramp:\n\n')
                C.show_grayscale_ramp(args.n)
        else:
            C.show_colors(args.n)

        if C.num_errors > 0:
            stderr.write("Warning: not all queries succeeded\n" +
                         "Warning:     (output contains " +
                         "placeholders and may be inaccurate)\n")

if __name__ == "__main__":
    main()


# %%
import numpy as np
import matplotlib.pyplot as plt

from question1 import x, y1, y2

# d is the distance between samples

def ct_energy(x, n, d): return sum([np.abs(x(i))**2 for i in n])*d

d = .0001
n = np.arange(-4, 4, d)
x_en = ct_energy(x, n, d)
y1_en = ct_energy(y1, n, d)
y2_en = ct_energy(y2, n, d)
# endsection
print(f'x_en: {x_en}\ny_en: {y1_en}\ny2_en:{y2_en}')
x_en: 2.6666166750070275
y_en: 1.3332833500056211
y2_en:2.6667166749880353


from sqlalchemy import asc
from sqlalchemy import func
from transaction import manager

from parks.logic.math_logic import latitude_to_miles
from parks.logic.math_logic import latitude_longitude_distance
from parks.logic.math_logic import longitude_to_miles
from parks.models import DBSession
from parks.models import Park
from parks.models import Stamp
from parks.models import StampCollection
from parks.models import StampHistory
from parks.models import StampLocation
from parks.models import StampToLocation

def get_stamps_by_park_id(park_id):
    max_time_subquery = DBSession.query(
        StampCollection.stamp_id.label('stamp_id'),
        func.max(StampCollection.date_collected).label('most_recent_time'),
    ).group_by(
        StampCollection.stamp_id
    ).subquery()

    return DBSession.query(
        Stamp,
        StampLocation,
        max_time_subquery.c.most_recent_time,
    ).join(
        StampToLocation,
    ).join(
        StampLocation,
    ).outerjoin(
        max_time_subquery,
        Stamp.id == max_time_subquery.c.stamp_id
    ).filter(
        StampLocation.park_id == park_id
    ).group_by(
        Stamp.id
    ).group_by(
        # This group_by needs to be included for the query to run in Postgres
        StampLocation.id
    ).group_by(
        # This group_by needs to be included for the query to run in Postgres
        max_time_subquery.c.most_recent_time
    ).all()

def get_stamps_by_location_id(location_id):
    max_time_subquery = DBSession.query(
        StampCollection.stamp_id.label('stamp_id'),
        func.max(StampCollection.date_collected).label('most_recent_time'),
    ).group_by(
        StampCollection.stamp_id
    ).subquery()

    return DBSession.query(
        Stamp,
        StampLocation,
        max_time_subquery.c.most_recent_time,
    ).join(
        StampToLocation,
    ).join(
        StampLocation,
    ).outerjoin(
        max_time_subquery,
        Stamp.id == max_time_subquery.c.stamp_id,
    ).filter(
        StampLocation.id == location_id,
    ).group_by(
        Stamp.id
    ).group_by(
        # This group_by needs to be included for the query to run in Postgres
        StampLocation.id
    ).group_by(
        # This group_by needs to be included for the query to run in Postgres
        max_time_subquery.c.most_recent_time
    ).all()

def get_nearby_stamps(latitude, longitude, distance_miles):
    lower_latitude = latitude - (distance_miles / latitude_to_miles())
    upper_latitude = latitude + (distance_miles / latitude_to_miles())
    lower_longitude = longitude - (distance_miles / longitude_to_miles(longitude))
    upper_longitude = longitude + (distance_miles / longitude_to_miles(longitude))

    max_time_subquery = DBSession.query(
        StampCollection.stamp_id.label('stamp_id'),
        func.max(StampCollection.date_collected).label('most_recent_time'),
    ).join(
        Stamp
    ).group_by(
        StampCollection.stamp_id
    ).subquery()

    stamps = DBSession.query(
        StampLocation,
        Stamp,
        Park,
        max_time_subquery.c.most_recent_time.label('last_seen'),
    ).join(
        StampToLocation
    ).join(
        Stamp
    ).join(
        Park
    ).outerjoin(
        max_time_subquery,
        max_time_subquery.c.stamp_id == Stamp.id
    ).filter(
        StampLocation.latitude.between(lower_latitude, upper_latitude)
    ).filter(
        StampLocation.longitude.between(lower_longitude, upper_longitude)
    ).order_by(
        asc(
            (latitude - StampLocation.latitude) * (latitude - StampLocation.latitude) +
            (longitude - StampLocation.longitude) * (longitude - StampLocation.longitude)
        )
    ).all()

    # We're doing square distance calculation in SQL so that we can use
    # indexes, so we might include some stamps that aren't within the radius
    # that we need to post-filter
    stamps = [
        s for s in stamps if latitude_longitude_distance(
            latitude,
            longitude,
            s.StampLocation.latitude,
            s.StampLocation.longitude
        ) < distance_miles
    ]

    return stamps

def stamp_exists(stamp_text):
    stamp_text_count = DBSession.query(
        Stamp.text
    ).filter(
        Stamp.text == stamp_text
    ).count()

    if stamp_text_count > 0:
        return True
    else:
        return False

def create_new_stamp(stamp_text, stamp_type, added_by_user_id):
    # The model allows for nulls here because my initial database population
    # script doesn't have a user, so just enforce this rule here
    if added_by_user_id is None:
        raise ValueError('added_by_user should not be None')

    stamp = Stamp(
        text=stamp_text,
        type=stamp_type,
        status='active',
        added_by_user_id=added_by_user_id,
    )
    DBSession.add(stamp)

    stamp_id = DBSession.query(
        Stamp.id
    ).filter(
        Stamp.text == stamp_text
    ).one()

    return stamp_id[0]

def edit_stamp(stamp_id, stamp_text, stamp_type, stamp_status, edited_by_user_id):
    # The model allows for nulls here because my initial database population
    # script doesn't have a user, so just enforce this rule here
    if edited_by_user_id is None:
        raise ValueError('edited_by_user should not be None')

    with manager:
        stamp = DBSession.query(
            Stamp
        ).filter(
            Stamp.id == stamp_id
        ).one()

        stamp.text = stamp_text
        stamp.type = stamp_type
        stamp.status = stamp_status

        stamp_history = StampHistory(
            stamp_id=stamp_id,
            text=stamp_text,
            type=stamp_type,
            status='active',
            edited_by_user_id=edited_by_user_id,
        )
        DBSession.add(stamp_history)

def get_stamps_beginning_with_string(text, limit=None):
    """Returns stamps with text that start with the substring."""
    if limit is None:
        limit = 10

    stamps = DBSession.query(
        Stamp
    ).filter(
        Stamp.text.like(text + '%')
    ).limit(
        limit
    ).all()

    return stamps


import numpy as np
import matplotlib.pyplot as plt
import os
import pylab

from mpl_toolkits.mplot3d import Axes3D

# experiments variables
datasets = ["kotanchek-test-0"]
schemes = ["proximity-xy", "surrounding-xy", "remoteness-xy", "nonlinearity"]
dist_metrics = ["L2.0"]
nums_neighbors = ["k5"]

# local paths
base_dir = os.path.expanduser("~/Dropbox/my_files/research/ISR/")
data_folder = base_dir + "datasets/original/"
weights_folder = base_dir + "datasets/2-08.06.2017/original/weights/"
plots_folder = base_dir + "plots/5-01.09.2017/original/"

if not os.path.exists(plots_folder):
    os.makedirs(plots_folder)

for dataset in datasets:
    print("Dataset: " + dataset)

    fold = data_folder + dataset + ".csv"

    for scheme in schemes:
        print("  Scheme: " + scheme)

        for num_neighbors in nums_neighbors:
            for dist_metric in dist_metrics:
                # for the nonlinearity scheme only the Euclidean distance was used
                if scheme == "nonlinearity" and dist_metric != "L2.0":
                    continue

                weights = weights_folder + "-".join([scheme, num_neighbors, dist_metric, dataset]) + ".csv"

                print("    Distance metric: " + dist_metric)
                print("    Data file: " + fold)
                print("    Weight file: " + weights)

                # read and process the datasets
                data = np.loadtxt(fold, delimiter=",")
                X = data[:, 0]
                Y = data[:, 1]
                Z = data[:, 2]

                # read and process the weight files
                W = np.loadtxt(weights, delimiter=",")
                labels = ['%.2f' % elem for elem in W.tolist()]
                min_weight = min(W) * 0.95
                max_weight = max(W) * 0.95

                areas = [(w - min_weight) / (max_weight - min_weight) * 400 for w in W]

                plt.figure(figsize=(16, 8))

                fig = pylab.figure(figsize=(16, 10))
                ax = Axes3D(fig)

                # version with black rings: ax.scatter(X, Y, Z, s=areas, facecolors='none', edgecolors='black')
                ax.scatter(X, Y, Z, s=areas, c="#1F77B4", facecolors="none", alpha=0.4)

                plt.xlabel("X", fontsize=12)
                plt.ylabel("Y", fontsize=12)

                plt.title("Weights - " + scheme + ", " + dist_metric + ", " + dataset)
                plt.savefig(plots_folder + "-".join([dataset, scheme, num_neighbors, dist_metric]) + ".pdf",
                            bbox_inches="tight")

                plt.close()


"""rio-tiler models."""

import itertools
import warnings
from enum import Enum
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union

import attr
import numpy
from affine import Affine
from pydantic import BaseModel
from rasterio.coords import BoundingBox
from rasterio.crs import CRS
from rasterio.dtypes import dtype_ranges
from rasterio.plot import reshape_as_image
from rasterio.transform import from_bounds
from rio_color.operations import parse_operations
from rio_color.utils import scale_dtype, to_math_type

from .errors import InvalidDatatypeWarning
from .types import ColorMapType, GDALColorMapType, IntervalTuple, NumType
from .utils import linear_rescale, render, resize_array

class NodataTypes(str, Enum):
    """rio-tiler Nodata types."""

    Alpha = "Alpha"
    Mask = "Mask"
    Internal = "Internal"
    Nodata = "Nodata"
    Empty = "None"

class RioTilerBaseModel(BaseModel):
    """Base Model for rio-tiler models."""

    def __getitem__(self, item):
        """Keep `getter` access for compatibility."""
        return self.__dict__[item]

class Bounds(RioTilerBaseModel):
    """Dataset Bounding box"""

    bounds: BoundingBox

class SpatialInfo(Bounds):
    """Dataset SpatialInfo"""

    minzoom: int
    maxzoom: int

class Info(SpatialInfo):
    """Dataset Info."""

    band_metadata: List[Tuple[str, Dict]]
    band_descriptions: List[Tuple[str, str]]
    dtype: str
    nodata_type: NodataTypes
    colorinterp: Optional[List[str]]
    scale: Optional[float]
    offset: Optional[float]
    colormap: Optional[GDALColorMapType]

    class Config:
        """Config for model."""

        extra = "allow"
        use_enum_values = True

class BandStatistics(RioTilerBaseModel):
    """Image statistics"""

    min: float
    max: float
    mean: float
    count: float
    sum: float
    std: float
    median: float
    majority: float
    minority: float
    unique: float
    histogram: List[List[NumType]]
    valid_percent: float
    masked_pixels: float
    valid_pixels: float

    class Config:
        """Config for model."""

        extra = "allow"  # We allow extra values for `percentiles_{}`

def to_coordsbbox(bbox) -> Optional[BoundingBox]:
    """Convert bbox to CoordsBbox nameTuple."""
    return BoundingBox(*bbox) if bbox else None

def rescale_image(
    data: numpy.ndarray,
    mask: numpy.ndarray,
    in_range: Sequence[IntervalTuple],
    out_range: Sequence[IntervalTuple] = ((0, 255),),
    out_dtype: Union[str, numpy.number] = "uint8",
):
    """Rescale image data."""
    if len(data.shape) < 3:
        data = numpy.expand_dims(data, axis=0)

    nbands = data.shape[0]

    if len(in_range) != nbands:
        in_range = ((in_range[0]),) * nbands

    if len(out_range) != nbands:
        out_range = ((out_range[0]),) * nbands

    for bdx in range(nbands):
        data[bdx] = numpy.where(
            mask,
            linear_rescale(data[bdx], in_range=in_range[bdx], out_range=out_range[bdx]),
            0,
        )

    return data.astype(out_dtype)

@attr.s
class ImageData:
    """Image Data class.

    Attributes:
        data (numpy.ndarray): pixel values.
        mask (numpy.ndarray): rasterio mask values.
        assets (list, optional): list of assets used to construct the data values.
        bounds (BoundingBox, optional): bounding box of the data.
        crs (rasterio.crs.CRS, optional): Coordinates Reference System of the bounds.
        metadata (dict, optional): Additional metadata. Defaults to `{}`.
        band_names (list, optional): name of each band. Defaults to `["1", "2", "3"]` for 3 bands image.

    """

    data: numpy.ndarray = attr.ib()
    mask: numpy.ndarray = attr.ib()
    assets: Optional[List] = attr.ib(default=None)
    bounds: Optional[BoundingBox] = attr.ib(default=None, converter=to_coordsbbox)
    crs: Optional[CRS] = attr.ib(default=None)
    metadata: Optional[Dict] = attr.ib(factory=dict)
    band_names: List[str] = attr.ib()

    @data.validator
    def _validate_data(self, attribute, value):
        """ImageData data has to be a 3d array in form of (count, height, width)"""
        if not len(value.shape) == 3:
            raise ValueError(
                "ImageData data has to be an array in form of (count, height, width)"
            )

    @band_names.default
    def _default_names(self):
        return [f"{ix + 1}" for ix in range(self.count)]

    @mask.default
    def _default_mask(self):
        return numpy.zeros((self.height, self.width), dtype="uint8") + 255

    def __iter__(self):
        """Allow for variable expansion (``arr, mask = ImageData``)"""
        for i in (self.data, self.mask):
            yield i

    @classmethod
    def create_from_list(cls, data: Sequence["ImageData"]):
        """Create ImageData from a sequence of ImageData objects.

        Args:
            data (sequence): sequence of ImageData.

        """
        h, w = zip(*[(img.height, img.width) for img in data])
        if len(set(h)) > 1 or len(set(w)) > 1:
            warnings.warn(
                "Cannot concatenate images with different size. Will resize using max width/heigh",
                UserWarning,
            )
            max_h, max_w = max(h), max(w)
            for img in data:
                if img.height == max_h and img.width == max_w:
                    continue
                img.data = resize_array(img.data, max_h, max_w)
                img.mask = resize_array(img.mask, max_h, max_w)

        arr = numpy.concatenate([img.data for img in data])
        mask = numpy.all([img.mask for img in data], axis=0).astype(numpy.uint8) * 255
        assets = list(
            dict.fromkeys(
                itertools.chain.from_iterable(
                    [img.assets for img in data if img.assets]
                )
            )
        )

        bounds_values = [img.bounds for img in data if img.bounds]
        bounds = bounds_values[0] if bounds_values else None

        crs_values = [img.crs for img in data if img.crs]
        crs = crs_values[0] if crs_values else None

        band_names = list(
            itertools.chain.from_iterable(
                [img.band_names for img in data if img.band_names]
            )
        )

        return cls(
            arr, mask, assets=assets, crs=crs, bounds=bounds, band_names=band_names
        )

    def as_masked(self) -> numpy.ma.MaskedArray:
        """return a numpy masked array."""
        data = numpy.ma.array(self.data)
        data.mask = self.mask == 0
        return data

    def data_as_image(self) -> numpy.ndarray:
        """Return the data array reshaped into an image processing/visualization software friendly order.

        (bands, rows, columns) -> (rows, columns, bands).

        """
        return reshape_as_image(self.data)

    @property
    def width(self) -> int:
        """Width of the data array."""
        return self.data.shape[2]

    @property
    def height(self) -> int:
        """Height of the data array."""
        return self.data.shape[1]

    @property
    def count(self) -> int:
        """Number of band."""
        return self.data.shape[0]

    @property
    def transform(self):
        """Returns the affine transform."""
        return (
            from_bounds(*self.bounds, self.width, self.height)
            if self.bounds
            else Affine.scale(self.width, -self.height)
        )

    def rescale(
        self,
        in_range: Sequence[IntervalTuple],
        out_range: Sequence[IntervalTuple] = ((0, 255),),
        out_dtype: Union[str, numpy.number] = "uint8",
    ):
        """Rescale data in place."""
        self.data = rescale_image(self.data, self.mask, in_range, out_range, out_dtype)

    def apply_color_formula(self, color_formula: Optional[str]):
        """Apply rio-color formula in place."""
        self.data[self.data < 0] = 0
        for ops in parse_operations(color_formula):
            self.data = scale_dtype(ops(to_math_type(self.data)), numpy.uint8)

    def post_process(
        self,
        in_range: Optional[Sequence[IntervalTuple]] = None,
        out_dtype: Union[str, numpy.number] = "uint8",
        color_formula: Optional[str] = None,
        **kwargs: Any,
    ) -> "ImageData":
        """Post-process image data.

        Args:
            in_range (tuple): input min/max bounds value to rescale from.
            out_dtype (str, optional): output datatype after rescaling. Defaults to `uint8`.
            color_formula (str, optional): rio-color formula (see: https://github.com/mapbox/rio-color).
            kwargs (optional): keyword arguments to forward to `rio_tiler.utils.linear_rescale`.

        Returns:
            ImageData: new ImageData object with the updated data.

        Examples:
            >>> img.post_process(in_range=((0, 16000), ))

            >>> img.post_process(color_formula="Gamma RGB 4.1")

        """
        data = self.data.copy()
        mask = self.mask.copy()

        if in_range:
            data = rescale_image(data, mask, in_range, out_dtype=out_dtype, **kwargs)

        if color_formula:
            data[data < 0] = 0
            for ops in parse_operations(color_formula):
                data = scale_dtype(ops(to_math_type(data)), numpy.uint8)

        return ImageData(
            data,
            mask,
            crs=self.crs,
            bounds=self.bounds,
            assets=self.assets,
            metadata=self.metadata,
        )

    def render(
        self,
        add_mask: bool = True,
        img_format: str = "PNG",
        colormap: Optional[ColorMapType] = None,
        **kwargs,
    ) -> bytes:
        """Render data to image blob.

        Args:
            add_mask (bool, optional): add mask to output image. Defaults to `True`.
            img_format (str, optional): output image format. Defaults to `PNG`.
            colormap (dict or sequence, optional): RGBA Color Table dictionary or sequence.
            kwargs (optional): keyword arguments to forward to `rio_tiler.utils.render`.

        Returns:
            bytes: image.

        """
        img_format = img_format.upper()

        if img_format == "GTIFF":
            if "transform" not in kwargs:
                kwargs.update({"transform": self.transform})
            if "crs" not in kwargs and self.crs:
                kwargs.update({"crs": self.crs})

        data = self.data.copy()
        datatype_range = (dtype_ranges[str(data.dtype)],)

        if not colormap:
            if img_format in ["PNG"] and data.dtype not in ["uint8", "uint16"]:
                warnings.warn(
                    f"Invalid type: `{data.dtype}` for the `{img_format}` driver. Data will be rescaled using min/max type bounds.",
                    InvalidDatatypeWarning,
                )
                data = rescale_image(data, self.mask, in_range=datatype_range)

            elif img_format in ["JPEG", "WEBP"] and data.dtype not in ["uint8"]:
                warnings.warn(
                    f"Invalid type: `{data.dtype}` for the `{img_format}` driver. Data will be rescaled using min/max type bounds.",
                    InvalidDatatypeWarning,
                )
                data = rescale_image(data, self.mask, in_range=datatype_range)

            elif img_format in ["JP2OPENJPEG"] and data.dtype not in [
                "uint8",
                "int16",
                "uint16",
            ]:
                warnings.warn(
                    f"Invalid type: `{data.dtype}` for the `{img_format}` driver. Data will be rescaled using min/max type bounds.",
                    InvalidDatatypeWarning,
                )
                data = rescale_image(data, self.mask, in_range=datatype_range)

        if add_mask:
            return render(
                data, self.mask, img_format=img_format, colormap=colormap, **kwargs
            )

        return render(data, img_format=img_format, colormap=colormap, **kwargs)


import random
from interact import *

# intro....

print(colors.yellow,'________________________ThisGuyCodez_________')
print(colors.green,' O')
print(colors.green,'\|/')
print(colors.green,' |')
print(colors.green,'/ \\')
print(colors.lightred,'_____________________________________________')
print(colors.orange,'__Python__HangMan_Terminal_Game______________')
print(colors.purple,'_____________________________________________')

# random names list

words = ["Sachmo","Waterfall", "Pineapple", "Island" , "Roswell", "Locksmith"]

# game scope
def game():
	#color control
	print(colors.orange)

	# WORNG ANSWER COUNT. if reaches 6(5 in code) then its game over.
	wrong_count = -1

	# get the word that needs to be guessed
	word = random.choice(words)

	# creates a _ space for each letter into an array then joined as a string
	# Also a list of the empty spaces to be filled
	word_spaces = ['_' for char in word]

	print('Guess 1 letter or you can guess the word...')
	print(f"It's a {len(word)} letter word: ", " ".join(word_spaces))

	# this should continue until all spaces
	# are filled or the deadman is all there

	def ask_4_guess(wrong_count):
		# color control
		print(colors.yellow)

		# first if/else-------------------------------------------------------running main prompts--------------------------------------------1

		# if true then its a letter they're guessing
		if ask_4_guess_type():
			# grab the letter
			guess = ask_4_letter_guess(word_spaces)

			# keep track whether or not the letter was found in there
			found = False

			# check if the letter is in the hidden word
			# if so then the letter should fill all the spots it is in
			for l in range(len(word)):
				# if word[l] is the users letter guess
				if word[l].lower() == guess.lower():
					# then the same exact iteration spot in 'word_spaces'
					# should == the letter
					word_spaces[l] = guess

					# let it be known the letter was found
					found = True

			# if letter was not found, add 1 to wrong_count
			if found == False:
				# add 1 to wrong count
				wrong_count = wrong_count+1
				# print the relevant
				wrong_answer(wrong_count)

		# if false then its a word they're guessing
		else:
			# grab the word
			guess = ask_4_word_guess()

			# see if the word matches
			if guess.lower() == word.lower():
				won_game(word)
				return wanna_play_again(game)
			# if word does not match, add 1 to wrong_count
			else:
				wrong_count = wrong_count+1
				# print the relevant
				wrong_answer(wrong_count)

		# first if/else-------------------------------------------------------running main prompts--------------------------------------------1

		# second if/else-----------------------------------------------Games Current Result--------------------------------------------------2
		# color control
		print(colors.yellow)
		print("Progress So Far: ", " ".join(word_spaces))

		'''
		logic....

		- if the user ran out of chances to guess then the game should end....

		- if there are still blank spots then continue the game or it should be a win
		'''
		# did user run out of guess chances 6(5 in code)
		if wrong_count == 5:
			# GAME LOST
			# ask to play again
			return wanna_play_again(game)

		# if there are still blank spaces
		elif '_' in " ".join(word_spaces):
			# then continue
			return ask_4_guess(wrong_count)

		# the game is over (user won)
		else:
			# GAME WON
			# print the winning msg
			won_game(word)
			# ask to play again
			return wanna_play_again(game)

		# second if/else-----------------------------------------------Games Current Result--------------------------------------------------2

	# run prompt loop
	return ask_4_guess(wrong_count)

# run game
game()


import librosa
import pickle
import numpy as np
import random
import torch
from torch import nn
import os
import soundfile as sf
from shutil import copyfile
import threading
import matplotlib.pyplot as plt
from ConvAE import ConvAE, create_network, accuracy_1_min_mab, normalized_loss
from pipeline_whole import SampleLibrary
sampler_dataset = pickle.load(open("simple_dataset.pkl", "rb"))
print("done loading data")

def worker_init_fn(worker_id):
    seed = np.random.get_state()[1][0] + worker_id
    np.random.seed(seed)
    random.seed(seed)

sampler_dataset_iterable = iter(torch.utils.data.DataLoader(sampler_dataset,
                                                      batch_size=8,
                                                      num_workers=0,
                                                      # pin_memory=True,
                                                      worker_init_fn=worker_init_fn)) # what is pin memory?
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3)
plt.ion() #needed to prevent show() from blocking
# plt.figure(figsize=(15,25))

def visualize(content, style, output, save = False, name = None, step = 'no-step', visible = True):
    ax1.clear()
    ax2.clear()
    ax3.clear()
    ax1.set_axis_off()
    ax2.set_axis_off()
    ax3.set_axis_off()
    ax1.title.set_text(f"Ground Truth")
    ax1.imshow(content)
    ax2.title.set_text(f"Style ({name})")
    ax2.imshow(style)
    ax3.title.set_text(f"Output")
    ax3.imshow(output)
    if visible:
        plt.show()
    plt.pause(1)
    if save and name is None:
        plt.savefig("test.png")
    elif save:
        plt.savefig(f"{name}_{step}.png", bbox_inches='tight',pad_inches = 0)

def phase_reconstructor(output, filename):
    N_FFT = 1024
    output = np.squeeze(output)
    a = np.zeros_like(output)
    a = np.exp(output) - 1
    print("phase reconstruction")
    # This code is supposed to do phase reconstruction
    p = 2 * np.pi * np.random.random_sample(a.shape) - np.pi
    for i in range(500):
        if i % 100 == 0:
            print("\t", i)
        S = a * np.exp(1j * p)
        x = librosa.istft(S)
        p = np.angle(librosa.stft(x, N_FFT))
    sf.write(filename, x, 22050)

def make_generator():
    feature_maps = 64
    depth = 8
    pooling_freq = 1e100  # large number to disable pooling layers
    strided_conv_freq = 2
    strided_conv_feature_maps = 64
    input_dim = (1, 513, 513)
    style_hidden = 32
    num_style_interferences = 3

    CONV_ENC_BLOCK = [("conv1", feature_maps), ("relu1", None)]
    CONV_ENC_LAYERS = create_network(CONV_ENC_BLOCK, depth,
                                        pooling_freq=pooling_freq,
                                        strided_conv_freq=strided_conv_freq,
                                        strided_conv_channels=strided_conv_feature_maps,
#                                         batch_norm_freq = 1e100
                                        )
    CONV_ENC_NW = CONV_ENC_LAYERS
    model = ConvAE(input_dim, enc_config=CONV_ENC_NW, num_instruments = 5, style_hidden_size = style_hidden, num_style_interferences =
                   num_style_interferences)
    return model

def make_classifier():
    feature_maps = 8
    depth = 12
    pooling_freq = 1e100  # large number to disable pooling layers
    strided_conv_freq = 2
    strided_conv_feature_maps = 8
    code_size = 5
    input_dim = (1, 513, 513)
    CONV_ENC_BLOCK = [("conv1", feature_maps), ("relu1", None)]
    CONV_ENC_LAYERS = create_network(CONV_ENC_BLOCK, depth,
                                     pooling_freq=pooling_freq,
                                     strided_conv_freq=strided_conv_freq,
                                     strided_conv_channels=strided_conv_feature_maps,
                                     )

    CONV_ENC_NW = CONV_ENC_LAYERS + [("flatten1", None), ("linear1", code_size), ("softmax1", None)]

    model = ConvAE(input_dim, enc_config=CONV_ENC_NW, disable_decoder = True)
    return model

reconstructor_thread_list = list()

def test_evaluate(generator_model, classifier_frozen, num_tests_per_instrument, step, save = True, diff_target = False):
    instruments = ["distortion", "harp", "harpsichord", "piano", "timpani"]
    averages_dict = {}
    style = None
#     input(generator_model.state_dict().keys())
    generator_model.eval()
    if save:
        print("saving model!")
        generator_model.save_feature_maps(step)
        torch.save(generator_model.state_dict(), f"ae_params_{step}.pt")

    soft_make_dir(f"evaluation_{step}")
    os.chdir(f"evaluation_{step}")
    if torch.cuda.is_available():
        device = "cuda"
    else:
        device = "cpu"

    for instrument in instruments:
        print(instrument)
        for i in range(num_tests_per_instrument):
            print(f"\t{i}")
            if diff_target:
                data, target, style = sampler_dataset.sampleTest(test_instrument=instrument)
                style = np.expand_dims(style, axis = 0)
                style = torch.as_tensor(style, device=device)

            else:
                data, target, one_hot = sampler_dataset.samplePair(test = True, test_instrument = instrument)

            data = np.expand_dims(data, axis = 0)
            target = np.expand_dims(target, axis = 0)
            data = torch.as_tensor(data, device=device)
            target = torch.as_tensor(target, device=device)

            style = style if diff_target else target

            style_vec = classifier_frozen.forward(style, None)

            out, code = generator_model.forward(data, style_vec)

            if torch.cuda.is_available():
                out = out.cpu().detach()
                target = target.cpu().detach()
                data = data.cpu().detach()
                style = style.cpu().detach()

            encoding_loss = ((out - target)**2).mean()
            if instrument not in averages_dict.keys():
                averages_dict[instrument] = 0
            averages_dict[instrument] += encoding_loss.numpy()
            print("saving plot!")
            visualize(data[0][0], style[0][0], out[0][0], save=True, name=instrument, step = i, visible = False)

            print("saving generating audios")
            t_gen = threading.Thread(target=phase_reconstructor, args=(out.numpy()[0], f"generated_{instrument}_{i}.wav"))
            t_truth = threading.Thread(target=phase_reconstructor, args=(target.numpy()[0], f"truth_{instrument}_{i}.wav"))
            t_gen.start()
            t_truth.start()
            reconstructor_thread_list.append(t_gen)
            reconstructor_thread_list.append(t_truth)
        averages_dict[instrument] /= num_tests_per_instrument

        for t in reconstructor_thread_list: #multithreading per trial
            t.join()
    print(averages_dict)
    import json
    json = json.dumps(averages_dict)
    f = open("losses.json", "w")
    f.write(json)
    f.close()
    os.chdir("../")
    generator_model.train()

def soft_make_dir(path):
    try:
        os.mkdir(path)
    except:
        print("directory already exists!")

def load_and_evaluate(generator_model, classifier_frozen, file_name, num_tests_per_instrument, step):
    generator_model.load_state_dict(torch.load(file_name))
    generator_model.load_feature_maps(step)
#     for key, value in generator_model.state_dict().items():
#         print(f"key {key}, value {value.shape}")
#     input("asdf")
    print("done loading!")
    soft_make_dir("evaluation")
    os.chdir("evaluation")
    test_evaluate(generator_model, classifier_frozen, num_tests_per_instrument = num_tests_per_instrument, step = step, save = False,
                  diff_target = True) #turn to true
    print("done!!")

def load_and_freeze_classifier(classifier, load_dir):
    classifier.load_state_dict(torch.load(load_dir))
    for p in classifier.parameters():
        p.requires_grad = False
    print("done loading and freezing classifier")
    return classifier

if __name__ == "__main__":
    #TODO: these are the parameters you can modify
    classifier_load_dir = "experiments_classifier/audio_classifier_smaller/evaluation_15000/classifier_params_15000.pt"
    experiment = "piano_fullmodel_unsupervised_truthstyle"
    num_training_steps = 15000
    path = f"experiments/{experiment}"
    load_test = True

    generator_model = make_generator()
    classifier = make_classifier()
    # input(classifier)
    classifier_frozen = load_and_freeze_classifier(classifier, classifier_load_dir)
    print("done generating and loading models")

    if torch.cuda.is_available():
        print("cuda available!")
        device = "cuda"
        classifier_frozen = classifier_frozen.cuda()
        generator_model = generator_model.cuda()
    else:
        device = "cpu"

    AE_optimizer = torch.optim.Adam(generator_model.parameters(), lr=1e-3)
    loss = nn.MSELoss()

    if load_test:
        exp_dir =  "piano_fullmodel_unsupervised_truthstyle"
        step = 15000
        file_name = f"ae_params_{step}.pt"
        tests_per_instrument = 25 #chanve back
        try:
            os.chdir(f"experiments/{exp_dir}")
        except:
            print("this experiment doesn't exist!")
            quit()
        load_and_evaluate(generator_model, classifier_frozen, file_name, num_tests_per_instrument = tests_per_instrument, step = step)
        quit()

    soft_make_dir(path)
    copyfile("train_unsupervised.py", f"{path}/train_unsupervised.py")
    copyfile("ConvAE.py", f"{path}/ConvAE.py")
    copyfile("pipeline_whole.py", f"{path}/pipeline_whole.py")
    os.chdir(path)

    norm_mult = 1e-7
    for i in range(num_training_steps + 1):
        x, target, one_hot = sampler_dataset_iterable.next()
        one_hot = torch.as_tensor(one_hot, device=device, dtype = torch.float32)
        x = torch.as_tensor(x, device=device)
        target = torch.as_tensor(target, device=device)
        style_vec = classifier_frozen.forward(target, None)
#         out, code = generator_model.forward(x, one_hot) #CHANGE BACK
        out, code = generator_model.forward(x, style_vec)
        if i % 1500 == 0:
            print("eval time!")
            test_evaluate(generator_model, classifier_frozen, num_tests_per_instrument = 5, step = i, save = True, diff_target = True)
        # print("l1 loss: ", norm_mult * torch.sum(torch.abs(out)).cpu().detach().numpy())
        # print("norm loss: " , norm_mult * torch.norm(out).cpu().detach().numpy())
        # encoding_loss = normalized_loss(out, target)
        encoding_loss = loss(out, target) #+ norm_mult * torch.sum(torch.abs(out))
        print(i, " ", encoding_loss.cpu().detach().numpy())
        AE_optimizer.zero_grad()
        encoding_loss.backward()
        AE_optimizer.step()


""" Test Album class """

import os
import pathlib
import tempfile

import pytest
from applescript import AppleScript

import photoscript
from tests.conftest import get_os_version, photoslib, suspend_capture
from tests.photoscript_config_data import (
    ALBUM_1_NAME,
    ALBUM_1_PATH_STR,
    ALBUM_1_PATH_STR_COLON,
    ALBUM_1_PHOTO_EXPORT_FILENAMES,
    ALBUM_1_PHOTO_UUIDS,
    ALBUM_1_POST_REMOVE_UUIDS,
    ALBUM_1_REMOVE_UUIDS,
    ALBUM_1_UUID,
    ALBUM_1_UUID_OSXPHOTOS,
    ALBUM_NAMES_ALL,
    ALBUM_NAMES_TOP,
    EMPTY_ALBUM_NAME,
    FOLDER_NAME,
    FOLDER_NAMES_ALL,
    FOLDER_NAMES_TOP,
    FOLDER_UUID,
    IMPORT_PATHS,
    IMPORT_PHOTOS,
    NUM_PHOTOS,
    PHOTO_ADD_UUID,
    PHOTO_FAVORITES_SET_UUID,
    PHOTO_FAVORITES_UNSET_UUID,
    PHOTOS_FAVORITES,
    PHOTOS_FAVORITES_SET,
    PHOTOS_FILENAMES,
    PHOTOS_PLANTS,
    PHOTOS_UUID,
    PHOTOS_UUID_FILENAMES,
    SELECTION_UUIDS,
)
from tests.utils import stemset

EMPTY_ALBUM_LEN = 0

########## Interactive tests run first ##########

########## Non-interactive tests ##########

def test_album_init():

    album = photoscript.Album(ALBUM_1_UUID)
    assert isinstance(album, photoscript.Album)

def test_album_init_osxphotos_uuid():
    """test Album() with osxphotos style UUID"""

    album = photoscript.Album(ALBUM_1_UUID_OSXPHOTOS)
    assert isinstance(album, photoscript.Album)
    assert album.id == ALBUM_1_UUID
    assert album.uuid == ALBUM_1_UUID_OSXPHOTOS

def test_album_init_bad_uuid():

    with pytest.raises(ValueError):
        assert photoscript.Album("BAD_UUID")

def test_album_id():

    album = photoscript.Album(ALBUM_1_UUID)
    assert album.id == ALBUM_1_UUID

def test_album_uuid():

    album = photoscript.Album(ALBUM_1_UUID)
    assert album.uuid == ALBUM_1_UUID_OSXPHOTOS

def test_len(photoslib: photoscript.PhotosLibrary):
    """test Album.__len__"""
    album = photoslib.album(ALBUM_1_NAME)
    assert len(album) == len(ALBUM_1_PHOTO_UUIDS)

def test_album_name_title(photoslib: photoscript.PhotosLibrary):
    album = photoslib.album(ALBUM_1_NAME)
    assert album.name == ALBUM_1_NAME
    assert album.title == ALBUM_1_NAME

def test_album_name_setter(photoslib: photoscript.PhotosLibrary):
    album = photoslib.album(ALBUM_1_NAME)
    new_name = "My New Album Name"
    album.name = new_name
    assert album.name == new_name
    assert album.title == new_name

    # reset name
    album.name = ALBUM_1_NAME

def test_album_title_setter(photoslib: photoscript.PhotosLibrary):
    album = photoslib.album(ALBUM_1_NAME)
    new_name = "My New Album Name"
    album.title = new_name
    assert album.name == new_name
    assert album.title == new_name

    # reset title
    album.title = ALBUM_1_NAME

def test_album_parent_id(photoslib: photoscript.PhotosLibrary):
    album = photoslib.album(ALBUM_1_NAME)
    assert album.parent.id == FOLDER_UUID

def test_album_parent(photoslib: photoscript.PhotosLibrary):

    album = photoslib.album(ALBUM_1_NAME)
    parent = album.parent
    assert isinstance(parent, photoscript.Folder)
    assert parent.name == FOLDER_NAME

def test_album_parent_top_level(photoslib: photoscript.PhotosLibrary):
    album = photoslib.album(ALBUM_NAMES_TOP[0])
    assert album.parent is None

def test_album_path_str(photoslib: photoscript.PhotosLibrary):
    album = photoslib.album(ALBUM_1_NAME)
    assert album.path_str() == ALBUM_1_PATH_STR
    assert album.path_str(":") == ALBUM_1_PATH_STR_COLON
    with pytest.raises(ValueError):
        assert album.path_str("FOO")

def test_album_photos(photoslib: photoscript.PhotosLibrary):
    album = photoslib.album(ALBUM_1_NAME)
    photo_ids = [p.id for p in album.photos()]
    assert sorted(photo_ids) == sorted(ALBUM_1_PHOTO_UUIDS)

def test_album_photos_empty(photoslib: photoscript.PhotosLibrary):
    album = photoslib.album(EMPTY_ALBUM_NAME)
    assert album.photos() == []

def test_album_photos_add(photoslib: photoscript.PhotosLibrary):

    global EMPTY_ALBUM_LEN
    album = photoslib.album(EMPTY_ALBUM_NAME)
    assert len(album) == 0
    added = album.add([photoscript.Photo(PHOTO_ADD_UUID)])
    assert len(album) == 1
    assert len(added) == 1
    assert added[0].id == PHOTO_ADD_UUID
    assert album.photos()[0].id == PHOTO_ADD_UUID

    EMPTY_ALBUM_LEN = len(album)

def test_album_photos_add_none(photoslib: photoscript.PhotosLibrary):
    """Test add with no photos"""

    album = photoslib.album(ALBUM_1_NAME)
    album_length = len(album)
    album.add([])
    assert len(album) == album_length

def test_album_import_photos(photoslib: photoscript.PhotosLibrary):
    """Test import photo"""

    global EMPTY_ALBUM_LEN
    cwd = os.getcwd()
    photo_paths = [str(pathlib.Path(cwd) / path) for path in IMPORT_PATHS]
    album = photoslib.album(EMPTY_ALBUM_NAME)
    imported = album.import_photos(photo_paths)
    assert len(imported) == len(IMPORT_PATHS)
    assert len(album) == EMPTY_ALBUM_LEN + len(IMPORT_PATHS)

    EMPTY_ALBUM_LEN = len(album)

def test_album_import_photos_skip_dup_check(photoslib: photoscript.PhotosLibrary):
    """Attempt to import a duplicate photo with skip_duplicate_check = True
    This will cause a duplicate photo to be imported"""

    # this test must be run after the previous test
    global EMPTY_ALBUM_LEN

    album = photoslib.album(EMPTY_ALBUM_NAME)
    cwd = os.getcwd()
    photo_paths = [str(pathlib.Path(cwd) / path) for path in IMPORT_PATHS]
    imported = album.import_photos(photo_paths, skip_duplicate_check=True)
    assert len(imported) == len(IMPORT_PATHS)
    assert len(album) == EMPTY_ALBUM_LEN + len(IMPORT_PATHS)

    EMPTY_ALBUM_LEN = len(album)

def test_album_export_photos_basic(photoslib: photoscript.PhotosLibrary):

    tmpdir = tempfile.TemporaryDirectory(prefix="photoscript_test_")
    album = photoslib.album(ALBUM_1_NAME)
    exported = album.export(tmpdir.name)
    exported = [pathlib.Path(filename).name for filename in exported]
    assert sorted(exported) == ALBUM_1_PHOTO_EXPORT_FILENAMES
    files = os.listdir(tmpdir.name)
    assert sorted(files) == sorted(ALBUM_1_PHOTO_EXPORT_FILENAMES)

def test_album_export_photos_duplicate_overwrite(photoslib: photoscript.PhotosLibrary):
    """Test calling export twice resulting in
    duplicate filenames but use overwrite = true"""

    tmpdir = tempfile.TemporaryDirectory(prefix="photoscript_test_")
    album = photoslib.album(ALBUM_1_NAME)
    exported1 = album.export(tmpdir.name, overwrite=True, original=True)
    exported2 = album.export(tmpdir.name, overwrite=True, original=True)
    exported = list({pathlib.Path(filename).name for filename in exported1 + exported2})

    # some versions of macOS use .JPG and some use .jpeg
    assert stemset(exported) == stemset(ALBUM_1_PHOTO_EXPORT_FILENAMES)
    files = os.listdir(tmpdir.name)
    assert stemset(files) == stemset(ALBUM_1_PHOTO_EXPORT_FILENAMES)

def test_album_remove_by_id(photoslib: photoscript.PhotosLibrary):
    """Test album.remove_by_id"""

    album = photoslib.album(ALBUM_1_NAME)
    parent_id = album.parent.id
    new_album = album.remove_by_id(ALBUM_1_REMOVE_UUIDS)
    assert isinstance(new_album, photoscript.Album)
    uuids = [photo.id for photo in new_album.photos()]
    assert sorted(uuids) == sorted(ALBUM_1_POST_REMOVE_UUIDS)
    assert new_album.title == ALBUM_1_NAME
    assert new_album.parent.id == parent_id
    assert album.id == new_album.id
    assert album.uuid == new_album.uuid

def test_album_remove(photoslib: photoscript.PhotosLibrary):
    """Test album.remove"""

    album = photoslib.album(ALBUM_1_NAME)
    photos = [photoscript.Photo(uuid) for uuid in ALBUM_1_REMOVE_UUIDS]
    new_album = album.remove(photos)
    assert isinstance(new_album, photoscript.Album)
    uuids = [photo.id for photo in new_album.photos()]
    assert sorted(uuids) == sorted(ALBUM_1_POST_REMOVE_UUIDS)
    assert new_album.title == ALBUM_1_NAME
    assert new_album.id == album.id


from collections import Counter

def analyze_feedback(feedback_list):
    if not feedback_list:
        return {
            'Most Frequent Positive Words': [],
            'Most Frequent Negative Words': [],
            'Overall Sentiment Score': 0,
            'Sentiment Report': 'Positive to Negative Ratio = N/A'
        }

    positive_words = set(['good', 'excellent', 'recommended', 'quick', 'highly'])
    negative_words = set(['terrible', 'bad', 'slow', 'poor'])

    positive_counts = Counter()
    negative_counts = Counter()

    for feedback in feedback_list:
        words = [word.lower().strip('.,?!') for word in feedback.split()]
        positive_counts.update([word for word in words if word in positive_words])
        negative_counts.update([word for word in words if word in negative_words])

    most_frequent_positive_words = [word for word, count in positive_counts.most_common()]
    most_frequent_negative_words = [word for word, count in negative_counts.most_common()]

    overall_sentiment_score = sum(positive_counts[word] for word in positive_words) - sum(negative_counts[word] for word in negative_words)

    total_words = sum(len(feedback.split()) for feedback in feedback_list)

    if total_words == 0:
        return {
            'Most Frequent Positive Words': most_frequent_positive_words,
            'Most Frequent Negative Words': most_frequent_negative_words,
            'Overall Sentiment Score': 0,
            'Sentiment Report': 'Positive to Negative Ratio = N/A'
        }

    positive_count = sum(positive_counts[word] for word in positive_words)
    negative_count = sum(negative_counts[word] for word in negative_words)
    positive_to_negative_ratio = positive_count / max(1, negative_count)

    return {
        'Most Frequent Positive Words': most_frequent_positive_words,
        'Most Frequent Negative Words': most_frequent_negative_words,
        'Overall Sentiment Score': overall_sentiment_score,
        'Sentiment Report': f'Positive to Negative Ratio = {positive_to_negative_ratio:.2f}:1'
    }

# Caso 1
feedback_list_1 = [
    "The service was excellent! Highly recommended.",
    "I had a terrible experience with the product quality.",
    "Good customer support and quick resolution.",
    "Very bad customer support and slow attention.",
    "Poor packaging and delivery service."
]

result_1 = analyze_feedback(feedback_list_1)
print("Caso 1:")
print(result_1)
print("\n---\n")

# Caso 2
feedback_list_2 = [
    "This is a good product.",
    "Excellent service!",
    "Satisfied with my purchase."
]

result_2 = analyze_feedback(feedback_list_2)
print("Caso 2:")
print(result_2)
print("\n---\n")

# Caso 3
feedback_list_3 = [
    "The service was bad.",
    "Poor customer experience.",
    "Terrible quality product."
]

result_3 = analyze_feedback(feedback_list_3)
print("Caso 3:")
print(result_3)
print("\n---\n")


import numpy as np
import pandas as pd

from utils import info, info_x, split_info_x

class C45Tree:
    leaf: bool
    partition_field: str
    leaf_class: np.ndarray
    subtrees: dict = {}
    most_popular_class: np.int64

    def __init__(self, data: pd.DataFrame) -> None:
        subset_fields = data.drop(columns='GRADE').columns

        subset_fields_gain_ratios = pd.Series(
            [gain_ratio(data, subset_field) * int(len(data[subset_field].unique()) != 1)
             for subset_field in subset_fields]).fillna(0)

        self.most_popular_class = data.GRADE.mode()[0]

        self.subtrees = {}

        self.leaf_class = data.GRADE.unique()

        if not any(subset_fields_gain_ratios) or len(data.GRADE.unique()) == 1:
            self.leaf = True
            return

        self.partition_field = subset_fields[np.argmax(
            subset_fields_gain_ratios)]
        self.leaf = False
        for partition_field_value in data[self.partition_field].unique():
            self.subtrees[partition_field_value] = C45Tree(
                data[data[self.partition_field] == partition_field_value].drop(columns=self.partition_field))

    def traverse(self, data_item: pd.DataFrame) -> np.int64:
        if not self.leaf:
            partition_value = data_item[self.partition_field]
            if partition_value in self.subtrees:
                return self.subtrees[partition_value].traverse(data_item)
            return self.most_popular_class
        final_class = self.leaf_class
        if len(final_class) == 1:
            return final_class[0]
        return self.most_popular_class

def gain_ratio(data: pd.DataFrame, partition_field: pd.Index):
    return (info(data) - info_x(data, partition_field)) / split_info_x(data, partition_field)


import pygmlion
import os
from collections import defaultdict

def get_test_files(test_name):
    _dir = os.path.join(os.getcwd(), 'test_graphs')

    test = {}
    for file in os.listdir(_dir):
        full_file = os.path.join(_dir, file)
        only_name = os.path.splitext(file)[0]

        info = only_name.split('_')

        if len(info) < 2:
            continue

        name = info.pop(0)

        if name == test_name:
            kind = info.pop(0)
            test[kind] = full_file

    return test

def read_file(filename):
    with open(filename, 'r') as f:
        return f.read()

def get_test_output(test_input):
    tempfile = '__test_file__.gml'
    parser.write_gml(test_input, tempfile)
    test_output = read_file(tempfile)
    os.unlink(tempfile)

    return test_output

def verify_identity(test):
    actual = get_test_output(parser.get_raw_gml(test['in']))
    expected = read_file(test['in'])

    assert actual == expected

def verify_transform(test):
    actual = get_test_output(parser.get_gml(test['in']))
    expected = read_file(test['out'])

    assert actual == expected

def test_ex_1():
    test = get_test_files('1')
    verify_identity(test)
    verify_transform(test)

def test_ex_2():
    test = get_test_files('2')
    verify_identity(test)
    verify_transform(test)

def test_ex_3():
    test = get_test_files('3')
    verify_identity(test)


## Array
## Backtracking

### Date: 07/20/2023

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        ans = []
        candidates.sort()

        def bt(start, total, path):
            if total == target:
                ans.append(path)
                return

            for i in range(start, len(candidates)):
                if total + candidates[i] > target:
                    return
                # skip duplicates
                elif i > start and candidates[i] == candidates[i-1]:
                    continue
                else:
                    bt(i + 1, total + candidates[i], path + [candidates[i]])

        bt(0, 0, [])
        return ans