Exemple #1
0
    def createMenu(self):
        menu = QMenu()
        showClassifierErrors = menu.addAction(
            u"Visualize classifier errors")  #type:QAction
        showVisualizeTree = menu.addAction(u"Visualize tree")  #type:QAction

        selectedNames = [i.text() for i in self.m_History.selectedItems()]
        o = None  # type:List
        if selectedNames is not None and len(selectedNames) == 1:
            Utils.debugOut("history_name: ", selectedNames)
            o = self.m_History.getNamedObject(selectedNames[0])
        temp_vp = None  # type:VisualizePanel
        temp_grph = None  # type:str
        if o is not None:
            for i in range(len(o)):
                temp = o[i]
                if isinstance(temp, VisualizePanel):
                    temp_vp = temp
                elif isinstance(temp, str):
                    temp_grph = temp
        if temp_vp is not None:
            showClassifierErrors.setEnabled(True)
            showClassifierErrors.triggered.connect(
                self.classifierErrorTrigger(temp_vp))
        else:
            showClassifierErrors.setEnabled(False)

        if temp_grph is not None:
            showVisualizeTree.setEnabled(True)
            showVisualizeTree.triggered.connect(
                self.visualizeTreeTrigger(temp_grph))
        else:
            showVisualizeTree.setEnabled(False)
        menu.exec_(QCursor.pos())
Exemple #2
0
 def addUndoPoint(self):
     if self.m_Data is not None:
         temp = tempfile.TemporaryFile()
         pickle.dump(self.m_Data, temp)
         temp.seek(0)
         self.m_UndoList.append(temp)
         self.state_changed_signal.emit()
     Utils.debugOut("Now undo list len:", len(self.m_UndoList))
Exemple #3
0
 def insertInstanceEvent(self, inst: Instances, row: int):
     self.m_Pass = True
     self.m_Table.insertRow(row)
     self.m_Table.setItem(row, 0, QTableWidgetItem(str(row + 1)))
     self.m_Table.setRawItem(inst, row)
     self.adjustRowNo(row)
     Utils.debugOut("insert after current instance count:",
                    self.model.getInstance().numInstances())
     self.m_Pass = False
Exemple #4
0
    def useFilter(cls, data: Instances, filter: 'Filter'):
        for i in range(data.numInstances()):
            filter.input(data.instance(i))
        filter.batchFinished()
        newData = filter.getOutputFormat()
        Utils.debugOut("Queue size:", filter.m_OutputQueue.qsize())
        processed = filter.output()
        while processed is not None:
            newData.add(processed)
            processed = filter.output()

        return newData
Exemple #5
0
 def generateMenu(self, pos):
     self.m_Table.setMenuClickNow(True)
     Utils.debugOut("currentSelectedRow:", self.m_Table.getSelectedRow())
     self.setMenu()
     action = self.tableMenu.exec_(self.m_Table.cursor().pos())
     if action == self.searchMenuItem:
         self.search()
     elif action == self.clearSearchMenuItem:
         self.clearSearch()
     elif action == self.deleteSelectedInstanceMenuItem:
         self.deleteInstance()
     elif action == self.insertNewInstanceMenuItem:
         self.addInstance()
     elif action == self.deleteAllSelectedInstancesMenuItem:
         self.deleteInstances()
     else:
         return
     self.m_Table.setMenuClickNow(False)
Exemple #6
0
 def getClassesFromProperties(self) -> Dict[str, HierarchyPropertyParser]:
     hpps = dict()
     className = self.m_ClassType.__name__
     cls = PluginManager.getPluginNamesOfType(className)
     if cls is None:
         return hpps
     b = ""
     for s in cls:
         b += s + ","
     listS = b[0:-1]
     typeOptions = self.sortClassesByRoot(listS)
     Utils.debugOut("All Class:", typeOptions)
     if typeOptions is not None:
         enm = typeOptions.keys()
         for root in enm:
             typeOption = typeOptions.get(root)
             hpp = HierarchyPropertyParser()
             hpp.build(typeOption, ',')
             hpps.update({root: hpp})
     return hpps
Exemple #7
0
    def createMenu(self):
        menu = QMenu()
        showClusterAssign = menu.addAction(
            u"Visualize cluster assignments")  # type:QAction

        selectedNames = [i.text() for i in self.m_History.selectedItems()]
        o = None  # type:List
        if selectedNames is not None and len(selectedNames) == 1:
            Utils.debugOut("history_name: ", selectedNames)
            o = self.m_History.getNamedObject(selectedNames[0])
        temp_vp = None  # type:VisualizePanel
        if o is not None:
            for i in range(len(o)):
                temp = o[i]
                if isinstance(temp, VisualizePanel):
                    temp_vp = temp
        if temp_vp is not None:
            showClusterAssign.setEnabled(True)
            showClusterAssign.triggered.connect(
                self.visualizeClusterAssignTrigger(temp_vp))
        else:
            showClusterAssign.setEnabled(False)
        menu.exec_(QCursor.pos())
Exemple #8
0
 def generateHeaderMenu(self, pos):
     self.m_Table.setMenuClickNow(True)
     self.m_CurrentCol = self.m_Table.horizontalHeader().logicalIndexAt(pos)
     Utils.debugOut("header menu item index:",
                    self.m_Table.horizontalHeader().logicalIndexAt(pos))
     self.setMenu()
     action = self.headerMenu.exec_(self.m_Table.cursor().pos())
     if action == self.setAllValuesToMenuItem:
         self.setValues(self.setAllValuesToMenuItem)
     elif action == self.setMissingValuesToMenuItem:
         self.setValues(self.setMissingValuesToMenuItem)
     elif action == self.replaceValuesMenuItem:
         self.setValues(self.replaceValuesMenuItem)
     elif action == self.renameAttributeMenuItem:
         self.renameAttribute()
     elif action == self.deleteAttributeMenuItem:
         self.deleteAttribute()
     elif action == self.deleteAttributesMenuItem:
         self.deleteAttributes()
     elif action == self.optimalColumnWidthMenuItem:
         self.setOptimalColWidth()
     else:
         return
     self.m_Table.setMenuClickNow(False)
Exemple #9
0
 def deleteInstanceEvent(self, row: int):
     self.m_Pass = True
     if self.m_CurrentCombobox is not None and self.m_CurrentCombobox.row(
     ) == row:
         self.m_CurrentCombobox = None
     self.m_Table.removeRow(row)
     Utils.debugOut("delete position:", row)
     Utils.debugOut("delete after table rowCount:", self.m_Table.rowCount())
     self.adjustRowNo(row)
     Utils.debugOut("delete after current instance count:",
                    self.model.getInstance().numInstances())
     self.m_Pass = False
 def setXLimt(self, left, right, len):
     Utils.debugOut("Xlimit_left:", left)
     Utils.debugOut("Xlimit_right:", right)
     Utils.debugOut("Xlimit_len:", len)
     midX = len / 2
     mid = (left + right) / 2
     ticks = [-0.5, midX - 0.5, len - 0.5]
     self.mpl.axes.set_xticks(ticks)
     left = '%.2f' % left
     mid = '%.2f' % mid
     right = '%.2f' % right
     labelNumber = [left, mid, right]
     labels = [str(i) for i in labelNumber]
     self.mpl.axes.set_xticklabels(labels)
     self.mpl.draw()
Exemple #11
0
    def threadClassifierRun(self):
        try:
            self.m_CEPanel.addToHistory()
            inst = Instances(self.m_Instances)
            trainTimeStart = trainTimeElapsed = testTimeStart = testTimeElapsed = 0
            userTestStructure = None
            if self.m_SetTestFrame is not None:
                userTestStructure = deepcopy(
                    self.m_SetTestFrame.getInstances())  #type:Instances
                userTestStructure.setClassIndex(self.m_TestClassIndex)

            #默认outputmodel,output per-class stats,output confusion matrix,store predictions for visualization
            #outputPredictionsText=None
            numFolds = 10
            classIndex = self.m_ClassCombo.currentIndex()
            inst.setClassIndex(classIndex)
            classifier = self.m_ClassifierEditor.getValue()  #type:Classifier
            name = time.strftime("%H:%M:%S - ")
            outPutResult = ""
            evaluation = None  #type:Evaluation
            grph = None

            if self.m_CVBut.isChecked():
                testMode = 1
                numFolds = int(self.m_CVText.text())
                if numFolds <= 1:
                    raise Exception("Number of folds must be greater than 1")
            elif self.m_TrainBut.isChecked():
                testMode = 2
            elif self.m_TestSplitBut.isChecked():
                testMode = 3
                # if source is None:
                #     raise Exception("No user test set has been specified")
                if not inst.equalHeaders(userTestStructure):
                    QMessageBox.critical(self.m_Explorer, "错误", "测试数据集属性不同")
            else:
                raise Exception("Unknown test mode")
            cname = classifier.__module__
            if cname.startswith("classifiers."):
                name += cname[len("classifiers."):]
            else:
                name += cname
            cmd = classifier.__module__
            # if isinstance(classifier,OptionHandler):
            #     cmd+=" "+Utils.joinOptions(classifier.getOptions())
            plotInstances = ClassifierErrorsPlotInstances()
            plotInstances.setInstances(userTestStructure if testMode ==
                                       4 else inst)
            plotInstances.setClassifier(classifier)
            plotInstances.setClassIndex(inst.classIndex())
            plotInstances.setPointSizeProportionalToMargin(False)
            outPutResult += "=== Run information ===\n\n"
            outPutResult += "Scheme:       " + cname

            # if isinstance(classifier,OptionHandler):
            #     o=classifier.getOptions()
            #     outPutResult+=" "+Utils.joinOptions(o)
            outPutResult += "\n"
            outPutResult += "Relation:     " + inst.relationName() + '\n'
            outPutResult += "Instances:    " + str(inst.numInstances()) + '\n'
            outPutResult += "Attributes:   " + str(inst.numAttributes()) + '\n'
            if inst.numAttributes() < 100:
                for i in range(inst.numAttributes()):
                    outPutResult += "              " + inst.attribute(
                        i).name() + '\n'
            else:
                outPutResult += "              [list of attributes omitted]\n"
            outPutResult += "Test mode:    "
            if testMode == 1:
                outPutResult += str(numFolds) + "-fold cross-validation\n"
            elif testMode == 2:
                outPutResult += "evaluate on training data\n"
            elif testMode == 3:
                outPutResult += "user supplied test set: " + str(
                    userTestStructure.numInstances()) + " instances\n"
            outPutResult += "\n"
            self.m_History.addResult(name, outPutResult)
            self.m_History.setSingle(name)

            if testMode == 2 or testMode == 3:
                trainTimeStart = time.time()
                classifier.buildClassifier(inst)
                trainTimeElapsed = time.time() - trainTimeStart
            outPutResult += "=== Classifier model (full training set) ===\n\n"
            outPutResult += str(classifier) + "\n"
            outPutResult += "\nTime taken to build model: " + Utils.doubleToString(
                trainTimeElapsed, 2) + " seconds\n\n"
            self.m_History.updateResult(name, outPutResult)
            if isinstance(classifier, Drawable):
                grph = classifier.graph()

            print("==========update Compelte=================")

            if testMode == 2:
                evaluation = Evaluation(inst)
                evaluation = self.setupEval(evaluation, classifier, inst,
                                            plotInstances, False)
                evaluation.setMetricsToDisplay(self.m_selectedEvalMetrics)
                plotInstances.setUp()
                testTimeStart = time.time()
                #TODO
                # if isinstance(classifier,BatchPredictor)
                # else:
                for jj in range(inst.numInstances()):
                    plotInstances.process(inst.instance(jj), classifier,
                                          evaluation)
                testTimeElapsed = time.time() - testTimeStart
                outPutResult += "=== Evaluation on training set ===\n"
            elif testMode == 1:
                rnd = 1
                inst.randomize(rnd)
                if inst.attribute(classIndex).isNominal():
                    inst.stratify(numFolds)
                evaluation = Evaluation(inst)
                evaluation = self.setupEval(evaluation, classifier, inst,
                                            plotInstances, False)
                evaluation.setMetricsToDisplay(self.m_selectedEvalMetrics)
                plotInstances.setUp()
                for fold in range(numFolds):
                    train = inst.trainCV(numFolds, fold, rnd)
                    evaluation = self.setupEval(evaluation, classifier, train,
                                                plotInstances, True)
                    evaluation.setMetricsToDisplay(self.m_selectedEvalMetrics)
                    current = deepcopy(classifier)
                    current.buildClassifier(train)
                    test = inst.testCV(numFolds, fold)
                    # TODO
                    # if isinstance(classifier,BatchPredictor)
                    # else:
                    for jj in range(test.numInstances()):
                        plotInstances.process(test.instance(jj), current,
                                              evaluation)
                if inst.attribute(classIndex).isNominal():
                    outPutResult += "=== Stratified cross-validation ===\n"
                else:
                    outPutResult += "=== Cross-validation ===\n"
            elif testMode == 3:
                evaluation = Evaluation(inst)
                evaluation = self.setupEval(evaluation, classifier, inst,
                                            plotInstances, False)

                plotInstances.setInstances(userTestStructure)
                evaluation.setMetricsToDisplay(self.m_selectedEvalMetrics)
                plotInstances.setUp()
                # TODO
                # if isinstance(classifier,BatchPredictor)
                testTimeStart = time.time()
                for i in range(userTestStructure.numInstances()):
                    instance = userTestStructure.instance(i)
                    # if isinstance(classifier,BatchPredictor)
                    #else
                    plotInstances.process(instance, classifier, evaluation)
                # if isinstance(classifier,BatchPredictor)
                testTimeElapsed = time.time() - testTimeStart
                outPutResult += "=== Evaluation on test set ===\n"
            if testMode != 1:
                mode = ""
                if testMode == 2:
                    mode = "training data"
                elif testMode == 3:
                    mode = "supplied test set"
                outPutResult += "\nTime taken to test model on " + mode + ": " + Utils.doubleToString(
                    testTimeElapsed, 2) + " seconds\n\n"
            outPutResult += evaluation.toSummaryString(False) + '\n'
            self.m_History.updateResult(name, outPutResult)
            if inst.attribute(classIndex).isNominal():
                outPutResult += evaluation.toClassDetailsString() + '\n'
                outPutResult += evaluation.toMatrixString() + '\n'
            self.m_History.updateResult(name, outPutResult)
            Utils.debugOut(outPutResult)

            if (plotInstances is not None and plotInstances.canPlot(False)):
                visName = name + " (" + inst.relationName() + ")"
                pl2d = plotInstances.getPlotData(cname)
                plotInstances.cleanUp()
                vv = []
                trainHeader = Instances(self.m_Instances, 0)
                trainHeader.setClassIndex(classIndex)
                vv.append(trainHeader)
                if grph is not None:
                    vv.append(grph)
                if evaluation is not None and evaluation.predictions(
                ) is not None:
                    vv.append(evaluation.predictions())
                    vv.append(inst.classAttribute())
                self.history_add_visualize_signal.emit(name, vv, visName, pl2d)
        except Exception as e:
            self.error_diglog_signal.emit(str(e))
        self.mutex.lock()
        self.m_StartBut.setEnabled(True)
        self.m_StopBut.setEnabled(False)
        self.m_RunThread = None
        self.mutex.unlock()
        print("RunFinished")
Exemple #12
0
 def deleteAttributes(self, indexList: List):
     self.addUndoPoint()
     Utils.debugOut('will delete attributes index:', indexList)
     for i in indexList:
         self.m_Data.deleteAttributeAt(i - 1)
     self.delete_attribute_signal[list].emit(indexList)
Exemple #13
0
 def submitEvent(self, inst: Instance, index: int):
     self.addUndoPoint()
     self.m_Data.add(inst, index)
     Utils.debugOut("insertDataList:", inst.m_AttValues)
     self.insert_instance_signal.emit(self.m_Data, index)
Exemple #14
0
 def insertInstance(self, index: int):
     Utils.debugOut("insert instance position:", index)
     self.dialog = InserInstanceDialog()
     self.dialog.setAttributes(self.m_Data, index)
     self.dialog.submit_signal.connect(self.submitEvent)
     self.dialog.show()
    def paintRect(self,
                  dataSet: np.ndarray,
                  barWidth: int,
                  isNumeric: bool = False,
                  colorList: List[str] = ("black"),
                  labels: List[str] = None):
        self.showFrame(False)
        self.fig.subplots_adjust(top=0.99,
                                 bottom=0.1,
                                 left=0.01,
                                 right=0.99,
                                 hspace=0,
                                 wspace=0)
        x = np.arange(len(dataSet[0]))
        # 堆积柱状图
        #width=(max-min)/(x-1)
        Utils.debugOut("colorList:", colorList)
        Utils.debugOut("barWidth:", barWidth)
        sum = [0] * x
        height = [0] * x
        bottom = np.array([0.0] * len(x))
        width = 0.8
        maxHeight = 0
        a = None
        if isNumeric:
            width = 1
        for i in range(len(dataSet)):
            try:
                colorName = colorList[i]
                Utils.debugOut("Matplotlib_paintRect_width:", width)
                Utils.debugOut("Matplotlib_paintRect_colorName:", colorName)
                label = None
                #图例标签
                if labels is not None:
                    label = labels[i]
                a = self.axes.bar(x,
                                  dataSet[i],
                                  bottom=bottom,
                                  color=self.m_defaultColors.get(colorName),
                                  width=width,
                                  label=label)
                bottom += dataSet[i]
                for j in range(len(dataSet[i])):
                    sum[j] += dataSet[i][j]
                    maxHeight = max(maxHeight, sum[j])
                    height[j] += a[j].get_height()
            except IndexError:
                print("dataSet.len:", len(dataSet))
                print("colorList.len:", len(colorList))
                print("colorList:", colorList)

        for i in x:
            self.axes.text(a[i].get_x() + a[i].get_width() / 2,
                           height[i],
                           "%d" % int(sum[i]),
                           ha='center',
                           va='bottom')

        self.axes.set_xticks([])
        self.axes.set_yticks([])
        #图例绘制
        if labels is not None:
            self.axes.legend(loc='upper right')
        if maxHeight != 0:
            self.axes.set_ylim(0, maxHeight * 1.1)
        # 显示范围
        #l=min+width*x-(max-min)/2
        #r=max+width*x-(max-min)/2
        # self.axes.set_xlim(11, 69)
        # self.axes.set_ylim(15, 400)
        self.draw()
Exemple #16
0
    def testCV(self, numFolds: int, numFold: int) -> 'Instances':
        if numFolds < 2:
            raise Exception("Number of folds must be at least 2!")
        if numFolds > self.numInstances():
            raise Exception("Can't have more folds than instances!")
        numInstForFold = self.numInstances() // numFolds
        if numFold < self.numInstances() % numFolds:
            numInstForFold += 1
            offset = numFold
        else:
            offset = self.numInstances() % numFolds
        test = Instances(self, numInstForFold)
        first = numFold * (self.numInstances() // numFolds) + offset
        self.copyInstances(first, numInstForFold, test)
        return test

    def lastInstance(self) -> Instance:
        return self.m_Instances[-1]

    def attributeToDoubleArray(self, index: int):
        result = []
        for i in range(self.numInstances()):
            result.append(self.instance(i).value(index))
        return result

    def enumerateAttributes(self) -> List[Attribute]:
        return self.m_Attributes


Utils.debugOut("Instances id:", id(Instances))
    def setTarget(self, target: object):
        if self.layout() is None:
            layout = QFormLayout()
            self.setLayout(layout)
        else:
            layout = self.layout()
        while layout.rowCount() > 0:
            layout.removeRow(0)
        self.m_Labels.clear()
        self.m_Views.clear()
        self.setVisible(False)
        self.m_NumEditable = 0
        self.m_Target = target
        # 忽略类型,直接固定的接口,接口包括返回所有属性name的List和所有方法name的List
        self.m_Properties = target.getAllProperties()  #type:Dict
        self.m_Methods = target.getAllMethods()  #type:Dict

        def setValue(name: str, attrType: type):
            if attrType is bool:

                def callSet(option: str):
                    if option.lower() == "true":
                        setattr(target, name, True)
                    else:
                        setattr(target, name, False)
            else:

                def callSet(option):
                    if option != "":
                        if attrType is int:
                            setattr(target, name, int(option))
                        elif attrType is float:
                            setattr(target, name, float(option))

            return callSet

        for name, value in self.m_Properties.items():
            val = None
            try:
                property = getattr(target, name)
                if value != "":
                    try:
                        val = getattr(target, value)
                    except AttributeError:
                        pass
            except AttributeError:
                continue

            # print("name:", name, "type:", type(property))
            label = QLabel(name)
            # func = setValue(name,type(property))
            if isinstance(property, bool):
                view = QComboBox()
                view.addItems(['False', 'True'])
                if property:
                    view.setCurrentIndex(1)
                else:
                    view.setCurrentIndex(0)
                # view.currentIndexChanged[str].connect(copy.deepcopy(func))
            elif val is not None:
                items = []
                view = QComboBox()
                cur = i = 0
                for item in val:
                    if isinstance(item, Tag):
                        items.append(item.getReadable())
                        if property == item.getID():
                            cur = i
                        i += 1
                view.addItems(items)
                view.setCurrentIndex(cur)
            else:
                view = QLineEdit()
                view.setText(str(value))
                # view.textChanged.connect(copy.deepcopy(func))
            layout.addRow(label, view)
            self.m_Labels.append(label)
            self.m_Views.append(view)
        self.setFixedHeight(40 * len(self.m_Properties))
        Utils.debugOut("layout row count:", layout.rowCount())
        self.repaint()
        self.show()
Exemple #18
0
 def viewTableCloseEvent(self, inst: Instances):
     if self.m_Instances.classIndex() < 0:
         inst.setClassIndex(-1)
     Utils.debugOut("\n\nnewInstance numAttribute:", inst.numAttributes())
     self.setInstances(inst)
 def paint(self):
     self.m_Painter.clear()
     if self.m_as is not None:
         if not self.m_doneCurrentAttribute and not self.m_threadRun:
             self.calcGraph(self.m_Painter.width(), self.m_Painter.height())
         if not self.m_threadRun and self.m_displayCurrentAttribute:
             if self.m_as.nominalWeights is not None and (
                     self.m_histBarClassCounts is not None
                     or self.m_histBarCounts is not None):
                 if self.m_classIndex >= 0 and self.m_data.attribute(
                         self.m_classIndex).isNominal():
                     intervalWidth = self.m_Painter.width() / len(
                         self.m_histBarClassCounts)
                     if intervalWidth > 5:
                         barWidth = math.floor(intervalWidth * 0.8)
                     else:
                         barWidth = 1
                     #计算y轴最大值
                     dataList = None
                     labels = None
                     first = True
                     nullBarCount = []
                     if self.m_data.attribute(
                             self.m_classIndex).isNominal():
                         labels = [None]
                         for k in range(
                                 self.m_data.attribute(
                                     self.m_classIndex).numValues()):
                             labels.append(
                                 self.m_data.attribute(
                                     self.m_classIndex).value(k))
                     for i in range(len(self.m_histBarClassCounts)):
                         if self.m_histBarClassCounts[i] is not None:
                             if first:
                                 dataList = [[] for k in range(
                                     self.m_histBarClassCounts[i].
                                     numAttributes())]
                                 first = False
                             for j in range(self.m_histBarClassCounts[i].
                                            numAttributes()):
                                 dataList[j].append(
                                     self.m_histBarClassCounts[i].value(j))
                         else:
                             nullBarCount.append(i)
                     if dataList is None:
                         dataList = [[0] * len(nullBarCount)]
                     else:
                         for i in range(len(nullBarCount)):
                             for j in range(len(dataList)):
                                 dataList[j].insert(nullBarCount[i], 0)
                     dataList = np.array(dataList)
                     self.m_Painter.mpl.paintRect(
                         dataList,
                         barWidth,
                         colorList=self.m_colorList,
                         labels=labels)
                 else:
                     intervalWidth = self.m_Painter.width() / len(
                         self.m_histBarCounts)
                     if intervalWidth > 5:
                         barWidth = math.floor(intervalWidth * 0.8)
                     else:
                         barWidth = 1
                     dataList = np.array([self.m_histBarCounts])
                     self.m_Painter.mpl.paintRect(dataList, barWidth)
             elif self.m_as.numericStats is not None and (
                     self.m_histBarCounts is not None
                     or self.m_histBarClassCounts is not None):
                 if self.m_classIndex >= 0 and self.m_data.attribute(
                         self.m_classIndex).isNominal():
                     if (self.m_Painter.width() - 6) / len(
                             self.m_histBarClassCounts) < 1:
                         barWidth = 1
                     else:
                         barWidth = (self.m_Painter.width() - 6) / len(
                             self.m_histBarClassCounts)
                     dataList = None
                     newColor = []
                     first = True
                     nullBarCount = []
                     labels = None
                     if self.m_data.attribute(
                             self.m_classIndex).isNominal():
                         labels = [None]
                         for k in range(
                                 self.m_data.attribute(
                                     self.m_classIndex).numValues()):
                             labels.append(
                                 self.m_data.attribute(
                                     self.m_classIndex).value(k))
                     for i in range(len(self.m_histBarClassCounts)):
                         if self.m_histBarClassCounts[i] is not None:
                             if first:
                                 dataList = [[] for k in range(
                                     self.m_histBarClassCounts[i].
                                     numAttributes())]
                             for j in range(self.m_histBarClassCounts[i].
                                            numAttributes()):
                                 # Utils.debugOut("histBarClassCount[",j,"]:",self.m_histBarClassCounts[i].value(j))
                                 dataList[j].append(
                                     self.m_histBarClassCounts[i].value(j))
                                 if first:
                                     newColor.append(self.m_colorList[j])
                             first = False
                         else:
                             nullBarCount.append(i)
                     if dataList is None:
                         dataList = [[0] * len(nullBarCount)]
                     else:
                         for i in range(len(nullBarCount)):
                             for j in range(len(dataList)):
                                 dataList[j].insert(nullBarCount[i], 0)
                     dataList = np.array(dataList)
                     Utils.debugOut("AttrVisual_paint_dataList:", dataList)
                     Utils.debugOut("AttrVisual_paint_barWidth:", barWidth)
                     self.m_Painter.mpl.paintRect(dataList,
                                                  barWidth,
                                                  isNumeric=True,
                                                  colorList=newColor,
                                                  labels=labels)
                 else:
                     if (self.m_Painter.width() - 6) / len(
                             self.m_histBarCounts) < 1:
                         barWidth = 1
                     else:
                         barWidth = (self.m_Painter.width() - 6) / len(
                             self.m_histBarCounts)
                     dataList = np.array([self.m_histBarCounts])
                     self.m_Painter.mpl.paintRect(dataList,
                                                  barWidth,
                                                  isNumeric=True)
                 self.m_Painter.setXLimt(self.m_as.numericStats.min,
                                         self.m_as.numericStats.max,
                                         len(dataList[0]))
             else:
                 self.m_Painter.clear()
    def run(self):
        self.m_panel.mutex.lock()

        if self.m_panel.m_classIndex >= 0 and self.m_panel.m_data.attribute(
                self.m_panel.m_classIndex).isNominal():
            intervalWidth = 3.49 * self.m_panel.m_as.numericStats.stdDev * math.pow(
                self.m_panel.m_data.numInstances(), -1 / 3)
            intervals = max(
                1,
                int(
                    round(
                        (self.m_panel.m_as.numericStats.max -
                         self.m_panel.m_as.numericStats.min) / intervalWidth)))

            # print(self.m_panel.m_Painter.width())
            if intervals > self.m_panel.m_Painter.width():
                #像素填充
                intervals = self.m_panel.m_Painter.width() - 6
                if intervals < 1:
                    intervals = 1
            histClassCounts = [[0] * (self.m_panel.m_data.attribute(
                self.m_panel.m_classIndex).numValues() + 1)
                               for i in range(intervals)]
            Utils.debugOut("max", self.m_panel.m_as.numericStats.max)
            Utils.debugOut("min", self.m_panel.m_as.numericStats.min)
            Utils.debugOut("intervalWidth", intervalWidth)
            Utils.debugOut("len", len(histClassCounts))
            Utils.debugOut("histClasCount:", histClassCounts)
            barRange = (
                self.m_panel.m_as.numericStats.max -
                self.m_panel.m_as.numericStats.min) / len(histClassCounts)

            self.m_panel.m_maxValue = 0
            if len(self.m_panel.m_colorList) == 0:
                self.m_panel.m_colorList.append("black")

            for i in range(
                    len(self.m_panel.m_colorList),
                    self.m_panel.m_data.attribute(
                        self.m_panel.m_classIndex).numValues() + 1):
                colorStr = AttributeVisualizationPanel.m_colorNames[(i - 1) %
                                                                    10]
                self.m_panel.m_colorList.append(colorStr)

            for k in range(self.m_panel.m_data.numInstances()):
                if not self.m_panel.m_data.instance(k).isMissing(
                        self.m_panel.m_attrIndex):
                    t = int(
                        math.ceil(
                            (self.m_panel.m_data.instance(k).value(
                                self.m_panel.m_attrIndex) -
                             self.m_panel.m_as.numericStats.min) / barRange))
                    if t == 0:
                        if self.m_panel.m_data.instance(k).isMissing(
                                self.m_panel.m_classIndex):
                            histClassCounts[t][
                                0] += self.m_panel.m_data.instance(k).weight()
                        else:
                            histClassCounts[t][int(
                                self.m_panel.m_data.instance(k).value(
                                    self.m_panel.m_classIndex) +
                                1)] += self.m_panel.m_data.instance(
                                    k).weight()
                    else:
                        if self.m_panel.m_data.instance(k).isMissing(
                                self.m_panel.m_classIndex):
                            histClassCounts[t - 1][
                                0] += self.m_panel.m_data.instance(k).weight()
                        else:
                            histClassCounts[t - 1][int(
                                self.m_panel.m_data.instance(k).value(
                                    self.m_panel.m_classIndex) +
                                1)] += self.m_panel.m_data.instance(
                                    k).weight()

            for histClassCount in histClassCounts:
                sum = 0
                for element in histClassCount:
                    sum += element
                if self.m_panel.m_maxValue < sum:
                    self.m_panel.m_maxValue = sum

            histClassCountsSparse = [None] * len(histClassCounts)
            for i in range(len(histClassCounts)):
                numSparseValues = 0
                for j in range(len(histClassCounts[i])):
                    if histClassCounts[i][j] > 0:
                        numSparseValues += 1
                sparseValues = [0] * numSparseValues
                sparseIndices = [0] * numSparseValues
                count = 0
                for j in range(len(histClassCounts[i])):
                    if histClassCounts[i][j] > 0:
                        sparseValues[count] = histClassCounts[i][j]
                        sparseIndices[count] = j
                        count += 1
                tempSparse = SparseInstance(1.0, sparseValues, sparseIndices,
                                            len(histClassCounts[i]))
                histClassCountsSparse[i] = tempSparse

            self.m_panel.m_histBarClassCounts = histClassCountsSparse
            self.m_panel.m_barRange = barRange
        else:
            intervalWidth = 3.49 * self.m_panel.m_as.numericStats.stdDev * math.pow(
                self.m_panel.m_data.numInstances(), -1 / 3)
            if Utils.isMissingValue(intervalWidth):
                intervals = 1
            else:
                intervals = max(
                    1,
                    round(
                        (self.m_panel.m_as.numericStats.max -
                         self.m_panel.m_as.numericStats.min) / intervalWidth))
            if intervals > self.m_panel.m_Painter.width():
                intervals = self.m_panel.m_Painter.width() - 6
                if intervals < 1:
                    intervals = 1
            histCounts = [0] * intervals
            barRange = (self.m_panel.m_as.numericStats.max -
                        self.m_panel.m_as.numericStats.min) / len(histCounts)
            self.m_panel.m_maxValue = 0

            for k in range(self.m_panel.m_data.numInstances()):
                if self.m_panel.m_data.instance(k).isMissing(
                        self.m_panel.m_attrIndex):
                    continue
                t = int(
                    math.ceil((self.m_panel.m_data.instance(k).value(
                        self.m_panel.m_attrIndex) -
                               self.m_panel.m_as.numericStats.min) / barRange))
                if t == 0:
                    histCounts[t] += self.m_panel.m_data.instance(k).weight()
                    if histCounts[t] > self.m_panel.m_maxValue:
                        self.m_panel.m_maxValue = histCounts[t]
                else:
                    histCounts[t -
                               1] += self.m_panel.m_data.instance(k).weight()
                    if histCounts[t - 1] > self.m_panel.m_maxValue:
                        self.m_panel.m_maxValue = histCounts[t - 1]
            self.m_panel.m_histBarCounts = histCounts
            self.m_panel.m_barRange = barRange
        self.m_panel.m_threadRun = False
        self.m_panel.m_displayCurrentAttribute = True
        self.m_panel.m_doneCurrentAttribute = True
        self.m_panel.paint()

        self.m_panel.mutex.unlock()