Exemple #1
0
class PieChart(QDialog):
    def __init__(self, title: str, project_data, parent=None):
        super(PieChart, self).__init__(parent)
        self.setWindowTitle(title)
        self._layout = QVBoxLayout(self)
        self.setMinimumWidth(600)
        self.setMinimumHeight(500)
        self._create_pie_chart(project_data)

    '''定义饼状图并获取各区间信息'''

    def get_data(self, mark_data):
        pie_series = QPieSeries()  # 定义PieSeries
        total_area = 0
        for j in range(len(mark_data)):
            total_area += mark_data[j][1]
        for j in range(len(mark_data)):
            percentage = mark_data[j][1] / total_area * 100
            str1 = "{:.1f}%".format(percentage) + mark_data[j][0]
            pie_series.append(str1, mark_data[j][1])
        return pie_series

    '''绘制饼状图各区间'''

    def set_slice(self, pie_series: QPieSeries, mark_data) -> QPieSeries:
        for i in range(len(mark_data)):
            slice_ = pie_series.slices()[i]  # 地道饼图的某一个元素切片
            slice_.setLabelVisible()  # 设置各区域文本标签
            slice_.setPen(QPen(Qt.darkGreen, 0))  # 设置画笔类型——边界线颜色
            slice_.setBrush(mark_data[i][2])  # 设置笔刷——区域颜色
        return pie_series

    '''绘制饼状图并显示'''

    def _create_pie_chart(self, project_data: tuple):
        font = QFont("黑体")
        point_size = font.pointSize()
        font.setPixelSize(point_size * 90 / 72)

        self.char_view = QChartView(self)  # 将父窗体设置为空,设置为独立窗口
        self.char_view.setFont(font)
        self.char_view.setGeometry(100, 100, 800, 600)  # 设置窗口位置和大小
        self.char_view.setRenderHint(QPainter.Antialiasing)  # 消除锯齿

        pie = self.get_data(project_data)  # 获取区域种类及占比信息

        pie_series = self.set_slice(pie, project_data)  # 绘制饼状图各区间
        self.char_view.chart().addSeries(pie_series)  # 将饼状图添加至charView中
        self.char_view.chart().setTitle("各类型地物占比")  # 设置标题
        self.char_view.chart().legend().hide()
        self._layout.addWidget(self.char_view)

    def closeEvent(self, QCloseEvent):
        del self._layout
        del self.char_view
        del self
Exemple #2
0
    def create_chart(self):
        # 创建折线视图窗口
        modelutil = ModelUtil()
        dataTable = modelutil.get_score(self.username)

        chart = QChartView(self)
        #获取显示器高宽
        screeRect = QApplication.desktop().screenGeometry()
        chart.setGeometry(QtCore.QRect(screeRect))
        chart.setRenderHint(QPainter.Antialiasing)  # 抗锯齿
        chart.raise_()

        # qfont=QFont()
        # qfont.setPointSize(34)
        # qfont.setPixelSize(45)

        chart._chart = QChart(title="考试成绩折线图")  # 创建折线视图
        # chart._chart.setFont(qfont)
        # chart.setStyleSheet(
        #                          "QChartView{border:2px}"
        #                          "QChartView{border-radius:10px}"
        #                          "QChartView{font-family:宋体}"
        #                          "QChartView{word-wrap:true}"
        #                          "QChartView{font-size:25px}"
        #                          "QChartView{padding:2px 2px}")
        # chart._chart.setFont(qfont)
        # chart._chart.setBackgroundVisible(visible=False)      # 背景色透明
        chart._chart.setBackgroundBrush(QBrush(QColor("#FFFFFF")))  # 改变图背景色

        #  图形项默认无法接收悬停事件,可以使用QGraphicsItem的setAcceptHoverEvents()函数使图形项可以接收悬停事件。
        chart._chart.setAcceptHoverEvents(True)
        # 4条折线的坐标值

        # 执行创建折线的函数
        self.create_series(dataTable, chart)

        chart._chart.createDefaultAxes()  # 创建默认的轴

        chart._chart.axisY().setTickCount(11)  # y1轴设置10个刻度
        chart._chart.axisY().setLabelFormat("%d")
        chart._chart.axisY().setRange(0, 100)  # 设置y1轴范围

        xnum = len(dataTable[0]) - 1
        chart._chart.axisX().setTickCount(xnum)  # X轴设置10个刻度
        # 执行定义X轴的函数
        # self.customAxisX(chart._chart)

        chart.setChart(chart._chart)
class Ui_SmainWindow(object):
   
    def setupUi(self, SmainWindow): 
        width = QDesktopWidget().screenGeometry().width()
        height = QDesktopWidget().screenGeometry().height()
        '''screen_resolution = app.desktop().screenGeometry()
                                width, height = screen_resolution.width(), screen_resolution.height()'''
        SmainWindow.setObjectName("SmainWindow")
        SmainWindow.resize((3400/3840)*width,(1700/2160)*height)
        SmainWindow.setMaximumSize(QtCore.QSize((3400/3840)*width,(1700/2160)*height))
        SmainWindow.setMinimumSize(QtCore.QSize((3400/3840)*width,(1700/2160)*height))
        self.centralwidget = QtWidgets.QWidget(SmainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.line = QtWidgets.QFrame(self.centralwidget)
        self.line.setGeometry(QtCore.QRect((20/3840)*width, (1070/2160)*height ,(3300/3840)*width, (30/2160)*height))
        self.line.setFrameShape(QtWidgets.QFrame.HLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setLineWidth(5)
        self.line.setObjectName("line")

        self.line2 = QtWidgets.QFrame(self.centralwidget)
        self.line2.setGeometry(QtCore.QRect((1440/3840)*width, (290/2160)*height ,(30/3840)*width, (700/2160)*height))
        self.line2.setFrameShape(QtWidgets.QFrame.VLine)
        self.line2.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line2.setLineWidth(5)
        self.line2.setObjectName("line2")

        self.line3 = QtWidgets.QFrame(self.centralwidget)
        self.line3.setGeometry(QtCore.QRect((2290/3840)*width, (290/2160)*height ,(30/3840)*width, (700/2160)*height))
        self.line3.setFrameShape(QtWidgets.QFrame.VLine)
        self.line3.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line3.setLineWidth(5)
        self.line3.setObjectName("line3")
       

        self.layout = QVBoxLayout(self.centralwidget)
        self.fig = Figure(figsize=((8/3840)*width, (6.5/2160)*height ))
        self.canvas = FigureCanvas(self.fig)
        self.layout.addWidget(self.canvas)

        self.widget = QWidget(self.centralwidget)
        #self.toolbar = NavigationToolbar(self.canvas, self.widget)
        self.layout.setMenuBar(NavigationToolbar(self.canvas,self.widget))
        self.widget.setLayout(self.layout)
        self.widget.setGeometry((1480/3840)*width,(290/2160)*height,(800/3840)*width,(600/2160)*height)
        
        
        
        
        
        #layout.addWidget(self.canvas)
        '''
        self.graphicsView = PlotWidget(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(700, 150, 700, 700))
        self.graphicsView.setObjectName("graphicsView")
        '''
        self.chartView = QChartView(self.centralwidget)
        self.chartView.setGeometry(QtCore.QRect((200/3840)*width, (1090/2160)*height, (1700/3840)*width, (500/2160)*height))
        self.chartView.setObjectName("graphicsView")


        self.browseFile = QtWidgets.QPushButton(self.centralwidget)
        self.browseFile.setGeometry(QtCore.QRect((200/3840)*width, (50/2160)*height, (350/3840)*width, (50/2160)*height))
        self.browseFile.setObjectName("browseFile")


        self.filenameLabel = QtWidgets.QLabel(self.centralwidget)
        self.filenameLabel.setGeometry(QtCore.QRect((700/3840)*width, (55/2160)*height, (350/3840)*width, (70/2160)*height))
        self.filenameLabel.setObjectName("filenameLabel")

        self.datasize = QtWidgets.QLabel(self.centralwidget)
        self.datasize.setGeometry(QtCore.QRect((20/3840)*width, (105/2160)*height, (350/3840)*width, (70/2160)*height))
        self.datasize.setObjectName("datasize")
        self.datasize.setText("Data Shape :")
        self.datasize.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 10pt;
                           font-family: Typograf;}""")

        self.datashape = QtWidgets.QLabel(self.centralwidget)
        self.datashape.setGeometry(QtCore.QRect((250/3840)*width, (105/2160)*height, (350/3840)*width, (70/2160)*height))
        self.datashape.setObjectName("datashape")
        self.datashape.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 12pt;
                           font-family: Typograf;}""")

        self.atributelabe = QtWidgets.QLabel(self.centralwidget)
        self.atributelabe.setGeometry(QtCore.QRect((295/3840)*width, (200/2160)*height, (350/3840)*width, (70/2160)*height))
        self.atributelabe.setObjectName("atributelabe")
        self.atributelabe.setText("Variables")
        self.atributelabe.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 10pt;
                           font-family: Typograf;}""")

        self.statisticlabel = QtWidgets.QLabel(self.centralwidget)
        self.statisticlabel.setGeometry(QtCore.QRect((1020/3840)*width, (200/2160)*height, (350/3840)*width, (70/2160)*height))
        self.statisticlabel.setObjectName("statisticlabel")
        self.statisticlabel.setText("Statistics")
        self.statisticlabel.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 10pt;
                           font-family: Typograf;}""")
        
        self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
        self.textBrowser.setGeometry(QtCore.QRect((740/3840)*width, (290/2160)*height, (700/3840)*width, (700/2160)*height))
        self.textBrowser.setObjectName("textBrowser")
        self.textBrowser.setStyleSheet(
        """QTextBrowser {
                           font: bold;
                           font-size: 12pt;
                           font-family: Courier;}""")

        self.missingvalulabel = QtWidgets.QLabel(self.centralwidget)
        self.missingvalulabel.setGeometry(QtCore.QRect((2330/3840)*width, (500/2160)*height, (250/3840)*width, (100/2160)*height))
        self.missingvalulabel.setObjectName("missingvalulabel")
        self.missingvalulabel.setText("Show Missing \nValues")
        self.missingvalulabel.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 10pt;
                           font-family: Courier;}""")
        
        self.resetbtn = QtWidgets.QPushButton(self.centralwidget)
        self.resetbtn.setGeometry(QtCore.QRect((2330/3840)*width, (300/2160)*height, (250/3840)*width, (50/2160)*height))
        self.resetbtn.setObjectName("resetbtn")
        self.resetbtn.setText("Reset")
        self.resetbtn.setEnabled(False)

        self.perclm = QtWidgets.QPushButton(self.centralwidget)
        self.perclm.setGeometry(QtCore.QRect((2330/3840)*width, (600/2160)*height, (250/3840)*width, (50/2160)*height))
        self.perclm.setObjectName("perclm")
        self.perclm.setText("PerColumn")
        self.perclm.setEnabled(False)

        self.perrow = QtWidgets.QPushButton(self.centralwidget)
        self.perrow.setGeometry(QtCore.QRect((2330/3840)*width, (670/2160)*height, (250/3840)*width, (50/2160)*height))
        self.perrow.setObjectName("perrow")
        self.perrow.setText("PerRow")
        self.perrow.setEnabled(False)

        self.datainfo = QtWidgets.QLabel(self.centralwidget)
        self.datainfo.setGeometry(QtCore.QRect((2850/3840)*width, (200/2160)*height, (350/3840)*width, (70/2160)*height))
        self.datainfo.setObjectName("statisticlabel")
        self.datainfo.setText("Data Info")
        self.datainfo.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 10pt;
                           font-family: Typograf;}""")
        
        self.infor = QtWidgets.QTextBrowser(self.centralwidget)
        self.infor.setGeometry(QtCore.QRect((2600/3840)*width, (290/2160)*height, (700/3840)*width, (700/2160)*height))
        self.infor.setObjectName("infor")
        self.infor.setStyleSheet(
        """QTextBrowser {
                           font: bold;
                           font-family: Courier;}""")

       
       
        self.calstatistics = QtWidgets.QPushButton(self.centralwidget)
        self.calstatistics.setGeometry(QtCore.QRect((200/3840)*width, (1020/2160)*height, (350/3840)*width, (50/2160)*height))
        self.calstatistics.setObjectName("calstatistics")
        

        self.listWidget = QtWidgets.QListWidget(self.centralwidget)
        self.listWidget.setGeometry(QtCore.QRect((20/3840)*width, (290/2160)*height, (700/3840)*width, (700/2160)*height))
        self.listWidget.setObjectName("listWidget")
        self.listWidget.setAlternatingRowColors(True)
       


        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setGeometry(QtCore.QRect((1480/3840)*width,(120/2160)*height,(800/3840)*width,(50/2160)*height))
        self.comboBox.setObjectName("comboBox")

        self.comboBox2 = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox2.setGeometry(QtCore.QRect((1480/3840)*width,(200/2160)*height,(800/3840)*width,(50/2160)*height))
        self.comboBox2.setObjectName("comboBox2")

        self.report = QtWidgets.QPushButton(self.centralwidget)
        self.report.setGeometry(QtCore.QRect((1700/3840)*width, (1020/2160)*height, (300/3840)*width, (50/2160)*height))
        self.report.setObjectName("report")
        self.report.setText("Generate Report")



        self.back = QtWidgets.QPushButton(self.centralwidget)
        self.back.setGeometry(QtCore.QRect((5/3840)*width, (1600/2160)*height, (300/3840)*width, (50/2160)*height))
        self.back.setObjectName("back")
        self.back.setText("Back")
        self.back.setStyleSheet(
        """QPushButton {
                           
                             
border-radius:0;
border:0;

text-align:left;
padding-left:70px;
qproperty-icon:url('back.png');
qproperty-iconSize: 40px 40px;}""")






        SmainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(SmainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, (469/3840)*width, (22/2160)*height))
        self.menubar.setObjectName("menubar")
        SmainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(SmainWindow)
        self.statusbar.setObjectName("statusbar")
        SmainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(SmainWindow)
        QtCore.QMetaObject.connectSlotsByName(SmainWindow)

        




    def retranslateUi(self, SmainWindow):
        _translate = QtCore.QCoreApplication.translate
        SmainWindow.setWindowTitle(_translate("SmainWindow", "Data Statistical Analysis"))
        self.browseFile.setText(_translate("SmainWindow", "Open File"))
        self.browseFile.clicked.connect(self.pushButton_handler)
        self.filenameLabel.setText(_translate("SmainWindow", ""))
        self.calstatistics.setText(_translate("SmainWindow", "Calculate Statistics"))
        self.calstatistics.clicked.connect(self.cal)
        self.listWidget.clicked.connect(self.listview_clicked)

        self.resetbtn.clicked.connect(self.information)
        self.perclm.clicked.connect(self.num_missing)
        self.perrow.clicked.connect(self.row_missing)
        self.report.clicked.connect(self.generatereport)


            
        
        

    def pushButton_handler(self):
        self.open_dialog_box()

    def open_dialog_box(self):
        filename = QFileDialog.getOpenFileName(None, 'Open File', r"~/Desktop", '*.csv')
        path = filename[0]

        with open(path, "r") as fpath:
            self.infor.clear()
            self.comboBox.clear()
            self.comboBox2.clear()
            self.datasetheaders=[]
            self.filenameLabel.setText(str(path))
            self.filenameLabel.adjustSize()
            pandas.set_option('display.max_rows', None)
            self.dataset=pandas.read_csv(fpath)
            buf = io.StringIO()
            self.dataset.info(verbose=True, null_counts=True,buf=buf)
            s = buf.getvalue()
            self.perclm.setDisabled(False)
            self.perrow.setDisabled(False)

            self.infor.append(s)
            SIZE=self.dataset.shape
            self.datashape.setText(str(SIZE))
            self.create_piechart()
            #headers=self.dataset.columns
            self.datasetheaders=self.dataset.columns.to_numpy()
            self.listWidget.clear()
          
            for i in range(len(self.datasetheaders)-1):
                self.listWidget.insertItem(i,self.datasetheaders[i])

            for i in range(len(self.datasetheaders)-1):
                self.comboBox.addItem(self.datasetheaders[i])

            for i in range(len(self.datasetheaders)-1):
                self.comboBox2.addItem(self.datasetheaders[i])    
                
           

            self.setup()

            self.comboBox.currentIndexChanged.connect(self.setup)
            self.comboBox2.currentIndexChanged.connect(self.setup)

            #print(unique_headers)

            '''print ("Missing values per column:")
                                                print(self.dataset.apply(lambda x: sum(x.isnull()))) 
                                    '''


    def generatereport(self):
        try:
            profile = ProfileReport(self.dataset)
            profile.to_file(output_file="AnalysisReport.html")
            print("yes")
        except Exception as e:
            print(repr(e))

        
    def information(self):
        self.infor.clear()
        self.resetbtn.setEnabled(False)
        self.perrow.setDisabled(False)
        self.perclm.setDisabled(False)
        buf = io.StringIO()
        self.dataset.info(verbose=True, null_counts=True,buf=buf)
        s = buf.getvalue()

        self.infor.append(s)

      
            

            
        



    def row_missing(self):
        self.perrow.setEnabled(False)
        self.perclm.setDisabled(False)
        self.resetbtn.setDisabled(False)
        self.infor.clear()
       
        #self.infor.append(str(self.dataset.apply(lambda x: sum(x.isnull()))))
        self.infor.append(str(self.dataset.apply(self.missing, axis=1)))

        
    def num_missing(self):
        self.perclm.setEnabled(False)
        self.perrow.setDisabled(False)
        self.resetbtn.setDisabled(False)
        self.infor.clear()
        #self.infor.append(str(self.dataset.apply(lambda x: sum(x.isnull()))))
        self.infor.append(str(self.dataset.apply(self.missing, axis=0)))
         
    def missing(self,x):
        return sum(x.isnull())




         
 
    def setup(self):
        try:
            print("fig")
            iris=self.dataset 
        
       


            x_index = 0
            y_index = 1
            w=iris.iloc[:,self.comboBox.currentIndex()]
            z=iris.iloc[:,self.comboBox2.currentIndex()]

            y=iris.iloc[:,-1].values

            # this formatter will label the colorbar with the correct target names
            #formatter = plt.FuncFormatter(y)

            #plt.figure(figsize=(5, 4))
        
            ax = self.fig.add_subplot(111)
            ax.clear()
            scatter=ax.scatter(w, z, c=y)
        
            #self.figure.colorbar(ticks=y)

            #ax.xlabel("iris.feature_names[x_index]")
            #ax.ylabel("iris.feature_names[y_index]")
            ax.set_xlabel(self.comboBox.currentText(),  fontsize=25) 
            ax.set_ylabel(self.comboBox2.currentText(), fontsize=25)
            ax.set_title('Scatter Plot',fontsize=25)

            legend1 = ax.legend(*scatter.legend_elements(),
                    loc="lower left", title="Classes")
            ax.add_artist(legend1)

            self.widget.adjustSize()
        

            print("fig123456789")

        except Exception as e:
            print(repr(e)) 
               

        
        

        


    def cal(self):
        #self.graphicsView.clear()
        z=self.dataset
        w=z.iloc[:,self.a]
     
        self.textBrowser.setText("Mean:\n"+str(np.mean(w))+"\nMedian:\n"+str(np.median(w))+"\nMode:\n"+str(stats.mode(w))+"\nvariance:\n"+str(np.var(w))+"\nStdev:\n"+str(np.std(w)))
        #self.textBrowser.adjustSize()
        '''
        pen = pg.mkPen(color=(255, 0, 0),width=8)
        self.graphicsView.setBackground('w')
        self.graphicsView.plot(w,symbol='+',symbolSize=30, pen=pen)
        '''
       


    def listview_clicked(self):
        item=self.listWidget.currentRow()
        self.a=item

    def create_piechart(self):
       
        z=self.dataset
        w=z.iloc[:,-1]
        r=w.value_counts()
        p=r.to_numpy()
        y=w.nunique()
       
      
        df_val_counts = pandas.DataFrame(r)
        df_val_counts = df_val_counts.reset_index()
        df_val_counts.columns = ['unique_values', 'counts']
        
        w=df_val_counts.iloc[:,0].to_numpy()
        k=df_val_counts.iloc[:,1].to_numpy()
        res = w.astype(str)
       
        series = QPieSeries()
        for i in range(y):
            series.append(res[i], k[i])
        

        
        
        chart = self.chartView.chart()
        chart.removeAllSeries()
        chart.legend().hide()
        chart.addSeries(series)
        chart.createDefaultAxes()
        
        chart.setAnimationOptions(QChart.AllAnimations)
        chart.setTitle("Pie Chart")
        
        
        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)
      
        #self.chartView = QChartView(chart)
        self.chartView.setRenderHint(QPainter.Antialiasing)
Exemple #4
0
class FormGroupDiagramDiscipline(object):
    def __init__(self, main_window):
        self.dark_theme = False
        self.analytics_table_discipline_group_window = main_window.analytics_table_discipline_group_window
        self.session = main_window.session
        self.group_diagram_discipline_window = main_window.group_diagram_discipline_window
        self.group_diagram_discipline_window.setObjectName("MainWindow")
        self.group_diagram_discipline_window.setFixedSize(900, 563)
        self.centralwidget = QtWidgets.QWidget(
            self.group_diagram_discipline_window)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(760, 500, 112, 32))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.clicked.connect(self.close_window)
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(650, 500, 112, 32))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_2.clicked.connect(self.previous_page)
        self.label_11 = QtWidgets.QLabel(self.centralwidget)
        self.label_11.setGeometry(QtCore.QRect(10, 110, 551, 371))
        self.label_11.setMinimumSize(QtCore.QSize(400, 0))
        self.label_11.setObjectName("label_11")

        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(10, 10, 111, 20))
        self.label_3.setObjectName("label_3")

        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(115, 10, 361, 21))
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(360, 10, 51, 20))
        self.label_5.setObjectName("label_5")
        self.label_7 = QtWidgets.QLabel(self.centralwidget)
        self.label_7.setGeometry(QtCore.QRect(415, 10, 141, 21))
        self.label_7.setObjectName("label_7")
        self.label_9 = QtWidgets.QLabel(self.centralwidget)
        self.label_9.setGeometry(QtCore.QRect(10, 30, 90, 20))
        self.label_9.setObjectName("label_9")

        self.label_10 = QtWidgets.QLabel(self.centralwidget)
        self.label_10.setGeometry(QtCore.QRect(100, 30, 373, 20))
        self.label_10.setObjectName("label_10")
        self.label_8 = QtWidgets.QLabel(self.centralwidget)
        self.label_8.setGeometry(QtCore.QRect(70, 45, 373, 31))
        self.label_8.setObjectName("label_8")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(10, 50, 58, 21))
        self.label.setObjectName("label")

        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_3.setGeometry(QtCore.QRect(10, 500, 281, 32))
        self.pushButton_3.setObjectName("pushButton_3")
        self.pushButton_3.clicked.connect(self.show_proportional_chart)

        self.group_diagram_discipline_window.setCentralWidget(
            self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(
            self.group_diagram_discipline_window)
        self.statusbar.setObjectName("statusbar")
        self.group_diagram_discipline_window.setStatusBar(self.statusbar)

        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(10, 110, 880, 371))
        chart = QChart()
        self.chartview = QChartView(chart, self.centralwidget)
        self.chartview.setGeometry(QtCore.QRect(10, 100, 101, 2))

        self.retranslateUi(self.group_diagram_discipline_window)
        QtCore.QMetaObject.connectSlotsByName(
            self.group_diagram_discipline_window)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(
            _translate("MainWindow", "Аналитика: вывод диаграммы"))
        self.pushButton.setText(_translate("MainWindow", "Закрыть"))
        self.pushButton_2.setText(_translate("MainWindow", "Назад"))
        self.label_3.setText(_translate("MainWindow", "Дисциплина:"))
        self.label_4.setText(_translate("MainWindow", "ФИО"))
        self.label_9.setText(_translate("MainWindow", "Тип анализа:"))
        self.label_10.setText(
            _translate("MainWindow", "Наименование типа анализа"))
        self.pushButton_3.setText(
            _translate("MainWindow", "Отобразить диаграмму в пропорциях"))

    def close_window(self):
        self.group_diagram_discipline_window.close()

    def show_proportional_chart(self):
        self.group_diagram_discipline_window.hide()
        self.chartview.hide()

        name = []
        value = []
        for i in self.data:
            name.append(str(i[0]))
            value.append(float(i[1]))

        fig = Figure(
            figsize=(10, 3), dpi=100
        )  # Инициализирования объект fig класса Figure размером 10 на 3 и плотность 100
        ax = fig.add_subplot()  # Инициализиурем subplot ax

        # Задаем ax что будет именно круговая диаграмма
        ax.pie(
            value,  # Значения сколько раз встречается определенная степень образования
            labels=name,  # title для частей
            shadow=1,  # Тень
            startangle=90,  # Угол с которого будет начинаться первая доля
            autopct='%1.1f%%'  # Указываем, что необходимо отобраджать проценты
        )

        canvas = FigureCanvasQTAgg(fig)
        canvas.draw()

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(canvas)

        self.widget.setLayout(layout)
        self.widget.show()

        self.chartview.setGeometry(QtCore.QRect(2, 2, 3, 3))
        self.pushButton_3.hide()
        self.group_diagram_discipline_window.show()

    def previous_page(self):
        self.group_diagram_discipline_window.hide()
        self.analytics_table_discipline_group_window.show()

    def update(self, dark_theme):
        if dark_theme:
            self.group_diagram_discipline_window.setStyleSheet(window_css)
            self.pushButton.setStyleSheet(button_css)
            self.pushButton_2.setStyleSheet(button_css)
            self.pushButton_3.setStyleSheet(button_css)
            self.label.setStyleSheet(label_css)
            self.label_8.setStyleSheet(label_css)
            self.label_10.setStyleSheet(label_css)
            self.label_9.setStyleSheet(label_css)
            self.label_7.setStyleSheet(label_css)
            self.label_5.setStyleSheet(label_css)
            self.label_4.setStyleSheet(label_css)
            self.label_3.setStyleSheet(label_css)
            self.label_11.setStyleSheet(label_css)
            self.dark_theme = True
        else:
            self.group_diagram_discipline_window.setStyleSheet("")
            self.pushButton.setStyleSheet("")
            self.pushButton_2.setStyleSheet("")
            self.pushButton_3.setStyleSheet("")
            self.label.setStyleSheet("")
            self.label_8.setStyleSheet("")
            self.label_10.setStyleSheet("")
            self.label_9.setStyleSheet("")
            self.label_7.setStyleSheet("")
            self.label_5.setStyleSheet("")
            self.label_4.setStyleSheet("")
            self.label_3.setStyleSheet("")
            self.label_11.setStyleSheet("")
            self.dark_theme = False
class FormGroupDiagram(object):
    def __init__(self, main_window):
        self.dark_theme = False
        self.analytics_table_group_window = main_window.analytics_table_group_window
        self.session = main_window.session
        self.group_diagram_window = main_window.group_diagram_window
        self.group_diagram_window.setObjectName("MainWindow")
        self.group_diagram_window.setFixedSize(900, 563)
        self.centralwidget = QtWidgets.QWidget(self.group_diagram_window)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(760, 500, 112, 32))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.clicked.connect(self.close_window)
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(650, 500, 112, 32))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_2.clicked.connect(self.previous_page)
        self.label_11 = QtWidgets.QLabel(self.centralwidget)
        self.label_11.setGeometry(QtCore.QRect(10, 110, 551, 371))
        self.label_11.setMinimumSize(QtCore.QSize(400, 0))
        self.label_11.setObjectName("label_11")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(10, 10, 111, 20))
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(115, 10, 361, 21))
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(360, 10, 51, 20))
        self.label_5.setObjectName("label_5")
        self.label_7 = QtWidgets.QLabel(self.centralwidget)
        self.label_7.setGeometry(QtCore.QRect(415, 10, 141, 21))
        self.label_7.setObjectName("label_7")
        self.label_9 = QtWidgets.QLabel(self.centralwidget)
        self.label_9.setGeometry(QtCore.QRect(10, 30, 90, 20))
        self.label_9.setObjectName("label_9")
        self.label_10 = QtWidgets.QLabel(self.centralwidget)
        self.label_10.setGeometry(QtCore.QRect(100, 30, 373, 20))
        self.label_10.setObjectName("label_10")
        self.label_8 = QtWidgets.QLabel(self.centralwidget)
        self.label_8.setGeometry(QtCore.QRect(70, 45, 373, 31))
        self.label_8.setObjectName("label_8")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(10, 50, 58, 21))
        self.label.setObjectName("label")
        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_3.setGeometry(QtCore.QRect(10, 500, 281, 32))
        self.pushButton_3.setObjectName("pushButton_3")
        self.pushButton_3.clicked.connect(self.show_proportional_chart)
        self.group_diagram_window.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(self.group_diagram_window)
        self.statusbar.setObjectName("statusbar")
        self.group_diagram_window.setStatusBar(self.statusbar)

        self.retranslateUi(self.group_diagram_window)
        QtCore.QMetaObject.connectSlotsByName(self.group_diagram_window)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(
            _translate("MainWindow", "Аналитика: вывод диаграммы"))
        self.pushButton.setText(_translate("MainWindow", "Закрыть"))
        self.pushButton_2.setText(_translate("MainWindow", "Назад"))
        self.label_11.setText(_translate("MainWindow", "TextLabel"))
        self.label_3.setText(_translate("MainWindow", "Номер группы:"))
        self.label_4.setText(_translate("MainWindow", "ФИО"))
        self.label_5.setText(_translate("MainWindow", "Сессия:"))
        self.label_7.setText(_translate("MainWindow", "Тип сессии"))
        self.label_9.setText(_translate("MainWindow", "Тип анализа:"))
        self.label_10.setText(
            _translate("MainWindow", "Наименование типа анализа"))
        self.label_8.setText(_translate("MainWindow", "Наименование периода"))
        self.label.setText(_translate("MainWindow", "Период:"))
        self.pushButton_3.setText(
            _translate("MainWindow", "Отобразить диаграмму в пропорциях"))

    def close_window(self):
        self.group_diagram_window.close()

    def show_proportional_chart(self):
        type_diagram = self.pushButton_3.text()
        self.group_diagram_window.hide()
        if type_diagram == "Отобразить диаграмму в пропорциях":

            group = self.label_4.text()
            session = self.label_7.text()
            period = self.label_8.text()

            control = Control()
            result: np.ndarray = control.analysis_group_proportional(
                self.session, group, session, period)

            r_len = len(result)
            set0 = QBarSet('0-24')
            set1 = QBarSet('25-49')
            set2 = QBarSet('50-74')
            set3 = QBarSet('75-100')

            if r_len == 4:
                set0 << int(result[0][1]) << int(result[1][1]) << int(
                    result[2][1]) << int(result[3][1])
                set1 << int(result[0][2]) << int(result[1][2]) << int(
                    result[2][2]) << int(result[3][2])
                set2 << int(result[0][3]) << int(result[1][3]) << int(
                    result[2][3]) << int(result[3][3])
                set3 << int(result[0][4]) << int(result[1][4]) << int(
                    result[2][4]) << int(result[3][4])

            elif r_len == 3:
                set0 << int(result[0][1]) << int(result[1][1]) << int(
                    result[2][1])
                set1 << int(result[0][2]) << int(result[1][2]) << int(
                    result[2][2])
                set2 << int(result[0][3]) << int(result[1][3]) << int(
                    result[2][3])
                set3 << int(result[0][4]) << int(result[1][4]) << int(
                    result[2][4])

            elif r_len == 2:
                set0 << int(result[0][1]) << int(result[1][1])
                set1 << int(result[0][2]) << int(result[1][2])
                set2 << int(result[0][3]) << int(result[1][3])
                set3 << int(result[0][4]) << int(result[1][4])

            else:
                set0 << int(result[0][1])
                set1 << int(result[0][2])
                set2 << int(result[0][3])
                set3 << int(result[0][4])

            cat = []
            for i in result:
                cat.append(i[0])

            series = QPercentBarSeries()
            series.append(set0)
            series.append(set1)
            series.append(set2)
            series.append(set3)

            chart = QChart()
            chart.addSeries(series)
            chart.setAnimationOptions(QChart.SeriesAnimations)

            axis = QBarCategoryAxis()
            axis.append(cat)
            chart.createDefaultAxes()
            chart.setAxisX(axis, series)

            chart.legend().setVisible(True)
            chart.legend().setAlignment(Qt.AlignBottom)
            centralwidget = self.centralwidget
            self.chartview = QChartView(chart, centralwidget)
            self.chartview.setGeometry(QtCore.QRect(10, 110, 880, 371))

        else:
            series = QPieSeries()
            for i in self.data:
                value = str(i[0]) + " / " + str(i[1])
                series.append(value, int(i[1]))

            # adding slice
            slice = QPieSlice()
            slice = series.slices()[0]
            slice.setExploded(True)
            slice.setLabelVisible(True)
            slice.setPen(QPen(Qt.darkGreen, 2))
            slice.setBrush(Qt.green)

            chart = QChart()
            chart.legend().hide()
            chart.addSeries(series)
            chart.createDefaultAxes()
            chart.setAnimationOptions(QChart.SeriesAnimations)

            chart.legend().setVisible(True)
            chart.legend().setAlignment(Qt.AlignBottom)
            centralwidget = self.centralwidget
            self.chartview = QChartView(chart, centralwidget)
            self.chartview.setGeometry(QtCore.QRect(10, 110, 880, 371))

        self.pushButton_3.hide()
        self.group_diagram_window.show()

    def previous_page(self):
        self.group_diagram_window.hide()
        self.analytics_table_group_window.show()

    def update(self, dark_theme):
        if dark_theme:
            self.group_diagram_window.setStyleSheet(window_css)
            self.pushButton.setStyleSheet(button_css)
            self.pushButton_2.setStyleSheet(button_css)
            self.label_11.setStyleSheet(label_css)
            self.label.setStyleSheet(label_css)
            self.pushButton_3.setStyleSheet(button_css)
            self.label_8.setStyleSheet(label_css)
            self.label_10.setStyleSheet(label_css)
            self.label_9.setStyleSheet(label_css)
            self.label_3.setStyleSheet(label_css)
            self.label_4.setStyleSheet(label_css)
            self.label_7.setStyleSheet(label_css)
            self.label_5.setStyleSheet(label_css)

            self.dark_theme = True
        else:
            self.group_diagram_window.setStyleSheet("")
            self.pushButton.setStyleSheet("")
            self.pushButton_2.setStyleSheet("")
            self.label_11.setStyleSheet("")
            self.label.setStyleSheet("")
            self.pushButton_3.setStyleSheet("")
            self.label_8.setStyleSheet("")
            self.label_10.setStyleSheet("")
            self.label_9.setStyleSheet("")
            self.label_3.setStyleSheet("")
            self.label_4.setStyleSheet("")
            self.label_7.setStyleSheet("")
            self.label_5.setStyleSheet("")
            self.dark_theme = False
class MainUI(QtWidgets.QMainWindow):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.filename = ''
        self.json = ()
        self.datax = []
        self.percent = 0.0
        self.setFixedSize(1280, 720)
        self.center()
        # self.setWindowOpacity(0.9)
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
        self.setWindowTitle('恶意函数预测系统')
        spin_icon = qtawesome.icon('fa5b.github', color='black')
        self.setWindowIcon(spin_icon)

        self.main_widget = QtWidgets.QWidget()  # 创建窗口主部件
        self.main_layout = QtWidgets.QGridLayout()  # 创建主部件的网格布局
        self.main_widget.setLayout(self.main_layout)  # 设置窗口主部件布局为网格布局

        self.left_widget = QtWidgets.QWidget()  # 创建左侧部件
        self.left_widget.setObjectName('left_widget')
        self.left_layout = QtWidgets.QGridLayout()  # 创建左侧部件的网格布局层
        self.left_widget.setLayout(self.left_layout)  # 设置左侧部件布局为网格

        self.left_up_widget = QtWidgets.QWidget()  # 创建左侧部件的上半部件
        self.left_up_widget.setObjectName('left_up_widget')
        self.left_up_layout = QtWidgets.QGridLayout()  # 创建左侧部件的网格布局层
        self.left_up_widget.setLayout(self.left_up_layout)  # 设置左侧部件布局为网格

        self.left_down_widget = QtWidgets.QWidget()  # 创建左侧部件的下半部件
        self.left_down_widget.setObjectName('left_down_widget')
        self.left_down_layout = QtWidgets.QGridLayout()  # 创建左侧部件的网格布局层
        self.left_down_widget.setLayout(self.left_down_layout)  # 设置左侧部件布局为网格

        self.left_layout.addWidget(self.left_up_widget, 0, 0, 3, 2)
        self.left_layout.addWidget(self.left_down_widget, 3, 0, 9, 2)

        self.main_layout.addWidget(self.left_widget, 0, 0, 12, 8)  # 左侧部件在第0行第0列,占8行3列
        self.setCentralWidget(self.main_widget)  # 设置窗口主部件

        self.pushButton = QtWidgets.QPushButton()
        self.pushButton.setObjectName("pushButton")
        self.pushButton.setText("选择文件")
        self.pushButton.setFont(QFont("Times", 18))
        self.pushButton.setFixedWidth(300)
        self.pushButton.setFixedHeight(100)
        self.pushButton.setStyleSheet('''QPushButton{background:#6DDF6D;border-radius:15px;}
QPushButton:hover{background:green;}''')
        self.left_up_layout.addWidget(self.pushButton, 0, 0, 1, 1)
        self.pushButton.clicked.connect(self.openfile)
        self.show()

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def openfile(self):
        openfile_name = QFileDialog.getOpenFileName(self, '请选择文件夹路径', '', 'All Files (*)')
        self.filename = openfile_name[0]
        self.json = self.algorithm(self.filename)
        self.write(self.json)
        print(self.filename)

    def algorithm(self,filename):
        cmd = "ida64 -A -S\"Z:\\Users\\zhangbo\\Desktop\\PredictionSystem\\code_prediction\\extract_trace_v3.py\" \"Z:\\Users\\zhangbo\\Desktop\\linux程序\\bc\""
        cmd2 = "ida64 -A -S\"Z:\\Users\\zhangbo\\Desktop\\PredictionSystem\\code_prediction\\extract_trace_v3.py\" " +"\""+filename+"\""
        print(cmd2)
        # print(cmd)
        os.system(cmd2)
        test_path = filename[:filename.rfind("/")+1]+"test.csv"
        while(1):
            if(os.path.exists(test_path)):
                break
        j = pc.prediction(test_path)
        j = json.loads(j)
        os.remove(test_path)
        # print(j)
        return j
    def paintEvent(self, event):  # set background_img
        painter = QPainter(self)
        painter.drawRect(self.rect())
        # pixmap = QPixmap("./img.jpeg")  # 换成自己的图片的相对路径
        pixmap = QPixmap("./img.jpeg")  # 换成自己的图片的相对路径
        painter.drawPixmap(self.rect(), pixmap)

    def write(self, jsonfile):
        self.right_widget = QtWidgets.QTableWidget()  # 创建右侧部件
        self.right_widget.setObjectName('right_widget')
        self.right_layout = QtWidgets.QGridLayout()
        self.right_widget.setLayout(self.right_layout)  # 设置右侧部件布局为网格

        self.main_layout.addWidget(self.right_widget, 0, 8, 12, 4)  # 右侧部件在第0行第3列,占8行9列
        self.right_widget.setColumnCount(2)
        self.right_widget.setRowCount(len(jsonfile))
        self.right_widget.setHorizontalHeaderLabels(['函数名', '状态'])
        self.right_widget.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.right_widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        # self.right_widget.setStyleSheet("selection-background-color:pink")
        self.right_widget.setColumnWidth(0, 100)
        self.right_widget.setColumnWidth(1, 100)
        i = 0
        x = 0
        for key, value in jsonfile.items():
            print([key, value])
            newItem = QTableWidgetItem(key)
            self.right_widget.setItem(i, 0, newItem)
            newItem = QTableWidgetItem(str(value))
            self.right_widget.setItem(i, 1, newItem)
            if value == 0:
                self.right_widget.item(i, 0).setBackground(QBrush(QColor(255, 0, 0)))
                self.right_widget.item(i, 1).setBackground(QBrush(QColor(255, 0, 0)))
                x += 1
            i = i + 1
        self.percent = x / i
        self.show()
        self.chartx()

    def chartx(self):
        self.pieseries = QPieSeries()  # 定义PieSeries
        self.pieseries.append("正常程序", 1 - self.percent)  # 插入第一个元素
        self.pieseries.append("恶意程序", self.percent)

        self.slice = self.pieseries.slices()[0]  # 得到饼图的某一个元素切片,在这取得为第一个
        # self.slice.setExploded()  # 设置为exploded
        self.slice.setLabelVisible()  # 设置Lable
        self.slice.setPen(QPen(Qt.darkGreen, 1))  # 设置画笔类型
        self.slice.setBrush(Qt.green)  # 设置笔刷
        self.slice1 = self.pieseries.slices()[1]  # 得到饼图的某一个元素切片,在这取得为第一个
        self.slice1.setExploded()  # 设置为exploded
        self.slice1.setLabelVisible()  # 设置Lable
        self.slice1.setPen(QPen(Qt.darkRed, 1))  # 设置画笔类型
        self.slice1.setBrush(Qt.red)  # 设置笔刷
        self.chart = QChart()  # 定义QChart
        self.chart.addSeries(self.pieseries)  # 将 pieseries添加到chart里
        self.chart.setTitle("恶意程序预测结果饼状图")  # 设置char的标题
        self.chart.legend().hide()  # 将char的legend设置为隐藏
        self.charview = QChartView(self.chart,
                                   self.left_down_widget)  # 定义charView窗口,添加chart元素,设置主窗口为父窗体,既将chartView嵌入到父窗体
        self.charview.setGeometry(0, 0, 800, 500)  # 设置charview在父窗口的大小、位置
        self.charview.setRenderHint(QPainter.Antialiasing)  # 设置抗锯齿
        self.charview.show()  # 将CharView窗口显示出来
class Ui_MainWindow(QtWidgets.QMainWindow):
    def setupUi(self):
        self.setObjectName("MainWindow")
        self.resize(850, 550)
        self.setWindowTitle("Rastrigin")
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")

        self.frameChart = QChartView(self.centralwidget)
        self.frameChart.setGeometry(QtCore.QRect(10, 10, 620, 500))
        self.frameChart.setFrameShape(QtWidgets.QFrame.Box)
        self.frameChart.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.frameChart.setRenderHint(QPainter.Antialiasing)
        self.frameChart.setObjectName("frameChart")

        self.genParams = QtWidgets.QGroupBox(self.centralwidget)
        self.genParams.setGeometry(QtCore.QRect(650, 10, 161, 110))
        self.genParams.setObjectName("genParams")
        self.genParams.setTitle("General parameters")

        self.label1 = QtWidgets.QLabel(self.genParams)
        self.label1.setGeometry(QtCore.QRect(10, 20, 61, 16))
        self.label1.setObjectName("label1")
        self.label1.setText("Population:")

        self.label2 = QtWidgets.QLabel(self.genParams)
        self.label2.setGeometry(QtCore.QRect(10, 50, 91, 16))
        self.label2.setObjectName("label2")
        self.label2.setText("No. generations:")

        self.label3 = QtWidgets.QLabel(self.genParams)
        self.label3.setGeometry(QtCore.QRect(10, 80, 81, 16))
        self.label3.setObjectName("label3")
        self.label3.setText("No. dimensions:")

        self.tbxPopulation = QtWidgets.QLineEdit(self.genParams)
        self.tbxPopulation.setGeometry(QtCore.QRect(100, 20, 51, 20))
        self.tbxPopulation.setObjectName("tbxPopulation")

        self.tbxGenerations = QtWidgets.QLineEdit(self.genParams)
        self.tbxGenerations.setGeometry(QtCore.QRect(100, 50, 51, 20))
        self.tbxGenerations.setObjectName("tbxGenerations")

        self.tbxDimensions = QtWidgets.QLineEdit(self.genParams)
        self.tbxDimensions.setGeometry(QtCore.QRect(100, 80, 51, 20))
        self.tbxDimensions.setObjectName("tbxDimensions")

        self.gaParams = QtWidgets.QGroupBox(self.centralwidget)
        self.gaParams.setGeometry(QtCore.QRect(650, 130, 191, 105))
        self.gaParams.setObjectName("gaParams")
        self.gaParams.setTitle("GA parameters")

        self.label4 = QtWidgets.QLabel(self.gaParams)
        self.label4.setGeometry(QtCore.QRect(10, 20, 61, 16))
        self.label4.setObjectName("label4")
        self.label4.setText("Mutation:")

        self.label5 = QtWidgets.QLabel(self.gaParams)
        self.label5.setGeometry(QtCore.QRect(10, 50, 91, 16))
        self.label5.setObjectName("label5")
        self.label5.setText("Elite members:")

        self.label9 = QtWidgets.QLabel(self.gaParams)
        self.label9.setGeometry(QtCore.QRect(10, 80, 61, 16))
        self.label9.setObjectName("label9")
        self.label9.setText("Max abs.:")

        self.tbxMutation = QtWidgets.QLineEdit(self.gaParams)
        self.tbxMutation.setGeometry(QtCore.QRect(100, 20, 51, 20))
        self.tbxMutation.setObjectName("tbxMutation")

        self.tbxElite = QtWidgets.QLineEdit(self.gaParams)
        self.tbxElite.setGeometry(QtCore.QRect(100, 50, 51, 20))
        self.tbxElite.setObjectName("tbxElite")

        self.tbxMaxAbs = QtWidgets.QLineEdit(self.gaParams)
        self.tbxMaxAbs.setGeometry(QtCore.QRect(100, 80, 51, 20))
        self.tbxMaxAbs.setObjectName("tbxMAxAbs")

        self.psoParams = QtWidgets.QGroupBox(self.centralwidget)
        self.psoParams.setGeometry(QtCore.QRect(650, 240, 161, 110))
        self.psoParams.setObjectName("psoParams")
        self.psoParams.setTitle("PSO parameters")

        self.label6 = QtWidgets.QLabel(self.psoParams)
        self.label6.setGeometry(QtCore.QRect(10, 20, 61, 16))
        self.label6.setObjectName("label6")
        self.label6.setText("Inertia factor:")

        self.label7 = QtWidgets.QLabel(self.psoParams)
        self.label7.setGeometry(QtCore.QRect(10, 50, 91, 16))
        self.label7.setObjectName("label7")
        self.label7.setText("Personal factor:")

        self.label8 = QtWidgets.QLabel(self.psoParams)
        self.label8.setGeometry(QtCore.QRect(10, 80, 81, 16))
        self.label8.setObjectName("label8")
        self.label8.setText("Social factor:")

        self.tbxInertia = QtWidgets.QLineEdit(self.psoParams)
        self.tbxInertia.setGeometry(QtCore.QRect(100, 20, 51, 20))
        self.tbxInertia.setObjectName("tbxInertia")

        self.tbxPersonal = QtWidgets.QLineEdit(self.psoParams)
        self.tbxPersonal.setGeometry(QtCore.QRect(100, 50, 51, 20))
        self.tbxPersonal.setObjectName("tbxPersonal")

        self.tbxSocial = QtWidgets.QLineEdit(self.psoParams)
        self.tbxSocial.setGeometry(QtCore.QRect(100, 80, 51, 20))
        self.tbxSocial.setObjectName("tbxSocial")

        self.cbxNoVis = QtWidgets.QCheckBox(self.centralwidget)
        self.cbxNoVis.setGeometry(QtCore.QRect(650, 350, 170, 17))
        self.cbxNoVis.setObjectName("cbxNoVis")
        self.cbxNoVis.setText("No visualization per generation")

        self.btnStartGA = QtWidgets.QPushButton(self.centralwidget)
        self.btnStartGA.setGeometry(QtCore.QRect(650, 370, 75, 23))
        self.btnStartGA.setObjectName("btnStartGA")
        self.btnStartGA.setText("Start GA")

        self.btnStartPSO = QtWidgets.QPushButton(self.centralwidget)
        self.btnStartPSO.setGeometry(QtCore.QRect(650, 400, 75, 23))
        self.btnStartPSO.setObjectName("btnStartPSO")
        self.btnStartPSO.setText("Start PSO")

        self.btnStop = QtWidgets.QPushButton(self.centralwidget)
        self.btnStop.setEnabled(False)
        self.btnStop.setGeometry(QtCore.QRect(740, 370, 75, 53))
        self.btnStop.setObjectName("btnStop")
        self.btnStop.setText("Stop")

        self.btnSaveChart = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveChart.setGeometry(QtCore.QRect(650, 450, 121, 41))
        self.btnSaveChart.setObjectName("btnSaveChart")
        self.btnSaveChart.setText("Save chart as image")

        self.btnSaveChartSeries = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveChartSeries.setGeometry(QtCore.QRect(650, 500, 121, 41))
        self.btnSaveChartSeries.setObjectName("btnSaveChartSeries")
        self.btnSaveChartSeries.setText("Save chart as series")

        self.setCentralWidget(self.centralwidget)
        QtCore.QMetaObject.connectSlotsByName(self)

        #Connect events
        self.btnStartGA.clicked.connect(self.btnStartGA_Click)
        self.btnStartPSO.clicked.connect(self.btnStartPSO_Click)
        self.btnStop.clicked.connect(self.btnStop_Click)
        self.btnSaveChart.clicked.connect(self.btnSaveChart_CLick)
        self.btnSaveChartSeries.clicked.connect(self.btnSaveChartSeries_Click)

        #Set default variables
        self.tbxGenerations.insert(str(NGEN))
        self.tbxPopulation.insert(str(POP_SIZE))
        self.tbxDimensions.insert(str(NO_DIMS))
        self.tbxMutation.insert(str(GA_MUTPB))
        self.tbxElite.insert(str(GA_NELT))
        self.tbxMaxAbs.insert(str(GA_MAX_ABS))
        self.tbxInertia.insert(str(PSO_INERTIA))
        self.tbxPersonal.insert(str(PSO_PERSONAL))
        self.tbxSocial.insert(str(PSO_SOCIAL))

    def btnStartGA_Click(self):

        global combination_series  # List of lists containing min_series of 5   results -- Added by Denis Lazor
        global parameter_name  # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor
        global best_fit_values  # List containing best fitness values for every of 5 experiments per combination -- Added by Denis Lazor

        global DIM_SIZES
        global ELITE_SIZES
        global MAX_ABS_SIZES
        global MUTATION_SIZES

        # Checking if files are empty or not -- Added by Denis Lazor
        csv_contains_ga = os.stat("graphs_csv/original_ga.csv").st_size != 0

        # Clearing non empty files if we are trying to write to them -- Added by Denis Lazor
        if csv_contains_ga:
            clear_all_csv("ga")

        parameter_name = "original"
        n = 5000
        print("GA:\n")

        # Automation for all necessary combinations -- Added by Denis Lazor
        for d in DIM_SIZES:
            MUTATION_SIZES = [0.05, 0.1, 0.2]
            ELITE_SIZES = [4, 8, 16]
            MAX_ABS_SIZES = [0.4]

            for m in MUTATION_SIZES:
                for e in ELITE_SIZES:
                    for ma in MAX_ABS_SIZES:

                        for i in range(5):
                            # Set global variables
                            global stop_evolution
                            global q_min_series
                            global q_max_series
                            global q_avg_series
                            stop_evolution = False
                            q_min_series.clear()
                            q_max_series.clear()
                            q_avg_series.clear()

                            # Set global variables from information on UI
                            global NGEN
                            global POP_SIZE
                            global GA_MUTPB
                            global GA_NELT
                            global GA_MAX_ABS
                            NGEN = int(self.tbxGenerations.text())
                            POP_SIZE = int(self.tbxPopulation.text())
                            GA_MUTPB = m
                            GA_NELT = e
                            GA_MAX_ABS = ma

                            ####Initialize deap GA objects####

                            # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize
                            self.creator = creator
                            self.creator.create("FitnessMin",
                                                base.Fitness,
                                                weights=(-1.0, ))

                            # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type
                            self.creator.create(
                                "Individual",
                                list,
                                fitness=self.creator.FitnessMin)

                            # Create base toolbox for finishing creation of a individual (cromosome)
                            self.toolbox = base.Toolbox()

                            # Define what type of data (number, gene) will it be in the cromosome
                            self.toolbox.register("attr_float", random.uniform,
                                                  F_MIN, F_MAX)
                            # Initialization procedure (initRepeat) for the cromosome. For the individual to be completed we need to run initRepeat for the amaout of genes the cromosome includes
                            self.toolbox.register("individual",
                                                  tools.initRepeat,
                                                  self.creator.Individual,
                                                  self.toolbox.attr_float,
                                                  n=NO_DIMS)

                            # Create a population of individuals (cromosomes). The population is then created by toolbox.population(n=300) where 'n' is the number of cromosomes in population
                            self.toolbox.register("population",
                                                  tools.initRepeat, list,
                                                  self.toolbox.individual)

                            # Register evaluation function
                            self.toolbox.register("evaluate", evaluateInd)

                            # Register what genetic operators to use
                            # Standard coding
                            self.toolbox.register(
                                "mate", tools.cxTwoPoint
                            )  # Use two point recombination
                            self.toolbox.register("mutate",
                                                  tools.mutGaussian,
                                                  mu=0,
                                                  sigma=GA_MAX_ABS,
                                                  indpb=0.5)

                            self.toolbox.register(
                                "select", tools.selTournament,
                                tournsize=3)  # Use tournament selection

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

                            # Generate initial poplation. Will be a member variable so we can easely pass everything to new thread
                            self.pop = self.toolbox.population(n=POP_SIZE)

                            # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs evaluate function for each individual in pop
                            fitnesses = list(
                                map(self.toolbox.evaluate, self.pop))
                            for ind, fit in zip(self.pop, fitnesses):
                                ind.fitness.values = fit  # Assign calcualted fitness value to individuals

                            # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached
                            self.fits = [
                                ind.fitness.values[0] for ind in self.pop
                            ]

                            # Disable start and enable stop
                            self.btnStartGA.setEnabled(False)
                            self.btnStartPSO.setEnabled(False)
                            self.btnStop.setEnabled(False)
                            self.genParams.setEnabled(False)
                            self.gaParams.setEnabled(False)
                            self.psoParams.setEnabled(False)
                            self.cbxNoVis.setEnabled(False)

                            # Start evolution
                            self.evolveGA()

                        # Best fitness value -- Added by Denis Lazor

                        best_fit = np.array(min(best_fit_values))[0]
                        mean_fit = np.array(
                            min(best_fit_values,
                                key=lambda x: abs(x - statistics.mean(
                                    np.asarray(best_fit_values).flatten())))
                        )[0]

                        # Index of best fitness value -- Added by Denis Lazor
                        mean_fit_idx = best_fit_values.index(mean_fit)

                        write_to_file(combination_series[mean_fit_idx],
                                      parameter_name, "ga")

                        # First name will be "original", second one "max_abs" -- Added by Denis Lazor
                        parameter_name = "max_abs"

                        print_results_GA(POP_SIZE, m, e, ma, mean_fit,
                                         best_fit, NGEN, d)

                        # Clearing past lists  -- Added by Denis Lazor
                        combination_series = []
                        best_fit_values = []

                    # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor
                    MAX_ABS_SIZES = MAX_ABS_SIZES[0:1]
                    parameter_name = "elites"

                ELITE_SIZES = ELITE_SIZES[0:1]
                parameter_name = "mutation"

            MUTATION_SIZES = MUTATION_SIZES[0:1]
            parameter_name = "original"

    def btnStartPSO_Click(self):
        global combination_series  # List of lists containing min_series of 5   results -- Added by Denis Lazor
        global parameter_name  # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor
        global best_fit_values  # List containing best fitness values for every of 5 experiments per combination -- Added by Denis Lazor

        global DIM_SIZES
        global INERTIA_SIZES
        global PERSONAL_F_SIZES
        global SOCIAL_F_SIZES

        # Checking if files are empty or not -- Added by Denis Lazor
        csv_contains_pso = os.stat("graphs_csv/original_pso.csv").st_size != 0

        # Clearing non empty files if we are trying to write to them -- Added by Denis Lazor
        if csv_contains_pso:
            clear_all_csv("pso")

        n = 5000
        parameter_name = "original"
        print("PSO:\n")

        # Automation for all necessary combinations -- Added by Denis Lazor
        for d in DIM_SIZES:
            INERTIA_SIZES = [0.0, 0.37, 0.74]
            PERSONAL_F_SIZES = [0.5, 1.0, 1.5]
            SOCIAL_F_SIZES = [0.5, 1.0, 1.5]

            for in_f in INERTIA_SIZES:
                for pers_f in PERSONAL_F_SIZES:
                    for soc_f in SOCIAL_F_SIZES:

                        for i in range(5):
                            # Set global variables
                            global stop_evolution
                            global q_min_series
                            global q_max_series

                            global q_avg_series
                            stop_evolution = False
                            q_min_series.clear()
                            q_max_series.clear()
                            q_avg_series.clear()

                            # Set global variables from information on UI
                            global NGEN
                            global POP_SIZE
                            global PSO_INERTIA
                            global PSO_PERSONAL
                            global PSO_SOCIAL
                            NGEN = int(self.tbxGenerations.text())
                            POP_SIZE = int(self.tbxPopulation.text())
                            PSO_INERTIA = in_f
                            PSO_PERSONAL = pers_f
                            PSO_SOCIAL = soc_f

                            ####Initialize deap PSO objects####

                            # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize
                            self.creator = creator
                            self.creator.create("FitnessMin",
                                                base.Fitness,
                                                weights=(-1.0, ))

                            # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type
                            self.creator.create(
                                "Particle",
                                list,
                                fitness=self.creator.FitnessMin,
                                speed=list,
                                best=None)

                            # Create base toolbox for finishing creation of a individual (particle) and population
                            self.toolbox = base.Toolbox()

                            # Particle initialization
                            self.toolbox.register("particle",
                                                  generateParticle,
                                                  cr=self.creator,
                                                  size=NO_DIMS,
                                                  min_val=F_MIN,
                                                  max_val=F_MAX)

                            # Create a population of individuals (particles). The population is then created by e.g. toolbox.population(n=300) where 'n' is the number of particles in population
                            self.toolbox.register("population",
                                                  tools.initRepeat, list,
                                                  self.toolbox.particle)

                            # Update function for each particle
                            self.toolbox.register("update", updateParticle)

                            # Evaluation function for each particle
                            self.toolbox.register("evaluate", evaluateInd)

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

                            # Create population
                            self.pop = self.toolbox.population(n=POP_SIZE)

                            # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs emaluet function for each individual in pop
                            fitnesses = list(
                                map(self.toolbox.evaluate, self.pop))
                            for ind, fit in zip(self.pop, fitnesses):
                                ind.fitness.values = fit

                            # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached
                            self.fits = [
                                ind.fitness.values[0] for ind in self.pop
                            ]

                            # Extraction current best position
                            self.global_best_position = tools.selBest(
                                self.pop, 1)[0][:]

                            # Disable start and enable stop
                            self.btnStartGA.setEnabled(False)
                            self.btnStartPSO.setEnabled(False)
                            self.btnStop.setEnabled(False)
                            self.genParams.setEnabled(False)
                            self.gaParams.setEnabled(False)
                            self.psoParams.setEnabled(False)
                            self.cbxNoVis.setEnabled(False)

                            # Start evolution
                            self.evolvePSO()

                        # Best fitness value -- Added by Denis Lazor
                        best_fit = np.array(min(best_fit_values))[0]
                        mean_fit = np.array(
                            min(best_fit_values,
                                key=lambda x: abs(x - statistics.mean(
                                    np.asarray(best_fit_values).flatten())))
                        )[0]

                        # Index of best fitness value -- Added by Denis Lazor
                        mean_fit_idx = best_fit_values.index(mean_fit)

                        write_to_file(combination_series[mean_fit_idx],
                                      parameter_name, "pso")

                        # First name will be "original", second one "social_factor" -- Added by Denis Lazor
                        parameter_name = "social_factor"

                        print_results_PSO(POP_SIZE, in_f, pers_f, soc_f,
                                          mean_fit, best_fit, NGEN, d)

                        # Clearing past lists  -- Added by Denis Lazor
                        print(best_fit_values)
                        combination_series = []
                        best_fit_values = []

                    # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor
                    SOCIAL_F_SIZES = SOCIAL_F_SIZES[0:1]
                    parameter_name = "personal_factor"

                PERSONAL_F_SIZES = PERSONAL_F_SIZES[0:1]
                parameter_name = "inertia"

            INERTIA_SIZES = INERTIA_SIZES[0:1]
            parameter_name = "original"

    def btnStop_Click(self):
        global stop_evolution
        stop_evolution = True
        #Disable stop and enable start
        self.btnStartGA.setEnabled(True)
        self.btnStartPSO.setEnabled(True)
        self.btnStop.setEnabled(False)
        self.genParams.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.psoParams.setEnabled(True)
        self.cbxNoVis.setEnabled(True)

    #Function for GA evolution
    def evolveGA(self):
        global q_min_series
        global q_max_series
        global q_avg_series

        global combination_series
        global best_fit_values

        combination_current_series = [
        ]  # Clearing fitness values series -- Added by Denis Lazor

        # Variable for keeping track of the number of generations
        curr_g = 0

        # Begin the evolution till goal is reached or max number of generation is reached
        while min(self.fits) != 0 and curr_g < NGEN:
            #Check if evolution and thread need to stop
            if stop_evolution:
                break  #Break the evolution loop

            # A new generation
            curr_g = curr_g + 1
            # print("-- Generation %i --" % curr_g)

            # Select the next generation individuals
            #Select POP_SIZE - NELT number of individuals. Since recombination is between neigbours, not two naighbours should be the clone of the same individual
            offspring = []
            offspring.append(self.toolbox.select(
                self.pop, 1)[0])  #add first selected individual
            for i in range(
                    POP_SIZE - GA_NELT - 1
            ):  # -1 because the first seleceted individual is already added
                while True:
                    new_o = self.toolbox.select(self.pop, 1)[0]
                    if new_o != offspring[len(
                            offspring
                    ) - 1]:  #if it is different than the last inserted then add to offspring and break
                        offspring.append(new_o)
                        break

            # Clone the selected individuals because all of the changes are inplace
            offspring = list(map(self.toolbox.clone, offspring))

            # Apply crossover on the selected offspring
            for child1, child2 in zip(offspring[::2], offspring[1::2]):
                self.toolbox.mate(child1, child2)  #inplace recombination
                #Invalidate new children fitness values
                del child1.fitness.values
                del child2.fitness.values

            #Apply mutation on the offspring
            for mutant in offspring:
                if random.random() < GA_MUTPB:
                    self.toolbox.mutate(mutant)
                    del mutant.fitness.values

            #Add elite individuals #Is clonning needed?
            offspring.extend(
                list(map(self.toolbox.clone, tools.selBest(self.pop,
                                                           GA_NELT))))

            # Evaluate the individuals with an invalid fitness
            invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
            fitnesses = map(self.toolbox.evaluate, invalid_ind)
            for ind, fit in zip(invalid_ind, fitnesses):
                ind.fitness.values = fit

            # print("  Evaluated %i individuals" % len(invalid_ind))

            #Replace population with offspring
            self.pop[:] = offspring

            # Gather all the fitnesses in one list and print the stats
            self.fits = [ind.fitness.values[0] for ind in self.pop]

            length = len(self.pop)
            mean = sum(self.fits) / length
            sum2 = sum(x * x for x in self.fits)
            std = abs(sum2 / length - mean**2)**0.5

            q_min_series.append(curr_g, min(self.fits))
            q_max_series.append(curr_g, max(self.fits))
            q_avg_series.append(curr_g, mean)

            combination_current_series.append(
                min(self.fits)
            )  # Saving min_series fitness values of an experiment -- Added by Denis Lazor

            # print("  Min %s" % q_min_series.at(q_min_series.count()-1).y())
            # print("  Max %s" % q_max_series.at(q_max_series.count()-1).y())
            # print("  Avg %s" % mean)
            # print("  Std %s" % std)
            #
            if self.cbxNoVis.isChecked():
                app.processEvents()
            else:
                self.chart = QChart()
                self.chart.addSeries(q_min_series)
                self.chart.addSeries(q_max_series)
                self.chart.addSeries(q_avg_series)
                self.chart.setTitle("Fitness value over time")
                self.chart.setAnimationOptions(QChart.NoAnimation)
                self.chart.createDefaultAxes()
                self.frameChart.setChart(self.chart)
                self.frameChart.repaint()
                app.processEvents()

        #Printing best individual
        best_ind = tools.selBest(self.pop, 1)[0]
        # print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))

        #Visulaize final solution
        if self.cbxNoVis.isChecked():
            self.chart = QChart()
            self.chart.addSeries(q_min_series)
            self.chart.addSeries(q_max_series)
            self.chart.addSeries(q_avg_series)
            self.chart.setTitle("Fitness value over time")
            self.chart.setAnimationOptions(QChart.NoAnimation)
            self.chart.createDefaultAxes()
            self.frameChart.setChart(self.chart)
            self.frameChart.repaint()

        #Disable stop and enable start
        self.btnStartGA.setEnabled(True)
        self.btnStartPSO.setEnabled(True)
        self.btnStop.setEnabled(False)
        self.genParams.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.psoParams.setEnabled(True)
        self.cbxNoVis.setEnabled(True)
        app.processEvents()

        combination_series.append(combination_current_series
                                  )  # Saving 5 results -- Added by Denis Lazor
        best_fit_values.append(
            best_ind.fitness.values
        )  # Adding best fitness value of experiment -- Added by Denis Lazor

    #Function for GA evolution
    def evolvePSO(self):
        global q_min_series
        global q_max_series
        global q_avg_series

        global combination_series
        global best_fit_values

        combination_current_series = [
        ]  # Clearing fitness values series -- Added by Denis Lazor

        # Variable for keeping track of the number of generations
        curr_g = 0

        while min(self.fits) != 0.0 and curr_g < NGEN:
            #Check if evolution and thread need to stop
            if stop_evolution:
                break  #Break the evolution loop

            # A new generation
            curr_g = curr_g + 1
            # print("-- Generation %i --" % curr_g)

            #Update particle position and evaluate particle
            for particle in self.pop:
                #Update
                self.toolbox.update(particle, self.global_best_position,
                                    PSO_INERTIA, PSO_PERSONAL, PSO_SOCIAL)
                #Evaluate
                fit = self.toolbox.evaluate(particle)
                #Update best position
                if fit[0] < particle.fitness.values[0]:
                    particle.best = particle[:]
                #Update fitness
                particle.fitness.values = fit

            #Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached
            self.fits = [ind.fitness.values[0] for ind in self.pop]

            #Extraction current best position
            self.global_best_position = tools.selBest(self.pop, 1)[0][:]

            #Stats
            length = len(self.pop)
            mean = sum(self.fits) / length
            sum2 = sum(x * x for x in self.fits)
            std = abs(sum2 / length - mean**2)**0.5

            q_min_series.append(curr_g, min(self.fits))
            q_max_series.append(curr_g, max(self.fits))
            q_avg_series.append(curr_g, mean)

            combination_current_series.append(
                min(self.fits)
            )  # Saving min_series fitness values of an experiment -- Added by Denis Lazor

            # print("  Min %s" % q_min_series.at(q_min_series.count()-1).y())
            # print("  Max %s" % q_max_series.at(q_max_series.count()-1).y())
            # print("  Avg %s" % mean)
            # print("  Std %s" % std)
            #
            if self.cbxNoVis.isChecked():
                app.processEvents()
            else:
                self.chart = QChart()
                self.chart.addSeries(q_min_series)
                self.chart.addSeries(q_max_series)
                self.chart.addSeries(q_avg_series)
                self.chart.setTitle("Fitness value over time")
                self.chart.setAnimationOptions(QChart.NoAnimation)
                self.chart.createDefaultAxes()
                self.frameChart.setChart(self.chart)
                self.frameChart.repaint()
                app.processEvents()

        #Printing best individual
        best_ind = tools.selBest(self.pop, 1)[0]
        # print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))

        #Visulaize final solution
        if self.cbxNoVis.isChecked():
            self.chart = QChart()
            self.chart.addSeries(q_min_series)
            self.chart.addSeries(q_max_series)
            self.chart.addSeries(q_avg_series)
            self.chart.setTitle("Fitness value over time")
            self.chart.setAnimationOptions(QChart.NoAnimation)
            self.chart.createDefaultAxes()
            self.frameChart.setChart(self.chart)
            self.frameChart.repaint()

        #Disable stop and enable start
        self.btnStartGA.setEnabled(True)
        self.btnStartPSO.setEnabled(True)
        self.btnStop.setEnabled(False)
        self.genParams.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.psoParams.setEnabled(True)
        self.cbxNoVis.setEnabled(True)
        app.processEvents()

        combination_series.append(combination_current_series
                                  )  # Saving 5 results -- Added by Denis Lazor
        best_fit_values.append(
            best_ind.fitness.values
        )  # Adding best fitness value of experiment -- Added by Denis Lazor

    def btnSaveChart_CLick(self):
        p = self.frameChart.grab()
        filename, _ = QFileDialog.getSaveFileName(
            None, "Save series chart as a image", "", "Image Files (*.png)")
        p.save(filename, "PNG")
        print("Chart series image saved to: ", filename)

    def btnSaveChartSeries_Click(self):
        global q_min_series
        global q_max_series
        global q_avg_series
        filename, _ = QFileDialog.getSaveFileName(None,
                                                  "Save series to text file",
                                                  "",
                                                  "Text Files (*.txt, *.csv)")
        with open(filename, 'w') as dat:
            for i in range(q_min_series.count()):
                dat.write('%f,%f,%f\n' %
                          (q_min_series.at(i).y(), q_avg_series.at(i).y(),
                           q_max_series.at(i).y()))
        print("Chart series saved to: ", filename)
class Ui_MainWindow(QtWidgets.QMainWindow):
    def setupUi(self):
        self.setObjectName("MainWindow")
        self.resize(600, 830)
        self.setWindowTitle("GA - Queens")
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.frameWorld = MyQFrame(self.centralwidget)
        self.frameWorld.img = QPixmap(1000, 1000)
        self.frameWorld.setGeometry(QtCore.QRect(10, 10, 400, 400))
        self.frameWorld.setFrameShape(QtWidgets.QFrame.Box)
        self.frameWorld.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.frameWorld.setObjectName("frameWorld")
        self.frameChart = QChartView(self.centralwidget)
        self.frameChart.setGeometry(QtCore.QRect(10, 420, 400, 400))
        self.frameChart.setFrameShape(QtWidgets.QFrame.Box)
        self.frameChart.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.frameChart.setRenderHint(QPainter.Antialiasing)
        self.frameChart.setObjectName("frameChart")
        self.gaParams = QtWidgets.QGroupBox(self.centralwidget)
        self.gaParams.setGeometry(QtCore.QRect(430, 10, 161, 171))
        self.gaParams.setObjectName("gaParams")
        self.gaParams.setTitle("GA parameters")
        self.label1 = QtWidgets.QLabel(self.gaParams)
        self.label1.setGeometry(QtCore.QRect(10, 20, 61, 16))
        self.label1.setObjectName("label1")
        self.label1.setText("Population:")
        self.label2 = QtWidgets.QLabel(self.gaParams)
        self.label2.setGeometry(QtCore.QRect(10, 50, 47, 16))
        self.label2.setObjectName("label2")
        self.label2.setText("Mutation:")
        self.label3 = QtWidgets.QLabel(self.gaParams)
        self.label3.setGeometry(QtCore.QRect(10, 80, 81, 16))
        self.label3.setObjectName("label3")
        self.label3.setText("Elite members:")
        self.label4 = QtWidgets.QLabel(self.gaParams)
        self.label4.setGeometry(QtCore.QRect(10, 110, 91, 16))
        self.label4.setObjectName("label4")
        self.label4.setText("No. generations:")
        self.cbxPermutation = QtWidgets.QCheckBox(self.gaParams)
        self.cbxPermutation.setGeometry(QtCore.QRect(35, 140, 91, 17))
        self.cbxPermutation.setObjectName("cbxPermutation")
        self.cbxPermutation.setText("Permutation")
        self.tbxPopulation = QtWidgets.QLineEdit(self.gaParams)
        self.tbxPopulation.setGeometry(QtCore.QRect(100, 20, 51, 20))
        self.tbxPopulation.setObjectName("tbxPopulation")
        self.tbxMutation = QtWidgets.QLineEdit(self.gaParams)
        self.tbxMutation.setGeometry(QtCore.QRect(100, 50, 51, 20))
        self.tbxMutation.setObjectName("tbxMutation")
        self.tbxElite = QtWidgets.QLineEdit(self.gaParams)
        self.tbxElite.setGeometry(QtCore.QRect(100, 80, 51, 20))
        self.tbxElite.setObjectName("tbxElite")
        self.tbxGenerations = QtWidgets.QLineEdit(self.gaParams)
        self.tbxGenerations.setGeometry(QtCore.QRect(100, 110, 51, 20))
        self.tbxGenerations.setObjectName("tbxGenerations")
        self.label5 = QtWidgets.QLabel(self.centralwidget)
        self.label5.setGeometry(QtCore.QRect(440, 190, 61, 16))
        self.label5.setObjectName("label5")
        self.label5.setText("No. queens:")
        self.tbxNoQueens = QtWidgets.QLineEdit(self.centralwidget)
        self.tbxNoQueens.setGeometry(QtCore.QRect(510, 190, 51, 20))
        self.tbxNoQueens.setObjectName("tbxNoQueens")
        self.cbxNoVis = QtWidgets.QCheckBox(self.centralwidget)
        self.cbxNoVis.setGeometry(QtCore.QRect(420, 215, 170, 17))
        self.cbxNoVis.setObjectName("cbxNoVis")
        self.cbxNoVis.setText("No visualization per generation")
        self.btnStart = QtWidgets.QPushButton(self.centralwidget)
        self.btnStart.setGeometry(QtCore.QRect(430, 250, 75, 23))
        self.btnStart.setObjectName("btnStart")
        self.btnStart.setText("Start")
        self.btnStop = QtWidgets.QPushButton(self.centralwidget)
        self.btnStop.setEnabled(False)
        self.btnStop.setGeometry(QtCore.QRect(510, 250, 75, 23))
        self.btnStop.setObjectName("btnStop")
        self.btnStop.setText("Stop")
        self.btnSaveWorld = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveWorld.setGeometry(QtCore.QRect(430, 370, 121, 41))
        self.btnSaveWorld.setObjectName("btnSaveWorld")
        self.btnSaveWorld.setText("Save world as image")
        self.btnSaveChart = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveChart.setGeometry(QtCore.QRect(430, 730, 121, 41))
        self.btnSaveChart.setObjectName("btnSaveChart")
        self.btnSaveChart.setText("Save chart as image")
        self.btnSaveChartSeries = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveChartSeries.setGeometry(QtCore.QRect(430, 780, 121, 41))
        self.btnSaveChartSeries.setObjectName("btnSaveChartSeries")
        self.btnSaveChartSeries.setText("Save chart as series")
        self.setCentralWidget(self.centralwidget)
        QtCore.QMetaObject.connectSlotsByName(self)

        #Connect events
        self.btnStart.clicked.connect(self.btnStart_Click)
        self.btnStop.clicked.connect(self.btnStop_Click)
        self.btnSaveWorld.clicked.connect(self.btnSaveWorld_Click)
        self.btnSaveChart.clicked.connect(self.btnSaveChart_CLick)
        self.btnSaveChartSeries.clicked.connect(self.btnSaveChartSeries_Click)

        #Set default GA variables
        self.tbxNoQueens.insert(str(NO_QUEENS))
        self.tbxGenerations.insert(str(NGEN))
        self.tbxPopulation.insert(str(POP_SIZE))
        self.tbxMutation.insert(str(MUTPB))
        self.tbxElite.insert(str(NELT))

        self.new_image = QPixmap(1000, 1000)

    def btnStart_Click(self):

        global success  # Number of times when fitness function reached 0 -- Added by Denis Lazor
        global generations  # Number of times when fitness function reached 0 -- Added by Denis Lazor
        global combination_series  # List of lists containing min_series of 5 correct results -- Added by Denis Lazor
        global parameter_name  # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor

        global ELITE_SIZES
        global BOARD_SIZES
        global POPULATION_SIZES
        global MUTATION_SIZES

        # Checking if files are empty or not -- Added by Denis Lazor
        csv_contains = os.stat("graphs_csv/original_.csv").st_size != 0
        csv_contains_permutation = os.stat(
            "graphs_csv/original_permutation.csv").st_size != 0
        permutation_checked = self.cbxPermutation.isChecked()

        # Clearing non empty files if we are trying to write to them -- Added by Denis Lazor
        if csv_contains_permutation and permutation_checked:
            clear_all_csv("p")
        if csv_contains and not permutation_checked:
            clear_all_csv("np")

        BOARD_SIZES = [12, 24]
        n = 5000
        # Automation for all necessary combinations -- Added by Denis Lazor
        for b in BOARD_SIZES:
            # Because we use slicing we need to restore parameters lists after changing board size
            POPULATION_SIZES = [50, 100, 200]
            MUTATION_SIZES = [0.04, 0.08, 0.16]
            ELITE_SIZES = [4, 8, 16]

            for p in POPULATION_SIZES:
                for m in MUTATION_SIZES:
                    for e in ELITE_SIZES:

                        success = 0
                        trials = 0  # Number of tries needed to find 5 'correct' results -- Added by Denis Lazor

                        while success < 5:  # Doing same combination till we get 5 'correct' results -- Added by Denis Lazor
                            trials = trials + 1

                            # Set global variables
                            global stop_evolution
                            global q_min_series
                            global q_max_series
                            global q_avg_series
                            stop_evolution = False
                            q_min_series.clear()
                            q_max_series.clear()
                            q_avg_series.clear()

                            # Set global variables from information on UI
                            global NO_QUEENS
                            global NGEN
                            global POP_SIZE
                            global MUTPB
                            global NELT
                            NO_QUEENS = b
                            NGEN = n
                            POP_SIZE = p
                            MUTPB = m
                            NELT = e

                            # Painting chess table
                            self.img = QPixmap(1000, 1000)
                            self.img.fill()
                            painter = QPainter(self.img)
                            painter.setPen(QPen(Qt.black, 10, Qt.SolidLine))
                            width = 1000 / NO_QUEENS
                            cur_width = 0
                            for i in range(
                                    NO_QUEENS + 1
                            ):  # +1 in order to draw the last line as well
                                painter.drawLine(cur_width, 0, cur_width, 1000)
                                painter.drawLine(0, cur_width, 1000, cur_width)
                                cur_width += width
                            painter.end()
                            self.frameWorld.img = self.img
                            # Redrawing frames
                            self.frameWorld.repaint()
                            app.processEvents()

                            ####Initialize deap GA objects####

                            # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize
                            creator.create("FitnessMin",
                                           base.Fitness,
                                           weights=(-1.0, ))

                            # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type
                            creator.create("Individual",
                                           list,
                                           fitness=creator.FitnessMin)

                            # Create base toolbox for finishing creation of a individual (cromosome)
                            self.toolbox = base.Toolbox()

                            # Define what type of data (number, gene) will it be in the cromosome
                            if self.cbxPermutation.isChecked():
                                # Permutation coding
                                self.toolbox.register("indices", random.sample,
                                                      range(NO_QUEENS),
                                                      NO_QUEENS)
                                # initIterate requires that the generator of genes (such as random.sample) generates an iterable (a list) variable
                                self.toolbox.register("individual",
                                                      tools.initIterate,
                                                      creator.Individual,
                                                      self.toolbox.indices)
                            else:
                                # Standard coding
                                self.toolbox.register(
                                    "attr_int", random.randint, 0,
                                    NO_QUEENS - 1
                                )  # number in cromosome is from 0 till IND_SIZE - 1
                                # Initialization procedure (initRepeat) for the cromosome. For the individual to be completed we need to run initRepeat for the amaout of genes the cromosome includes
                                self.toolbox.register("individual",
                                                      tools.initRepeat,
                                                      creator.Individual,
                                                      self.toolbox.attr_int,
                                                      n=NO_QUEENS)

                            # Create a population of individuals (cromosomes). The population is then created by toolbox.population(n=300) where 'n' is the number of cromosomes in population
                            self.toolbox.register("population",
                                                  tools.initRepeat, list,
                                                  self.toolbox.individual)

                            # Register evaluation function
                            self.toolbox.register("evaluate", evaluateInd)

                            # Register what genetic operators to use
                            if self.cbxPermutation.isChecked():
                                # Permutation coding
                                self.toolbox.register(
                                    "mate",
                                    tools.cxUniformPartialyMatched,
                                    indpb=0.2
                                )  # Use uniform recombination for permutation coding
                                self.toolbox.register("mutate",
                                                      tools.mutShuffleIndexes,
                                                      indpb=0.2)
                            else:
                                # Standard coding
                                self.toolbox.register(
                                    "mate", tools.cxTwoPoint
                                )  # Use two point recombination
                                self.toolbox.register(
                                    "mutate",
                                    tools.mutUniformInt,
                                    low=0,
                                    up=NO_QUEENS - 1,
                                    indpb=0.2)  # 20% that the gene will change

                            self.toolbox.register(
                                "select", tools.selTournament,
                                tournsize=3)  # Use tournament selection

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

                            # Generate initial poplation. Will be a member variable so we can easely pass everything to new thread
                            self.pop = self.toolbox.population(n=POP_SIZE)

                            # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs evaluate function for each individual in pop
                            fitnesses = list(
                                map(self.toolbox.evaluate, self.pop))
                            for ind, fit in zip(self.pop, fitnesses):
                                ind.fitness.values = fit  # Assign calcualted fitness value to individuals

                            # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached
                            self.fits = [
                                ind.fitness.values[0] for ind in self.pop
                            ]

                            self.fits

                            # Disable start and enable stop
                            self.btnStart.setEnabled(False)
                            self.btnStop.setEnabled(True)
                            self.gaParams.setEnabled(False)
                            self.tbxNoQueens.setEnabled(False)
                            self.cbxNoVis.setEnabled(False)

                            # Start evolution
                            self.evolve()

                        # Mean number of generations nedeed for finding 5 correct solutions -- Added by Denis Lazor
                        mean_gen = min(generations,
                                       key=lambda x: abs(x - statistics.mean(
                                           generations)))
                        # Index of mean_gen value -- Added by Denis Lazor
                        mean_idx = generations.index(mean_gen)

                        write_to_file(
                            combination_series[mean_idx], parameter_name,
                            permutation_checked
                        )  # First name will be "original", second one "elites" -- Added by Denis Lazor
                        parameter_name = "elites"

                        print_results(b, p, m, e, trials, generations,
                                      mean_gen, NGEN)

                        # Clearing past lists  -- Added by Denis Lazor
                        generations = []
                        combination_series = []

                    # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor
                    ELITE_SIZES = ELITE_SIZES[0:1]
                    parameter_name = "mutation"
                MUTATION_SIZES = MUTATION_SIZES[0:1]
                parameter_name = "population"
            POPULATION_SIZES = POPULATION_SIZES[0:1]
            parameter_name = "original"

            n = 30000  # Increasing generation size for 24x24 board

    def btnStop_Click(self):
        global stop_evolution
        stop_evolution = True
        #Disable stop and enable start
        self.btnStop.setEnabled(False)
        self.btnStart.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.tbxNoQueens.setEnabled(True)
        self.cbxNoVis.setEnabled(True)

    #Function for GA evolution
    def evolve(self):
        global q_min_series
        global q_max_series
        global q_avg_series
        global success
        global generations
        global combination_series
        global NO_QUEENS
        global NGEN
        global POP_SIZE
        global MUTPB
        global NELT

        combination_current_series = []

        # Variable for keeping track of the number of generations
        curr_g = 0

        # Begin the evolution till goal is reached or max number of generation is reached
        while min(self.fits) != 0 and curr_g < NGEN:
            #Check if evolution and thread need to stop
            if stop_evolution:
                break  #Break the evolution loop

            # A new generation
            curr_g = curr_g + 1
            #print("-- Generation %i --" % curr_g)

            # Select the next generation individuals
            #Select POP_SIZE - NELT number of individuals. Since recombination is between neigbours, not two naighbours should be the clone of the same individual
            offspring = []
            offspring.append(self.toolbox.select(
                self.pop, 1)[0])  #add first selected individual
            for i in range(
                    POP_SIZE - NELT - 1
            ):  # -1 because the first seleceted individual is already added
                while True:
                    new_o = self.toolbox.select(self.pop, 1)[0]
                    if new_o != offspring[len(
                            offspring
                    ) - 1]:  #if it is different than the last inserted then add to offspring and break
                        offspring.append(new_o)
                        break

            # Clone the selected individuals because all of the changes are inplace
            offspring = list(map(self.toolbox.clone, offspring))

            # Apply crossover on the selected offspring
            for child1, child2 in zip(offspring[::2], offspring[1::2]):
                self.toolbox.mate(child1, child2)  #inplace recombination
                #Invalidate new children fitness values
                del child1.fitness.values
                del child2.fitness.values

            #Apply mutation on the offspring
            for mutant in offspring:
                if random.random() < MUTPB:
                    self.toolbox.mutate(mutant)
                    del mutant.fitness.values

            #Add elite individuals #Is clonning needed?
            offspring.extend(
                list(map(self.toolbox.clone, tools.selBest(self.pop, NELT))))

            # Evaluate the individuals with an invalid fitness
            invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
            fitnesses = map(self.toolbox.evaluate, invalid_ind)
            for ind, fit in zip(invalid_ind, fitnesses):
                ind.fitness.values = fit

            #print("  Evaluated %i individuals" % len(invalid_ind))

            #Replace population with offspring
            self.pop[:] = offspring

            # Gather all the fitnesses in one list and print the stats
            self.fits = [ind.fitness.values[0] for ind in self.pop]

            length = len(self.pop)
            mean = sum(self.fits) / length
            sum2 = sum(x * x for x in self.fits)
            std = abs(sum2 / length - mean**2)**0.5

            q_min_series.append(curr_g, min(self.fits))
            q_max_series.append(curr_g, max(self.fits))
            q_avg_series.append(curr_g, mean)

            combination_current_series.append(
                min(self.fits)
            )  # Saving min_series fitness values of an experiment -- Added by Denis Lazor

            # Checking if fitness value of 0 is reached -- Added by Denis Lazor
            for f in self.fits:
                if f == 0:
                    success = success + 1
                    generations.append(curr_g)
                    combination_series.append(combination_current_series)
                    break

            #print("  Min %s" % q_min_series.at(q_min_series.count()-1).y())
            #print("  Max %s" % q_max_series.at(q_max_series.count()-1).y())
            #print("  Avg %s" % mean)
            #print("  Std %s" % std)

            if self.cbxNoVis.isChecked():
                app.processEvents()
            else:
                #Draw queen positions of best individual on a image
                best_ind = tools.selBest(self.pop, 1)[0]
                self.updateWorldFrame(generateQueenImage(best_ind))

                self.chart = QChart()
                #self.chart.addSeries(q_min_series)
                #self.chart.addSeries(q_max_series)
                #q_avg_series.setName("Board: " + str(b) + " Population: " + str(p) + " Elite: " + str(e) + " Mutation:" + str(m*100) + "% " + "Generations:" + str(NGSEN))
                self.chart.addSeries(q_avg_series)
                self.chart.setTitle("QN: " + str(NO_QUEENS) + " POP: " +
                                    str(POP_SIZE) + " EL: " + str(NELT) +
                                    " MT: " + str(MUTPB * 100) + "% ")
                self.chart.setAnimationOptions(QChart.NoAnimation)
                self.chart.createDefaultAxes()
                self.frameChart.setChart(self.chart)

        #Printing best individual
        best_ind = tools.selBest(self.pop, 1)[0]
        #print("Best individual is %s, %s \n" % (best_ind, best_ind.fitness.values))

        #Visulaize final solution
        if self.cbxNoVis.isChecked():
            #Draw queen positions of best individual on a image
            best_ind = tools.selBest(self.pop, 1)[0]
            self.updateWorldFrame(generateQueenImage(best_ind))

            self.chart = QChart()
            #self.chart.addSeries(q_min_series)
            #self.chart.addSeries(q_max_series)
            self.chart.addSeries(q_avg_series)
            self.chart.setTitle("QN: " + str(NO_QUEENS) + " POP: " +
                                str(POP_SIZE) + " EL: " + str(NELT) + " MT: " +
                                str(MUTPB * 100) + "% ")
            self.chart.setAnimationOptions(QChart.NoAnimation)
            self.chart.createDefaultAxes()
            self.frameChart.setChart(self.chart)

        #Disable stop and enable start
        self.btnStop.setEnabled(False)
        self.btnStart.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.tbxNoQueens.setEnabled(True)
        self.cbxNoVis.setEnabled(True)

    def updateWorldFrame(self, queens_img):
        #new_image = QPixmap(1000,1000)
        self.new_image.fill()  #White color is default
        painter = QPainter(self.new_image)
        #First draw the table
        painter.drawPixmap(self.new_image.rect(), self.img)
        #Then draw the queens
        painter.drawImage(self.new_image.rect(), queens_img)
        painter.end()
        #Set new image to the frame
        self.frameWorld.img = self.new_image
        #Redrawing frames
        self.frameWorld.repaint()
        self.frameChart.repaint()
        app.processEvents()

    def btnSaveWorld_Click(self):
        filename, _ = QFileDialog.getSaveFileName(None,
                                                  "Save world as a image", "",
                                                  "Image Files (*.png)")
        self.frameWorld.img.save(filename, "PNG")
        print("World image saved to: ", filename)

    def btnSaveChart_CLick(self):
        p = self.frameChart.grab()
        filename, _ = QFileDialog.getSaveFileName(
            None, "Save series chart as a image", "", "Image Files (*.png)")
        p.save(filename, "PNG")
        print("Chart series image saved to: ", filename)

    def btnSaveChartSeries_Click(self):
        global q_min_series
        global q_max_series
        global q_avg_series
        filename, _ = QFileDialog.getSaveFileName(None,
                                                  "Save series to text file",
                                                  "",
                                                  "Text Files (*.txt, *.csv)")
        with open(filename, 'w') as dat:
            for i in range(q_min_series.count()):
                dat.write('%f,%f,%f\n' %
                          (q_min_series.at(i).y(), q_avg_series.at(i).y(),
                           q_max_series.at(i).y()))
        print("Chart series saved to: ", filename)
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.pixelRow = QLabel()
        self.pixelRow.setFixedSize(20, nbPixels)

        self.matrixDisplay = QTextEdit()
        self.matrixDisplay.setFixedSize(165, 180)

        self.valuesDisplay = QTextEdit()
        self.valuesDisplay.setFixedSize(50, nbPixels)

        # CHART
        self.serie = QLineSeries()

        self.chart = QChart()
        self.chart.addSeries(self.serie)
        self.chart.legend().hide()
        self.chart.layout().setContentsMargins(0, 0, 0, 0)

        self.xAxis = QValueAxis()
        self.xAxis.setTitleText("Height")
        self.xAxis.setLabelFormat("%d")
        self.xAxis.setRange(0, nbPixels)

        self.yAxis = QValueAxis()
        self.yAxis.setLabelFormat("%d")
        self.yAxis.setTitleText("Distance ")
        self.yAxis.setRange(0, couleurMax)

        self.chart.setAxisX(self.xAxis)
        self.chart.setAxisY(self.yAxis)

        self.serie.attachAxis(self.xAxis)
        self.serie.attachAxis(self.yAxis)

        self.chart.setTitle("Profile line")

        self.chartView = QChartView(self)
        self.chartView.setChart(self.chart)
        self.chartView.rotate(90)
        self.chartView.setGeometry(20, 195, 450, 400)
        #end CHART

        self.timer = QTimer(self)
        self.timer.setInterval(periode)
        self.timer.start
        self.timer.timeout.connect(self.refresh)

        self.startButton = QPushButton("START")
        self.startButton.setDefault(True)
        self.startButton.clicked.connect(self.startTimer)
        self.startButton.setFixedSize(100, 50)

        self.stopButton = QPushButton("STOP")
        self.stopButton.setDefault(True)
        self.stopButton.clicked.connect(self.stopTimer)
        self.stopButton.setFixedSize(100, 50)

        topLayout = QGridLayout()
        topLayout.addWidget(self.startButton, 0, 0)
        topLayout.addWidget(self.stopButton, 1, 0)
        topLayout.addWidget(self.matrixDisplay, 0, 1, 2, 1)

        mainLayout = QGridLayout()
        mainLayout.addLayout(topLayout, 0, 0)
        mainLayout.addWidget(self.pixelRow, 0, 1, 2, 1)
        mainLayout.addWidget(self.valuesDisplay, 0, 2, 2, 1)
        mainLayout.addWidget(self.chartView, 1, 0)

        mainwidget = QWidget()
        mainwidget.setLayout(mainLayout)
        self.setCentralWidget(mainwidget)

        self.setWindowTitle("Minecraft Depth Map")

    def startTimer(self):
        self.timer.start()

    def stopTimer(self):
        self.timer.stop()

    def refresh(self):
        self.serie.clear()
        self.valuesDisplay.clear()
        screen = app.primaryScreen()
        #grabWindow(wID, x, y, w, h)
        pix = QPixmap(
            screen.grabWindow(0,
                              int((screenW * 3) / 4) - 10,
                              int((screenH - nbPixels) / 2), 20, nbPixels))
        self.pixelRow.setPixmap(pix)
        img = QImage(pix.toImage())

        array = [0 for i in range(nbBlocsH)]

        for i in range(nbBlocsH):
            y = nbPixels - (i * (nbPixels / nbBlocsH) + (nbPixels /
                                                         (2 * nbBlocsH)))
            colorvalue = 255 - QColor(img.pixel(10, y)).black()
            self.valuesDisplay.append(str(colorvalue))
            self.valuesDisplay.append("\n")
            self.serie.append(y, colorvalue)

            #convert colors from 0->couleurMax to 0->nbBlocsD
            if colorvalue > couleurMax:
                colorvalue = nbBlocsD
            elif colorvalue < couleurMin:
                colorvalue = 0
            else:
                colorvalue = int(colorvalue / (couleurMax / nbBlocsD))
            array[i] = colorvalue

        self.convertToMatrix(array)

    def convertToMatrix(self, array):

        matrix = [[0 for j in range(nbBlocsD)] for i in range(nbBlocsH)]

        for i in range(nbBlocsH):
            if array[i] < nbBlocsD:
                matrix[i][array[i]] = 1
                if i < (nbBlocsH - 1):
                    if array[i + 1] > (array[i] + 1):
                        for j in range(array[i] + 1,
                                       min(nbBlocsD, array[i + 1])):
                            matrix[i][j] = 1
                if i > 0:
                    if array[i - 1] > (array[i] + 1):
                        for j in range(array[i] + 1,
                                       min(nbBlocsD, array[i - 1])):
                            matrix[i][j] = 1

        #test1Scalable.convertToHexa(motifF,nbBlocsD,nbBlocsH)  # es-ce bien la fonction a utiliser pour l'affichage ?
        self.displayMatrix(matrix)

    def displayMatrix(self, matrix):
        self.matrixDisplay.clear()
        for j in range(nbBlocsD - 1, -1, -1):
            line = ""
            for i in range(nbBlocsH):
                line = line + str(matrix[i][j]) + "  "
                #self.matrixDisplay.append( line)
                #self.matrixDisplay.append( str(matrix[i][j]) + "  ")
                #self.matrixDisplay.moveCursor( QTextCursor.EndOfLine )
            self.matrixDisplay.append(line)
class Ui_MainWindow(QtWidgets.QMainWindow):
    def openDetails(self):

        self.window = QtWidgets.QDialog()
        self.ui = Ui_Detail()
        self.ui.setupUi(self.window)
        self.window.show()
        if self.inputUlasan.toPlainText() != '':
            self.ui.setDetail(self.tmp_res[0], self.tmp_res[1],
                              self.tmp_res[2], self.tmp_res[3],
                              self.tmp_res[4], self.tmp_res[5])
            return

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setObjectName("MainWindow")
        self.resize(1366, 768)
        self.setAutoFillBackground(False)

        self.ind = 0

        namaPantai = []
        npn = NamaPantai()
        namaPan = npn.nama_pantai()
        for i in range(len(namaPan)):
            namaPantai.append(namaPan[i])
        self.label_pantai = namaPantai

        self.label_pantai_sort = self.getLabelSort()[0]
        self.label_pantai_sort2 = self.getLabelSort()[1]
        self.label_pantai_sort3 = self.getLabelSort()[2]
        self.label_pantai_sort4 = self.getLabelSort()[3]
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 1366, 768))
        self.tabWidget.setObjectName("tabWidget")
        self.tab_Grafik = QtWidgets.QWidget()
        self.tab_Grafik.setObjectName("tab_Grafik")
        self.radioALL = QtWidgets.QRadioButton(self.tab_Grafik)
        self.radioALL.setGeometry(QtCore.QRect(850, 30, 100, 21))
        self.radioDT = QtWidgets.QRadioButton(self.tab_Grafik)
        self.radioDT.setGeometry(QtCore.QRect(950, 30, 100, 21))
        self.radioDT.setObjectName("radioDT")
        self.radioAK = QtWidgets.QRadioButton(self.tab_Grafik)
        self.radioAK.setGeometry(QtCore.QRect(1050, 30, 100, 21))
        self.radioAK.setObjectName("radioAK")
        self.radioKB = QtWidgets.QRadioButton(self.tab_Grafik)
        self.radioKB.setGeometry(QtCore.QRect(1150, 30, 100, 21))
        self.radioKB.setObjectName("radioKB")
        self.radioFS = QtWidgets.QRadioButton(self.tab_Grafik)
        self.radioFS.setGeometry(QtCore.QRect(1250, 30, 100, 21))
        self.radioFS.setObjectName("radioFS")

        self.step = 0.8
        self.verticalScrollBar = QtWidgets.QScrollBar(
            self.tab_Grafik,
            sliderMoved=self.onAxisSliderMoved,
            pageStep=self.step * 10)
        self.verticalScrollBar.setGeometry(QtCore.QRect(30, 620, 1300, 20))
        self.verticalScrollBar.setOrientation(QtCore.Qt.Horizontal)
        self.verticalScrollBar.setObjectName("verticalScrollBar")

        self.comboBox = QtWidgets.QComboBox(self.tab_Grafik)
        self.comboBox.setGeometry(QtCore.QRect(110, 30, 161, 21))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("=Pilih=")
        self.tmp_res = None

        for i in range(len(namaPan)):
            self.comboBox.addItem(namaPan[i])
        self.label_6 = QtWidgets.QLabel(self.tab_Grafik)
        self.label_6.setGeometry(QtCore.QRect(40, 30, 81, 16))
        self.label_6.setObjectName("label_6")
        self.graphicsView = QChartView(self.tab_Grafik)
        self.graphicsView.setGeometry(QtCore.QRect(30, 70, 1300, 520))
        self.graphicsView.setObjectName("graphicsView")
        self.tabWidget.addTab(self.tab_Grafik, "")

        self.tab_Klasifikasi = QtWidgets.QWidget()
        self.tab_Klasifikasi.setObjectName("tab_Klasifikasi")
        self.label = QtWidgets.QLabel(self.tab_Klasifikasi)
        self.label.setGeometry(QtCore.QRect(450, 70, 381, 31))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.tab_Klasifikasi)
        self.label_2.setGeometry(QtCore.QRect(170, 150, 131, 16))
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.tab_Klasifikasi)
        self.label_3.setGeometry(QtCore.QRect(170, 370, 200, 16))
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.tab_Klasifikasi)
        self.label_4.setGeometry(QtCore.QRect(850, 150, 71, 16))
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(self.tab_Klasifikasi)
        self.label_5.setGeometry(QtCore.QRect(850, 370, 71, 21))
        self.label_5.setObjectName("label_5")
        self.inputUlasan = QtWidgets.QPlainTextEdit(self.tab_Klasifikasi)
        self.inputUlasan.setGeometry(QtCore.QRect(170, 200, 500, 121))
        self.inputUlasan.setFont(QFont('Times', 15))
        self.inputUlasan.setObjectName("inputUlasan")
        self.hasilPreprocessing = QtWidgets.QPlainTextEdit(
            self.tab_Klasifikasi)
        self.hasilPreprocessing.setGeometry(QtCore.QRect(170, 420, 500, 121))
        self.hasilPreprocessing.setFont(QFont('Times', 15))
        self.hasilPreprocessing.setObjectName("hasilPreprocessing")
        self.hasilSentimen = QtWidgets.QPlainTextEdit(self.tab_Klasifikasi)
        self.hasilSentimen.setGeometry(QtCore.QRect(850, 200, 300, 121))
        self.hasilSentimen.setObjectName("hasilSentimen")
        self.hasilSentimen.setFont(QFont('Times', 15))
        self.hasilKategori = QtWidgets.QPlainTextEdit(self.tab_Klasifikasi)
        self.hasilKategori.setGeometry(QtCore.QRect(850, 420, 300, 121))
        self.hasilKategori.setObjectName("hasilKategori")
        self.hasilKategori.setFont(QFont('Times', 15))
        self.buttonPrediksi = QtWidgets.QPushButton(self.tab_Klasifikasi)
        self.buttonPrediksi.setGeometry(QtCore.QRect(170, 570, 111, 30))
        self.buttonPrediksi.setObjectName("buttonPrediksi")
        self.buttonDetail = QtWidgets.QPushButton(self.tab_Klasifikasi)
        self.buttonDetail.setGeometry(QtCore.QRect(350, 570, 111, 30))
        self.buttonDetail.setObjectName("buttonDetail")
        self.buttonClear = QtWidgets.QPushButton(self.tab_Klasifikasi)
        self.buttonClear.setGeometry(QtCore.QRect(1039, 570, 111, 30))
        self.buttonClear.setObjectName("buttonClear")
        self.tabWidget.addTab(self.tab_Klasifikasi, "")
        self.tab_Pengujian = QtWidgets.QWidget()
        self.tab_Pengujian.setObjectName("tab_Pengujian")
        self.graphicsView_sentimen = QChartView(self.tab_Pengujian)
        self.graphicsView_sentimen.setGeometry(QtCore.QRect(50, 100, 600, 560))
        self.graphicsView_sentimen.setObjectName("graphicsView")
        self.graphicsView_kategori = QChartView(self.tab_Pengujian)
        self.graphicsView_kategori.setGeometry(QtCore.QRect(
            700, 100, 600, 560))
        self.graphicsView_kategori.setObjectName("graphicsView")
        self.label_ujisentimen = QtWidgets.QLabel(self.tab_Pengujian)
        self.label_ujisentimen.setGeometry(QtCore.QRect(200, 50, 300, 31))
        self.label_ujisentimen.setObjectName("label_ujisentimen")
        self.label_ujiKategori = QtWidgets.QLabel(self.tab_Pengujian)
        self.label_ujiKategori.setGeometry(QtCore.QRect(850, 50, 300, 31))
        self.label_ujiKategori.setObjectName("label_ujiKategori")
        self.tabWidget.addTab(self.tab_Pengujian, "")
        self.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)
        self.retranslateUi(self)
        QtCore.QMetaObject.connectSlotsByName(self)

        self.comboBox.activated.connect(self.selectionChange)
        self.ALL()
        self.buttonPrediksi.clicked.connect(self.on_click)
        self.buttonClear.clicked.connect(self.delete)
        self.buttonDetail.clicked.connect(self.openDetails)
        self.graphicsView_sentimen.setChart(self.grafik_uji_sentimen())
        self.graphicsView_kategori.setChart(self.grafik_uji_kategori())
        self.radioALL.setChecked(True)
        self.radioALL.toggled.connect(self.ALL)
        self.radioDT.toggled.connect(self.DT)
        self.radioAK.toggled.connect(self.AK)
        self.radioKB.toggled.connect(self.KB)
        self.radioFS.toggled.connect(self.FS)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow",
                                             "Analisis Sentimen"))
        self.buttonPrediksi.setText(_translate("MainWindow", "Prediksi"))
        self.buttonDetail.setText(_translate("MainWindow", "Detail"))
        self.buttonClear.setText(_translate("MainWindow", "Hapus"))
        self.radioALL.setText(_translate("MainWindow", "Kategori"))
        self.radioDT.setText(_translate("MainWindow", "Daya Tarik"))
        self.radioAK.setText(_translate("MainWindow", "Aksesbilitas"))
        self.radioKB.setText(_translate("MainWindow", "Kebersihan"))
        self.radioFS.setText(_translate("MainWindow", "Fasilitas"))
        self.label.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:14pt; font-weight:600;\">KLASIFIKASI ULASAN GOOGLE MAPS</span></p></body></html>"
            ))
        self.label_2.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:10pt; font-weight:600;\">Masukkan Ulasan :</span></p></body></html>"
            ))
        self.label_3.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-size:10pt; font-weight:600;\">Hasil Preprocessing :</span></p></body></html>"
            ))
        self.label_4.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:10pt; font-weight:600;\">Sentimen :</span></p></body></html>"
            ))
        self.label_5.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:10pt; font-weight:600;\">Kategori :</span></p></body></html>"
            ))
        self.label_ujisentimen.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:12pt; font-weight:600;\">Grafik Pengujian Sentimen</span></p></body></html>"
            ))
        self.label_ujiKategori.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><span style=\" font-size:12pt; font-weight:600;\">Grafik Pengujian Kategori</span></p></body></html>"
            ))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_Klasifikasi),
                                  _translate("MainWindow", "Klasifikasi"))
        self.comboBox.setItemText(0, _translate("MainWindow", "-Pilih-"))
        np = NamaPantai()
        hasil = np.nama_pantai()
        for i in range(len(hasil)):
            self.comboBox.setItemText(i + 1,
                                      _translate("MainWindow", hasil[i]))
        self.label_6.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-size:9pt;\">Pilih Pantai :</span></p></body></html>"
            ))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_Grafik),
                                  _translate("MainWindow", "Grafik"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_Pengujian),
                                  _translate("MainWindow", "Pengujian"))

    def selectionChange(self):
        pilih_pantai = str(self.comboBox.currentText())
        if pilih_pantai == '-Pilih-':
            self.ALL()
            return
        gf = Grafik(pilih_pantai)
        hasil = gf.hasil_grafik()
        hasil_dayatarik = hasil[0]
        hasil_aksesbilitas = hasil[1]
        hasil_kebersihan = hasil[2]
        hasil_fasilitas = hasil[3]
        total_pantai = hasil[4]
        daya_tarik = (hasil_dayatarik / total_pantai) * 100
        aksesbilitas = (hasil_aksesbilitas / total_pantai) * 100
        kebersihan = (hasil_kebersihan / total_pantai) * 100
        fasilitas = (hasil_fasilitas / total_pantai) * 100
        nilai = {
            'Daya Tarik': daya_tarik,
            'Aksesbilitas': aksesbilitas,
            'Kebersihan': kebersihan,
            'Fasilitas': fasilitas
        }
        maks = max(nilai['Daya Tarik'], nilai['Aksesbilitas'],
                   nilai['Kebersihan'], nilai['Fasilitas'])
        for i in nilai:
            if maks == nilai[i]:
                print(i)
        set0 = QBarSet(pilih_pantai)
        set0 << daya_tarik << aksesbilitas << kebersihan << fasilitas
        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        chart = QChart()
        chart.addSeries(series)
        chart.setTitle('Pantai ' + str(pilih_pantai))

        labelnya = ["Daya Tarik", "Aksesbilitas", "Kebersihan", "Fasilitas"]

        series = QPieSeries()
        series.append("dt", daya_tarik)
        series.append("ak", aksesbilitas)
        series.append("keb", kebersihan)
        series.append("fas", fasilitas)

        slice = QPieSlice()
        slice = series.slices()[0]
        slice.setExploded(False)
        slice.setLabelVisible(True)
        slice.setBrush(QtGui.QColor("blue"))

        slice = QPieSlice()
        slice = series.slices()[1]
        slice.setExploded(False)
        slice.setLabelVisible(True)
        slice.setBrush(QtGui.QColor("red"))

        slice = QPieSlice()
        slice = series.slices()[2]
        slice.setExploded(False)
        slice.setLabelVisible(True)
        slice.setBrush(QtGui.QColor("green"))

        slice = QPieSlice()
        slice = series.slices()[3]
        slice.setExploded(False)
        slice.setLabelVisible(True)
        slice.setBrush(QtGui.QColor("orange"))
        i = 0
        for slice in series.slices():
            slice.setLabel(labelnya[i] +
                           "  {:.1f}%".format(100 * slice.percentage()))
            i = i + 1

        chart = QChart()
        chart.legend().hide()
        chart.addSeries(series)
        chart.createDefaultAxes()
        chart.setAnimationOptions(QChart.SeriesAnimations)
        self.graphicsView.setChart(chart)

    def ALL(self):
        self.ind = 0
        set0 = QBarSet('Daya Tarik')
        set1 = QBarSet('Aksesbilitas')
        set2 = QBarSet('Kebersihan')
        set3 = QBarSet('Fasilitas')

        set0.setColor(QtGui.QColor("blue"))
        set1.setColor(QtGui.QColor("red"))
        set2.setColor(QtGui.QColor("green"))
        set3.setColor(QtGui.QColor("orange"))
        gf = Grafik_2()

        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        hasil = gf.hasil_dayatarik()
        for i in range(len(hasil)):
            set0.append((hasil[i] / jml_pantai[i]) * 100)

        hasil2 = gf.hasil_aksesbilitas()
        for i in range(len(hasil2)):
            set1.append((hasil2[i] / jml_pantai[i]) * 100)

        hasil3 = gf.hasil_kebersihan()
        for i in range(len(hasil3)):
            set2.append((hasil3[i] / jml_pantai[i]) * 100)

        hasil4 = gf.hasil_fasilitas()
        for i in range(len(hasil4)):
            set3.append((hasil4[i] / jml_pantai[i]) * 100)

        series = QBarSeries()
        series.append(set0)
        series.append(set1)
        series.append(set2)
        series.append(set3)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)
        series.setLabelsAngle(-90)

        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        axisY.applyNiceNumbers()
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.adjust_axes(0, 2)
        self.lims = np.array([0, 6])
        self.onAxisSliderMoved(self.verticalScrollBar.value())

    def getLabelSort(self):
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        value2 = []
        value3 = []
        value4 = []
        hasil = gf.hasil_dayatarik()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)
        index = np.argsort(value)[::-1]
        label_sorting = []
        for i in index:
            label_sorting.append(self.label_pantai[i])

        hasil2 = gf.hasil_aksesbilitas()
        for i in range(len(hasil2)):
            value2.append((hasil2[i] / jml_pantai[i]) * 100)
        sorting2 = sorted(value2, reverse=True)
        index2 = np.argsort(value2)[::-1]
        label_sorting2 = []
        for i in index2:
            label_sorting2.append(self.label_pantai[i])

        hasil3 = gf.hasil_kebersihan()
        for i in range(len(hasil3)):
            value3.append((hasil3[i] / jml_pantai[i]) * 100)
        sorting3 = sorted(value3, reverse=True)
        index3 = np.argsort(value3)[::-1]
        label_sorting3 = []
        for i in index3:
            label_sorting3.append(self.label_pantai[i])

        hasil4 = gf.hasil_fasilitas()
        for i in range(len(hasil4)):
            value4.append((hasil4[i] / jml_pantai[i]) * 100)
        sorting4 = sorted(value4, reverse=True)
        index4 = np.argsort(value4)[::-1]
        label_sorting4 = []
        for i in index4:
            label_sorting4.append(self.label_pantai[i])
        return (label_sorting, label_sorting2, label_sorting3, label_sorting4)

    def adjust_axes(self, value_min, value_max):
        if value_max > 35:
            return
        self.chart.createDefaultAxes()
        self.chart.axisX().setRange(str(value_min), str(value_max))
        if self.ind == 0:
            for i in range(
                    value_min, value_max +
                    1 if value_max < 36 else len(self.label_pantai)):
                self.chart.axisX().replace(
                    str(i), self.label_pantai[i - 1 if i > 0 else i])
        if self.ind == 1:
            for i in range(
                    value_min, value_max +
                    1 if value_max < 36 else len(self.label_pantai_sort)):
                self.chart.axisX().replace(
                    str(i), self.label_pantai_sort[i - 1 if i > 0 else i])
        if self.ind == 2:
            for i in range(
                    value_min, value_max +
                    1 if value_max < 36 else len(self.label_pantai_sort2)):
                self.chart.axisX().replace(
                    str(i), self.label_pantai_sort2[i - 1 if i > 0 else i])
        if self.ind == 3:
            for i in range(
                    value_min, value_max +
                    1 if value_max < 36 else len(self.label_pantai_sort3)):
                self.chart.axisX().replace(
                    str(i), self.label_pantai_sort3[i - 1 if i > 0 else i])
        if self.ind == 4:
            for i in range(
                    value_min, value_max +
                    1 if value_max < 36 else len(self.label_pantai_sort4)):
                self.chart.axisX().replace(
                    str(i), self.label_pantai_sort4[i - 1 if i > 0 else i])

    @QtCore.pyqtSlot(int)
    def onAxisSliderMoved(self, value):
        r = value / ((1 + self.step) * 10)
        l1 = self.lims[0] + r * np.diff(self.lims)
        l2 = l1 + np.diff(self.lims) * self.step
        self.adjust_axes(math.floor(l1), math.ceil(l2))

    def DT(self):
        self.ind = 1
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        hasil = gf.hasil_dayatarik()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)
        index = np.argsort(value)[::-1]
        label_sorting = []
        for i in index:
            label_sorting.append(self.label_pantai[i])

        set0 = QBarSet('Daya Tarik')
        set0.setColor(QtGui.QColor("blue"))
        for i in range(len(hasil)):
            set0.append(sorting)

        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)
        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        axisX = QBarCategoryAxis()
        axisX.setLabelsAngle(-90)

        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        self.chart.addAxis(axisX, Qt.AlignBottom)
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        axisY.applyNiceNumbers()
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.lims = np.array([0, 10])
        self.onAxisSliderMoved(self.verticalScrollBar.value())

    def AK(self):
        self.ind = 2
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        hasil = gf.hasil_aksesbilitas()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)

        set0 = QBarSet('Aksesbilitas')
        set0.setColor(QtGui.QColor("red"))
        for i in range(len(hasil)):
            set0.append(sorting)
        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)

        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)

        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        axisY.applyNiceNumbers()
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.adjust_axes(0, 2)
        self.lims = np.array([0, 10])
        self.onAxisSliderMoved(self.verticalScrollBar.value())

    def KB(self):
        self.ind = 3
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        hasil = gf.hasil_kebersihan()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)

        set0 = QBarSet('Kebersihan')
        set0.setColor(QtGui.QColor("green"))
        for i in range(len(hasil)):
            set0.append(sorting)

        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)

        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)

        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        axisY.applyNiceNumbers()
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.adjust_axes(0, 2)
        self.lims = np.array([0, 10])
        self.onAxisSliderMoved(self.verticalScrollBar.value())

    def FS(self):
        self.ind = 4
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        hasil = gf.hasil_fasilitas()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)

        set0 = QBarSet('Fasilitas')
        set0.setColor(QtGui.QColor("orange"))
        for i in range(len(hasil)):
            set0.append(sorting)

        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)

        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)

        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        axisY.applyNiceNumbers()
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.adjust_axes(0, 2)
        self.lims = np.array([0, 10])
        self.onAxisSliderMoved(self.verticalScrollBar.value())

    def on_click(self):
        textboxValue = self.inputUlasan.toPlainText()
        cf = Classification(textboxValue)
        hasil = cf.klasifikasi()
        hasil_sentimen = hasil[0]
        hasil_kategori = hasil[1]
        token = hasil[2]
        predict_sentimen_positif = hasil[3]
        predict_sentimen_negatif = hasil[4]

        predict_DayaTarik = hasil[5]
        predict_Aksesbilitas = hasil[6]
        predict_Kebersihan = hasil[7]
        predict_Fasilitas = hasil[8]
        if self.inputUlasan.toPlainText() != '':
            self.inputUlasan.setPlainText(textboxValue)
            self.hasilPreprocessing.setPlainText(token)
            self.hasilSentimen.setPlainText(hasil_sentimen)
            self.hasilKategori.setPlainText(hasil_kategori)
            self.tmp_res = (predict_sentimen_positif, predict_sentimen_negatif,
                            predict_DayaTarik, predict_Aksesbilitas,
                            predict_Kebersihan, predict_Fasilitas)

        return self.tmp_res

    def delete(self):
        self.inputUlasan.setPlainText("")
        self.hasilPreprocessing.setPlainText("")
        self.hasilSentimen.setPlainText("")
        self.hasilKategori.setPlainText("")

    def grafik_uji_sentimen(self):
        with open(
                'C:/Users/asus/Desktop/SKRIPSWEET BISMILLAH/MODUL PROGRAM/Modul Program Bismillah/Pengujian/hasil_uji_sentimen_kfold.json'
        ) as f:
            dataa = json.load(f)
        print(dataa)
        acc = dataa['acc']
        pres = dataa['presisi']
        rec = dataa['recall']
        set0 = QBarSet('Akurasi')
        set1 = QBarSet('Presisi')
        set2 = QBarSet('Recall')

        for i in range(len(acc)):
            set0.append(acc[i] * 100)

        for i in range(len(pres)):
            set1.append(pres[i] * 100)

        for i in range(len(rec)):
            set2.append(rec[i] * 100)

        series = QBarSeries()
        series.append(set0)
        series.append(set1)
        series.append(set2)

        set0.setColor(QtGui.QColor("navy"))
        set1.setColor(QtGui.QColor("yellow"))
        set2.setColor(QtGui.QColor("red"))

        chart = QChart()
        chart.addSeries(series)
        chart.setAnimationOptions(QChart.SeriesAnimations)
        label_pantai = ['K=1', 'K=2', 'K=3', 'K=4', 'K=5']
        axisX = QBarCategoryAxis()
        axisX.append(label_pantai)
        axisX.setLabelsAngle(0)
        axisY = QValueAxis()
        axisX.setTitleText("K-Fold Cross Validation")
        axisY.setTitleText("Prosentase (%)")
        axisY.setRange(0, max(set0))
        axisY.setMinorTickCount(5)
        chart.addAxis(axisX, Qt.AlignBottom)
        chart.addAxis(axisY, Qt.AlignLeft)
        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)
        return (chart)

    def grafik_uji_kategori(self):
        with open(
                'C:/Users/asus/Desktop/SKRIPSWEET BISMILLAH/MODUL PROGRAM/Modul Program Bismillah/Pengujian/hasil_uji_kategori_kfold.json'
        ) as f:
            dataa = json.load(f)
        print(dataa)
        acc = dataa['acc']
        pres = dataa['presisi']
        rec = dataa['recall']
        set0 = QBarSet('Akurasi')
        set1 = QBarSet('Presisi')
        set2 = QBarSet('Recall')

        for i in range(len(acc)):
            set0.append(acc[i] * 100)

        for i in range(len(pres)):
            set1.append(pres[i] * 100)

        for i in range(len(rec)):
            set2.append(rec[i] * 100)

        series = QBarSeries()
        series.append(set0)
        series.append(set1)
        series.append(set2)
        set0.setColor(QtGui.QColor("navy"))
        set1.setColor(QtGui.QColor("yellow"))
        set2.setColor(QtGui.QColor("red"))

        chart = QChart()
        chart.addSeries(series)
        chart.setAnimationOptions(QChart.SeriesAnimations)
        label_pantai = ['K=1', 'K=2', 'K=3', 'K=4', 'K=5']
        axisX = QBarCategoryAxis()
        axisX.append(label_pantai)
        axisX.setLabelsAngle(0)
        axisY = QValueAxis()
        axisX.setTitleText("K-Fold Cross Validation")
        axisY.setTitleText("Prosentase (%)")
        axisY.setRange(0, max(set0))
        axisY.setMinorTickCount(5)

        chart.addAxis(axisX, Qt.AlignBottom)
        chart.addAxis(axisY, Qt.AlignLeft)
        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)
        return (chart)
            label.setFont(font)
            label.setMinimumSize(QtCore.QSize(16777215, 20))
        font = QtGui.QFont()
        font.setFamily("微软雅黑 Light")
        font.setPointSize(20)
        font.setBold(False)
        font.setWeight(50)
        labels = ('label', 'label_3', 'label_5', 'label_8')
        for label_name in labels:
            label = form.frame.findChild((QtWidgets.QLabel), label_name)
            label.setFont(font)
            label.setMinimumSize(QtCore.QSize(16777215, 20))


# def AddQtChartsIntoMainForm(form):
#     # 增加图表项目到主窗口
#     # main code here

#     # example code here

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mywin = MyMainForm()
    GetSystemDefinitionToChangeFontSizeAndLabelSize(mywin)
    mywin.show()
    charview = QChartView(mywin.create_bar_chart(), mywin.frame_2)
    charview.setGeometry(0, 0, mywin.frame_2.width(), mywin.frame_2.height())
    charview.show()
    print(str(mywin.frame_2.width()) + ":" + str(mywin.frame_2.height()))
    sys.exit(app.exec_())
class Example(QMainWindow):
    def __init__(self, ):
        super().__init__()
        self.bijiao = [0, 0, 0]

        self.res = ""
        self.queue = []
        self.k = -1
        self.flag = -1

        try:
            self.initUI()
            self.chart_init(10)
        except:
            traceback.print_exc()

    def initUI(self):

        icon = QtGui.QIcon()
        icon.addPixmap(
            QtGui.QPixmap("D:\\Sysytem\\Desktop\\zhong\\data\\ico.ico"),
            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.setWindowIcon(icon)

        self.resize(1000, 700)
        self.setWindowTitle('Icon')

        self.setObjectName("清华大学得不到的学生")
        self.setWindowTitle("一枚小乖乖~")
        self.label = QLabel(self)
        self.label.setWindowTitle("清华大学得不到的学生")
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)

        self.label.setGeometry(QtCore.QRect(15, 15, 970, self.height() - 30))
        self.label.setText("")
        palette = QtGui.QPalette()

        self.label.setStyleSheet("background-color: #fff;border-radius: 15px;")
        self.labelshadow = QGraphicsDropShadowEffect(self)
        self.labelshadow.setBlurRadius(15)
        self.labelshadow.setOffset(1, 1)
        self.label.setGraphicsEffect(self.labelshadow)

        self.label.setScaledContents(True)
        self.label.setObjectName("label")

        self.pushButton_12 = QtWidgets.QPushButton(self)
        self.pushButton_12.setGeometry(
            QtCore.QRect(self.width() - 55, 29, 20, 20))
        self.pushButton_12.setStyleSheet(
            "QPushButton{\n"
            "    background:#fc625d;\n"
            "    color:white;\n"
            "    box-shadow: 1px 1px 3px rgba(0,0,0,0.3);font-size:20px;border-radius: 10px;font-family: 微软雅黑;\n"
            "}\n"
            "QPushButton:hover{                    \n"
            "    background:#FF2D2D;\n"
            "}\n"
            "QPushButton:pressed{\n"
            "    border: 1px solid #3C3C3C!important;\n"
            "    background:#AE0000;\n"
            "}")
        self.pushButton_12.clicked.connect(self.close)

        self.pushButton_14 = QtWidgets.QPushButton(self)
        self.pushButton_14.setGeometry(
            QtCore.QRect(self.width() - 55 - 35, 29, 20, 20))
        self.pushButton_14.setStyleSheet(
            "QPushButton{\n"
            "    background:#35cd4b;\n"
            "    color:white;\n"
            "    box-shadow: 1px 1px 3px rgba(0,0,0,0.3);font-size:20px;border-radius: 10px;font-family: 微软雅黑;\n"
            "}\n"
            "QPushButton:hover{                    \n"
            "    background:#00CC00;\n"
            "}\n"
            "QPushButton:pressed{\n"
            "    border: 1px solid #3C3C3C!important;\n"
            "    background:#009900;\n"
            "}")
        self.pushButton_14.clicked.connect(self.showMinimized)

        self.color = ["#e89291", "#c4b98b", "#81a8e1", "#8cc9c4", "#83bde2"]
        # -----------------------------------------------------------------测试数量------------------------
        error = QtWidgets.QLineEdit(self)
        error.setGeometry(QtCore.QRect(70, 70, 150, 50))
        error.setStyleSheet(
            "text-align: center;background-color: " + self.color[0] +
            ";border-radius: 7px;border: 0px solid #000;color:#ffffff;font-size:20px;font-family: 微软雅黑;"
        )
        errorshadow = QGraphicsDropShadowEffect(self)
        error.setPlaceholderText("测试数量")
        errorshadow.setBlurRadius(30)
        cl = QColor("#cacaca")
        errorshadow.setColor(cl)
        error.setAlignment(Qt.AlignCenter)
        errorshadow.setOffset(0, 0)
        error.textChanged.connect(self.set_suliang)
        # error.setGraphicsEffect(errorshadow)

        # -----------------------------------------------------------------随机范围------------------------

        fan = QtWidgets.QLineEdit(self)
        fan.setGeometry(QtCore.QRect(240, 70, 150, 50))
        fan.setStyleSheet(
            "text-align: center;background-color: " + self.color[2] +
            ";border-radius: 7px;border: 0px solid #000;color:#ffffff;font-size:20px;font-family: 微软雅黑;"
        )
        fanshadow = QGraphicsDropShadowEffect(self)
        fanshadow.setBlurRadius(30)
        fancl = QColor("#cacaca")
        fan.setPlaceholderText("随机范围")
        fanshadow.setColor(fancl)
        fan.setAlignment(Qt.AlignCenter)
        fanshadow.setOffset(0, 0)
        fan.textChanged.connect(self.set_fanwei)
        # fan.setGraphicsEffect(fanshadow)

        # -----------------------------------------------------------------内存块数-----------------------

        kuai = QtWidgets.QLineEdit(self)
        kuai.setGeometry(QtCore.QRect(410, 70, 150, 50))
        kuai.setStyleSheet(
            "text-align: center;background-color: " + self.color[3] +
            ";border-radius: 7px;border: 0px solid #000;color:#ffffff;font-size:20px;font-family: 微软雅黑;"
        )
        kuaishadow = QGraphicsDropShadowEffect(self)
        kuaishadow.setBlurRadius(30)
        kuaicl = QColor("#cacaca")
        kuai.setPlaceholderText("内存块数")
        kuaishadow.setColor(kuaicl)
        kuai.setAlignment(Qt.AlignCenter)
        kuaishadow.setOffset(0, 0)
        kuai.textChanged.connect(self.set_kuai)
        # kuai.setGraphicsEffect(kuaishadow)

        self.Button = QtWidgets.QPushButton(self)
        self.Button.setGeometry(QtCore.QRect(580, 70, 150, 50))
        self.Button.setStyleSheet(
            "QPushButton{text-align: center;background-color: #83bde2;"
            "border-radius: 7px;border: 0px solid #000;color:#ffffff;"
            "font-size:20px;font-family: 微软雅黑;}" + "QPushButton:hover{ " +
            "    background-color: #9ad0d0;color: white;" + "}")
        Buttonshadow = QGraphicsDropShadowEffect(self)
        Buttonshadow.setBlurRadius(30)
        Buttoncl = QColor("#cacaca")
        self.Button.setText("执行")
        Buttonshadow.setColor(Buttoncl)
        Buttonshadow.setOffset(0, 0)
        # Button.setGraphicsEffect(Buttonshadow)
        self.Button.clicked.connect(self.on_click_start)

        self.avgflag = 0

        self.qq = QtWidgets.QPushButton(self)
        self.qq.setGeometry(QtCore.QRect(750, 70, 180, 50))
        self.qq.setStyleSheet(
            "color: #000;text-align: center;background-color: #f0f0f0;border-radius: 7px;border: 0px solid #000;font-size:14px;font-family: 微软雅黑;"
        )
        self.qq.clicked.connect(self.on_avg)

        self.show()

    def on_avg(self):
        if self.avgflag == 0:
            self.series.hide()

            self.serieslru.hide()

            self.seriesopt.hide()

            self.seriesfifoavg.show()

            self.serieslruavg.show()

            self.seriesoptavg.show()
            self.avgflag = 1
        else:

            self.series.show()

            self.serieslru.show()

            self.seriesopt.show()

            self.seriesfifoavg.hide()

            self.serieslruavg.hide()

            self.seriesoptavg.hide()
            self.avgflag = 0

    def set_kuai(self, text):
        self.kuai = text

    def set_fanwei(self, text):
        self.fan = text

    def set_suliang(self, text):
        self.su = text

    def hideerror(self):
        self.error.hide()

    def set_kuaishu(self, text):
        self.kuaishu = text

    def set_yemian(self, text):
        self.yemian = text

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = e.globalPos() - self.pos()
            e.accept()

    def mouseReleaseEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.m_drag = False

    def mouseMoveEvent(self, e):
        try:
            if Qt.LeftButton and self.m_drag:
                self.move(e.globalPos() - self.m_DragPosition)
                e.accept()
        except:
            print("错误代码:000x0")

    def on_click_start(self):
        try:
            self.jishu = 0
            self.thread = MyThread()
            self.thread.set_su(self.su)
            self.thread.set_kuai(self.kuai)
            self.thread.set_x(self.dtaxisX)
            self.thread.set_fan(self.fan)
            self.thread.det_bijiao(self.bijiao)
            self.dailist = []
            self.avg = []
            self.avg1 = []
            self.avg2 = []
            self.dailistlru = []
            self.dailistopt = []
            self.thread.sinOut.connect(self.change)
            self.thread.start()

            # self.qq.setText("FIFO:%0.2f   LRU:%0.2f \n OPT:%0.2f" % (self.bijiao[0], self.bijiao[1], self.bijiao[2]))

        except:
            traceback.print_exc()
        # self.sinOut.emit(self.dailist)
        # self.sinOut2.emit(self.dailistlru)
        # self.sinOut3.emit(self.dailistopt)

    def change(self, dailist):
        try:
            # print(dailist)
            # arr = str.split(dailist)
            # print(arr)

            flag = 0
            start = 0
            flag = dailist.find(" ", flag)
            flag = dailist.find(" ", flag + 1)
            end = flag
            arr = str.split(dailist[start:end])

            start = flag
            flag = dailist.find(" ", flag + 1)
            flag = dailist.find(" ", flag + 1)
            end = flag
            arr1 = str.split(dailist[start:end])

            start = flag
            flag = dailist.find(" ", flag + 1)
            flag = dailist.find(" ", flag + 1)
            end = flag
            arr2 = str.split(dailist[start:end])

            self.dailist.append(QPointF(float(arr[0]), float(arr[1])))

            self.dailistlru.append(QPointF(float(arr1[0]), float(arr1[1])))

            self.dailistopt.append(QPointF(float(arr2[0]), float(arr2[1])))
            #
            self.series.replace(self.dailist)
            self.serieslru.replace(self.dailistlru)
            self.seriesopt.replace(self.dailistopt)

            if self.jishu == 0:
                self.bijiao[0] = float(arr[1])
                self.bijiao[1] = float(arr1[1])
                self.bijiao[2] = float(arr2[1])
                self.jishu = 1
            else:
                self.bijiao[0] = (float(arr[1]) + self.bijiao[0]) / 2.0
                self.bijiao[1] = (float(arr1[1]) + self.bijiao[1]) / 2.0
                self.bijiao[2] = (float(arr2[1]) + self.bijiao[2]) / 2.0
                self.jishu = self.jishu + 1

            self.avg.append(QPointF(float(arr[0]), self.bijiao[0]))
            self.avg1.append(QPointF(float(arr[0]), self.bijiao[1]))
            self.avg2.append(QPointF(float(arr[0]), self.bijiao[2]))

            # print(self.avg)
            self.seriesfifoavg.replace(self.avg)
            self.serieslruavg.replace(self.avg1)
            self.seriesoptavg.replace(self.avg2)

            self.qq.setText("FIFO:%0.2f   LRU:%0.2f \n OPT:%0.2f" %
                            (self.bijiao[0], self.bijiao[1], self.bijiao[2]))
        except:
            traceback.print_exc()

    def drawLine(self):
        self.series.replace(self.dailist)
        # print("uiy")

    def chart_init(self, su):
        self.start_num = 0
        self.chart = QChartView(self)
        self.chart.setGeometry(50, 150,
                               self.width() - 100,
                               self.height() - 150 - 50)  # 设置charView位置、大小
        self.series = QSplineSeries()
        self.series.setName("FIFO")
        self.chart.chart().addSeries(self.series)

        pen = QPen(Qt.gray)
        pen.setWidth(2)
        self.serieslru = QSplineSeries()
        self.serieslru.setPen(pen)
        self.serieslru.setName("LRU")
        self.serieslru.setColor(QColor("#e89291"))
        self.chart.chart().addSeries(self.serieslru)

        pen2 = QPen(Qt.gray)
        pen2.setWidth(2)
        self.seriesopt = QSplineSeries()
        self.seriesopt.setPen(pen2)
        self.seriesopt.setColor(QColor("#3ea54f"))
        self.seriesopt.setName("OPT")
        self.chart.chart().addSeries(self.seriesopt)

        penfifo = QPen(Qt.gray)
        penfifo.setWidth(2)
        self.seriesfifoavg = QSplineSeries()
        self.seriesfifoavg.setPen(penfifo)
        self.seriesfifoavg.setName("FIFO-avg")
        self.seriesfifoavg.setColor(QColor("#209fdf"))
        self.chart.chart().addSeries(self.seriesfifoavg)
        self.seriesfifoavg.hide()

        penavg = QPen(Qt.gray)
        penavg.setWidth(2)
        self.serieslruavg = QSplineSeries()
        self.serieslruavg.setPen(penavg)
        self.serieslruavg.setName("LRU-avg")
        self.serieslruavg.setColor(QColor("#e89291"))
        self.chart.chart().addSeries(self.serieslruavg)
        self.serieslruavg.hide()

        pen2avg = QPen(Qt.gray)
        pen2avg.setWidth(2)
        self.seriesoptavg = QSplineSeries()
        self.seriesoptavg.setPen(pen2avg)
        self.seriesoptavg.setColor(QColor("#3ea54f"))
        self.seriesoptavg.setName("OPT-avg")
        self.chart.chart().addSeries(self.seriesoptavg)
        self.seriesoptavg.hide()

        self.dtaxisX = QValueAxis()
        self.vlaxisY = QValueAxis()
        self.dtaxisX.setMin(10)
        self.dtaxisX.setMax(100)
        self.vlaxisY.setMin(0)
        self.vlaxisY.setMax(100)
        self.dtaxisX.setTickCount(6)
        self.vlaxisY.setTickCount(11)
        self.dtaxisX.setTitleText("页数")
        self.vlaxisY.setTitleText("缺页率")
        self.vlaxisY.setGridLineVisible(False)
        self.chart.chart().addAxis(self.dtaxisX, Qt.AlignBottom)
        self.chart.chart().addAxis(self.vlaxisY, Qt.AlignLeft)
        self.series.attachAxis(self.dtaxisX)
        self.series.attachAxis(self.vlaxisY)

        self.serieslru.attachAxis(self.dtaxisX)
        self.serieslru.attachAxis(self.vlaxisY)

        self.seriesopt.attachAxis(self.dtaxisX)
        self.seriesopt.attachAxis(self.vlaxisY)

        self.seriesoptavg.attachAxis(self.dtaxisX)
        self.seriesoptavg.attachAxis(self.vlaxisY)
        self.serieslruavg.attachAxis(self.dtaxisX)
        self.serieslruavg.attachAxis(self.vlaxisY)
        self.seriesfifoavg.attachAxis(self.dtaxisX)
        self.seriesfifoavg.attachAxis(self.vlaxisY)

        self.chart.chart().setTitleBrush(QBrush(Qt.cyan))
        cc = QColor("#f0f0f0")
        self.chart.setBackgroundBrush(cc)
        self.chart.setStyleSheet(
            "QChartView{ background-color: #83bde2;border-radius: 20px;}")
        self.chart.show()
Exemple #13
0
class Ui_MainWindow(QtWidgets.QMainWindow):
    def setupUi(self):
        self.setObjectName("MainWindow")
        self.resize(850, 1080)
        self.setWindowTitle("GA - Queens")
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.frameWorld = MyQFrame(self.centralwidget)
        self.frameWorld.img = QPixmap(1000, 1000)
        self.frameWorld.setGeometry(QtCore.QRect(10, 10, 620, 600))
        self.frameWorld.setFrameShape(QtWidgets.QFrame.Box)
        self.frameWorld.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.frameWorld.setObjectName("frameWorld")
        self.frameChart = QChartView(self.centralwidget)
        self.frameChart.setGeometry(QtCore.QRect(10, 620, 620, 400))
        self.frameChart.setFrameShape(QtWidgets.QFrame.Box)
        self.frameChart.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.frameChart.setRenderHint(QPainter.Antialiasing)
        self.frameChart.setObjectName("frameChart")
        self.gaParams = QtWidgets.QGroupBox(self.centralwidget)
        self.gaParams.setGeometry(QtCore.QRect(650, 10, 161, 145))
        self.gaParams.setObjectName("gaParams")
        self.gaParams.setTitle("GA parameters")
        self.label1 = QtWidgets.QLabel(self.gaParams)
        self.label1.setGeometry(QtCore.QRect(10, 20, 61, 16))
        self.label1.setObjectName("label1")
        self.label1.setText("Population:")
        self.label2 = QtWidgets.QLabel(self.gaParams)
        self.label2.setGeometry(QtCore.QRect(10, 50, 47, 16))
        self.label2.setObjectName("label2")
        self.label2.setText("Mutation:")
        self.label3 = QtWidgets.QLabel(self.gaParams)
        self.label3.setGeometry(QtCore.QRect(10, 80, 81, 16))
        self.label3.setObjectName("label3")
        self.label3.setText("Elite members:")
        self.label4 = QtWidgets.QLabel(self.gaParams)
        self.label4.setGeometry(QtCore.QRect(10, 110, 91, 16))
        self.label4.setObjectName("label4")
        self.label4.setText("No. generations:")
        self.tbxPopulation = QtWidgets.QLineEdit(self.gaParams)
        self.tbxPopulation.setGeometry(QtCore.QRect(100, 20, 51, 20))
        self.tbxPopulation.setObjectName("tbxPopulation")
        self.tbxMutation = QtWidgets.QLineEdit(self.gaParams)
        self.tbxMutation.setGeometry(QtCore.QRect(100, 50, 51, 20))
        self.tbxMutation.setObjectName("tbxMutation")
        self.tbxElite = QtWidgets.QLineEdit(self.gaParams)
        self.tbxElite.setGeometry(QtCore.QRect(100, 80, 51, 20))
        self.tbxElite.setObjectName("tbxElite")
        self.tbxGenerations = QtWidgets.QLineEdit(self.gaParams)
        self.tbxGenerations.setGeometry(QtCore.QRect(100, 110, 51, 20))
        self.tbxGenerations.setObjectName("tbxGenerations")
        self.cbxNoVis = QtWidgets.QCheckBox(self.centralwidget)
        self.cbxNoVis.setGeometry(QtCore.QRect(650, 170, 170, 17))
        self.cbxNoVis.setObjectName("cbxNoVis")
        self.cbxNoVis.setText("No visualization per generation")
        self.cbxBorder = QtWidgets.QCheckBox(self.centralwidget)
        self.cbxBorder.setGeometry(QtCore.QRect(650, 200, 100, 17))
        self.cbxBorder.setObjectName("cbxBorder")
        self.cbxBorder.setText("Border patrol")
        self.btnStart = QtWidgets.QPushButton(self.centralwidget)
        self.btnStart.setGeometry(QtCore.QRect(650, 230, 75, 23))
        self.btnStart.setObjectName("btnStart")
        self.btnStart.setText("Start")
        self.btnStop = QtWidgets.QPushButton(self.centralwidget)
        self.btnStop.setEnabled(False)
        self.btnStop.setGeometry(QtCore.QRect(730, 230, 75, 23))
        self.btnStop.setObjectName("btnStop")
        self.btnStop.setText("Stop")
        self.btnSaveWorld = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveWorld.setGeometry(QtCore.QRect(650, 570, 121, 41))
        self.btnSaveWorld.setObjectName("btnSaveWorld")
        self.btnSaveWorld.setText("Save world as image")
        self.btnSaveChart = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveChart.setGeometry(QtCore.QRect(650, 930, 121, 41))
        self.btnSaveChart.setObjectName("btnSaveChart")
        self.btnSaveChart.setText("Save chart as image")
        self.btnSaveChartSeries = QtWidgets.QPushButton(self.centralwidget)
        self.btnSaveChartSeries.setGeometry(QtCore.QRect(650, 980, 121, 41))
        self.btnSaveChartSeries.setObjectName("btnSaveChartSeries")
        self.btnSaveChartSeries.setText("Save chart as series")
        self.setCentralWidget(self.centralwidget)
        QtCore.QMetaObject.connectSlotsByName(self)

        #Connect events
        self.btnStart.clicked.connect(self.btnStart_Click)
        self.btnStop.clicked.connect(self.btnStop_Click)
        self.btnSaveWorld.clicked.connect(self.btnSaveWorld_Click)
        self.btnSaveChart.clicked.connect(self.btnSaveChart_CLick)
        self.btnSaveChartSeries.clicked.connect(self.btnSaveChartSeries_Click)

        #Set default GA variables
        self.tbxGenerations.insert(str(NGEN))
        self.tbxPopulation.insert(str(POP_SIZE))
        self.tbxMutation.insert(str(MUTPB))
        self.tbxElite.insert(str(NELT))

        self.new_image = QPixmap(1000, 1000)

    def btnStart_Click(self):

        global combination_series  # List of lists containing min_series of 5 correct results -- Added by Denis Lazor
        global parameter_name  # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor
        global best_fit_values  # List containing best fitness values for every of 5 experiments per combination -- Added by Denis Lazor
        global best_individual  # Saving best individuals for drawing the best solution -- Added by Denis Lazor

        global ELITE_SIZES
        global POPULATION_SIZES
        global MUTATION_SIZES

        # Checking if files are empty or not -- Added by Denis Lazor
        csv_contains = os.stat("graphs_csv/original.csv").st_size != 0

        if csv_contains:
            clear_all_csv()

        n = 5000
        # Automation for all necessary combinations -- Added by Denis Lazor

        for p in POPULATION_SIZES:
            for m in MUTATION_SIZES:
                for e in ELITE_SIZES:
                    for i in range(5):

                        # Set global variables
                        global stop_evolution
                        global q_min_series
                        global q_max_series
                        global q_avg_series
                        stop_evolution = False
                        q_min_series.clear()
                        q_max_series.clear()
                        q_avg_series.clear()

                        # Set global variables from information on UI
                        global NGEN
                        global POP_SIZE
                        global MUTPB
                        global NELT
                        NGEN = n
                        POP_SIZE = p
                        MUTPB = m
                        NELT = e
                        global border_check
                        border_check = self.cbxBorder.isChecked()

                        # Loading Croatia map
                        self.img = QPixmap(620, 600)
                        self.img.load('Croatia620.png')
                        self.frameWorld.img = self.img
                        # Drawing towns
                        painter = QPainter(self.img)
                        painter.setPen(QPen(Qt.black, 10, Qt.SolidLine))
                        painter.setFont(QFont('Arial', 12))
                        for i in range(len(gradovi)):
                            x, y = GlobToImgCoords(sirine[i], duzine[i])
                            painter.drawPoint(x, y)
                            painter.drawText(x + 5, y + 5, gradovi[i])

                        painter.end()
                        # Redrawing frames
                        self.frameWorld.repaint()
                        app.processEvents()

                        ####Initialize deap GA objects####

                        # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize
                        creator.create("FitnessMin",
                                       base.Fitness,
                                       weights=(-1.0, ))

                        # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type
                        creator.create("Individual",
                                       list,
                                       fitness=creator.FitnessMin)

                        # Create base toolbox for finishing creation of a individual (cromosome)
                        self.toolbox = base.Toolbox()

                        # This is if we want a permutation coding of genes in the cromosome
                        self.toolbox.register("indices", random.sample,
                                              range(IND_SIZE), IND_SIZE)

                        # initIterate requires that the generator of genes (such as random.sample) generates an iterable (a list) variable
                        self.toolbox.register("individual", tools.initIterate,
                                              creator.Individual,
                                              self.toolbox.indices)

                        # Create a population of individuals (cromosomes). The population is then created by toolbox.population(n=300) where 'n' is the number of cromosomes in population
                        self.toolbox.register("population", tools.initRepeat,
                                              list, self.toolbox.individual)

                        # Register evaluation function
                        self.toolbox.register("evaluate", evaluateInd)

                        # Register what genetic operators to use
                        self.toolbox.register(
                            "mate", tools.cxUniformPartialyMatched, indpb=0.2
                        )  # Use uniform recombination for permutation coding

                        # Permutation coding
                        self.toolbox.register("mutate",
                                              tools.mutShuffleIndexes,
                                              indpb=0.2)

                        self.toolbox.register(
                            "select", tools.selTournament,
                            tournsize=3)  # Use tournament selection

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

                        # Generate initial poplation. Will be a member variable so we can easely pass everything to new thread
                        self.pop = self.toolbox.population(n=POP_SIZE)

                        # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs evaluate function for each individual in pop
                        fitnesses = list(map(self.toolbox.evaluate, self.pop))
                        for ind, fit in zip(self.pop, fitnesses):
                            ind.fitness.values = fit  # Assign calcualted fitness value to individuals

                        # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached
                        self.fits = [ind.fitness.values[0] for ind in self.pop]

                        # Disable start and enable stop
                        self.btnStart.setEnabled(False)
                        self.btnStop.setEnabled(True)
                        self.gaParams.setEnabled(False)
                        self.cbxBorder.setEnabled(False)
                        self.cbxNoVis.setEnabled(False)

                        # Start evolution
                        self.evolve()

                    # Best fitness value -- Added by Denis Lazor
                    best_fit = np.array(min(best_fit_values))[0]
                    mean_fit = min(
                        best_fit_values,
                        key=lambda x: abs(x - statistics.mean(
                            (np.asarray(best_fit_values)).flatten())))[0]

                    # Index of best fitness value -- Added by Denis Lazor
                    best_fit_idx = best_fit_values.index(best_fit)

                    write_to_file(combination_series[best_fit_idx],
                                  parameter_name)

                    # First name will be "original", second one "elites" -- Added by Denis Lazor
                    parameter_name = "elites"

                    print_results(p, m, e, best_fit, mean_fit, NGEN)

                    # Clearing past lists  -- Added by Denis Lazor
                    combination_series = []
                    best_fit_values = []

                # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor
                ELITE_SIZES = ELITE_SIZES[0:1]
                parameter_name = "mutation"

            MUTATION_SIZES = MUTATION_SIZES[0:1]
            parameter_name = "population"

        print("Best individual: " + str(best_individual))
        self.updateWorldFrame(generateWorldImage(
            best_individual))  # Drawing best solution -- Added by Denis Lazor

    def btnStop_Click(self):
        global stop_evolution
        stop_evolution = True
        #Disable stop and enable start
        self.btnStop.setEnabled(False)
        self.btnStart.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.cbxBorder.setEnabled(True)
        self.cbxNoVis.setEnabled(True)

    #Function for GA evolution
    def evolve(self):
        global q_min_series
        global q_max_series
        global q_avg_series

        global best_fit_values
        global combination_series
        global best_individual

        combination_current_series = [
        ]  # Clearing fitness values series -- Added by Denis Lazor

        # Variable for keeping track of the number of generations
        curr_g = 0

        # Begin the evolution till goal is reached or max number of generation is reached
        while min(self.fits) != 0 and curr_g < NGEN:
            #Check if evolution and thread need to stop
            if stop_evolution:
                break  #Break the evolution loop

            # A new generation
            curr_g = curr_g + 1
            #print("-- Generation %i --" % curr_g)

            # Select the next generation individuals
            #Select POP_SIZE - NELT number of individuals. Since recombination is between neigbours, not two naighbours should be the clone of the same individual
            offspring = []
            offspring.append(self.toolbox.select(
                self.pop, 1)[0])  #add first selected individual
            for i in range(
                    POP_SIZE - NELT - 1
            ):  # -1 because the first seleceted individual is already added
                while True:
                    new_o = self.toolbox.select(self.pop, 1)[0]
                    if new_o != offspring[len(
                            offspring
                    ) - 1]:  #if it is different than the last inserted then add to offspring and break
                        offspring.append(new_o)
                        break

            # Clone the selected individuals because all of the changes are inplace
            offspring = list(map(self.toolbox.clone, offspring))

            # Apply crossover on the selected offspring
            for child1, child2 in zip(offspring[::2], offspring[1::2]):
                self.toolbox.mate(child1, child2)  #inplace recombination
                #Invalidate new children fitness values
                del child1.fitness.values
                del child2.fitness.values

            #Apply mutation on the offspring
            for mutant in offspring:
                if random.random() < MUTPB:
                    self.toolbox.mutate(mutant)
                    del mutant.fitness.values

            #Add elite individuals #Is clonning needed?
            offspring.extend(
                list(map(self.toolbox.clone, tools.selBest(self.pop, NELT))))

            # Evaluate the individuals with an invalid fitness
            invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
            fitnesses = map(self.toolbox.evaluate, invalid_ind)
            for ind, fit in zip(invalid_ind, fitnesses):
                ind.fitness.values = fit

            #print("  Evaluated %i individuals" % len(invalid_ind))

            #Replace population with offspring
            self.pop[:] = offspring

            # Gather all the fitnesses in one list and print the stats
            self.fits = [ind.fitness.values[0] for ind in self.pop]

            length = len(self.pop)
            mean = sum(self.fits) / length
            sum2 = sum(x * x for x in self.fits)
            std = abs(sum2 / length - mean**2)**0.5

            q_min_series.append(curr_g, min(self.fits))
            q_max_series.append(curr_g, max(self.fits))
            q_avg_series.append(curr_g, mean)

            combination_current_series.append(
                min(self.fits)
            )  # Saving min_series fitness values of an experiment -- Added by Denis Lazor

            #print("  Min %s" % q_min_series.at(q_min_series.count()-1).y())
            #print("  Max %s" % q_max_series.at(q_max_series.count()-1).y())
            #print("  Avg %s" % mean)
            #print("  Std %s" % std)

            if self.cbxNoVis.isChecked():
                app.processEvents()
            else:
                self.chart = QChart()
                self.chart.addSeries(q_min_series)
                self.chart.addSeries(q_max_series)
                self.chart.addSeries(q_avg_series)
                self.chart.setTitle("Fitness value over time")
                self.chart.setAnimationOptions(QChart.NoAnimation)
                self.chart.createDefaultAxes()
                self.frameChart.setChart(self.chart)

                #Draw queen positions of best individual on a image
                best_ind = tools.selBest(self.pop, 1)[0]
                self.updateWorldFrame(generateWorldImage(best_ind))

        #Printing best individual
        best_ind = tools.selBest(self.pop, 1)[0]
        #print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))

        combination_series.append(
            combination_current_series
        )  # Saving best 5 results -- Added by Denis Lazor

        if not best_individual:
            best_individual = best_ind

        elif best_ind.fitness.values < best_individual.fitness.values:  # Saving best individual in all combinations -- Added by Denis Lazor
            best_individual = best_ind

        best_fit_values.append(
            best_ind.fitness.values
        )  # Adding best fitness value of experiment -- Added by Denis Lazor

        # #Visulaize final solution
        # if self.cbxNoVis.isChecked():
        #     self.chart = QChart()
        #     self.chart.addSeries(q_min_series)
        #     self.chart.addSeries(q_max_series)
        #     self.chart.addSeries(q_avg_series)
        #     self.chart.setTitle("Fitness value over time")
        #     self.chart.setAnimationOptions(QChart.NoAnimation)
        #     self.chart.createDefaultAxes()
        #     self.frameChart.setChart(self.chart)
        #
        #     #Draw queen positions of best individual on a image
        #     best_ind = tools.selBest(self.pop, 1)[0]
        #     self.updateWorldFrame(generateWorldImage(best_ind))

        #Disable stop and enable start
        self.btnStop.setEnabled(False)
        self.btnStart.setEnabled(True)
        self.gaParams.setEnabled(True)
        self.cbxBorder.setEnabled(True)
        self.cbxNoVis.setEnabled(True)

    def updateWorldFrame(self, best_individual_img):
        #new_image = QPixmap(1000,1000)
        self.new_image.fill()  #White color is default
        painter = QPainter(self.new_image)
        #First draw the map with towns
        painter.drawPixmap(self.new_image.rect(), self.img)
        #Then draw the best individual
        painter.drawImage(self.new_image.rect(), best_individual_img)
        painter.end()
        #Set new image to the frame
        self.frameWorld.img = self.new_image
        #Redrawing frames
        self.frameWorld.repaint()
        self.frameChart.repaint()
        app.processEvents()

    def btnSaveWorld_Click(self):
        filename, _ = QFileDialog.getSaveFileName(None,
                                                  "Save world as a image", "",
                                                  "Image Files (*.png)")
        self.frameWorld.img.save(filename, "PNG")
        print("World image saved to: ", filename)

    def btnSaveChart_CLick(self):
        p = self.frameChart.grab()
        filename, _ = QFileDialog.getSaveFileName(
            None, "Save series chart as a image", "", "Image Files (*.png)")
        p.save(filename, "PNG")
        print("Chart series image saved to: ", filename)

    def btnSaveChartSeries_Click(self):
        global q_min_series
        global q_max_series
        global q_avg_series
        filename, _ = QFileDialog.getSaveFileName(None,
                                                  "Save series to text file",
                                                  "",
                                                  "Text Files (*.txt, *.csv)")
        with open(filename, 'w') as dat:
            for i in range(q_min_series.count()):
                dat.write('%f,%f,%f\n' %
                          (q_min_series.at(i).y(), q_avg_series.at(i).y(),
                           q_max_series.at(i).y()))
        print("Chart series saved to: ", filename)