def __init__(self): super().__init__() # This is not a setting because openContext cannot retrieve it before # filling the combo. Settings store this as pending_value self.value = "" self.data = None self.n_matched = None form = QFormLayout() gui.widgetBox(self.controlArea, orientation=form) self.var_model = DomainModel(order=DomainModel.MIXED, valid_types=DiscreteVariable) var_combo = gui.comboBox(None, self, "variable", contentsLength=50, model=self.var_model, callback=self._on_variable_changed) self.value_model = PyListModel() value_combo = gui.comboBox(None, self, "value", label="Value: ", model=self.value_model, callback=self._on_value_changed, contentsLength=50, sizePolicy=(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)) form.addRow("Variable:", var_combo) form.addRow("Value:", value_combo)
def test_itemData(self): model = PyListModel([1, 2, 3, 4]) mi = model.index(2) model.setItemData(mi, {Qt.ToolTipRole: "foo"}) self.assertEqual(model.itemData(mi)[Qt.ToolTipRole], "foo") self.assertEqual(model.itemData(model.index(5)), {})
def test_delegate(self): model = PyListModel([None]) def set_item(v: dict): model.setItemData(model.index(0), v) def get_style_option() -> QStyleOptionViewItem: opt = QStyleOptionViewItem() delegate.initStyleOption(opt, model.index(0)) return opt set_item({Qt.EditRole: Categorical("a", (), ())}) delegate = VariableEditDelegate() opt = get_style_option() self.assertEqual(opt.text, "a") self.assertFalse(opt.font.italic()) set_item({TransformRole: [Rename("b")]}) opt = get_style_option() self.assertEqual(opt.text, "a \N{RIGHTWARDS ARROW} b") self.assertTrue(opt.font.italic()) set_item({TransformRole: [AsString()]}) opt = get_style_option() self.assertIn("reinterpreted", opt.text) self.assertTrue(opt.font.italic())
def test_setitem(self): model = PyListModel([1, 2, 3, 4]) model[1] = 42 self.assertSequenceEqual(model, [1, 42, 3, 4]) model[-1] = 42 self.assertSequenceEqual(model, [1, 42, 3, 42]) with self.assertRaises(IndexError): model[4] # pylint: disable=pointless-statement with self.assertRaises(IndexError): model[-5] # pylint: disable=pointless-statement model = PyListModel([1, 2, 3, 4]) model[0:0] = [-1, 0] self.assertSequenceEqual(model, [-1, 0, 1, 2, 3, 4]) model = PyListModel([1, 2, 3, 4]) model[len(model):len(model)] = [5, 6] self.assertSequenceEqual(model, [1, 2, 3, 4, 5, 6]) model = PyListModel([1, 2, 3, 4]) model[0:2] = (-1, -2) self.assertSequenceEqual(model, [-1, -2, 3, 4]) model = PyListModel([1, 2, 3, 4]) model[-2:] = [-3, -4] self.assertSequenceEqual(model, [1, 2, -3, -4]) model = PyListModel([1, 2, 3, 4]) with self.assertRaises(IndexError): # non unit strides currently not supported model[0:-1:2] = [3, 3]
def test_extend(self): model = PyListModel([]) model.extend([1, 2, 3, 4]) self.assertSequenceEqual(model, [1, 2, 3, 4]) model.extend([5, 6]) self.assertSequenceEqual(model, [1, 2, 3, 4, 5, 6]) self.assertEqual(len(model), len(model._other_data))
def test_clear(self): model = PyListModel([1, 2, 3, 2, 4]) model.clear() self.assertSequenceEqual(model, []) self.assertEqual(len(model), len(model._other_data)) model.clear() self.assertSequenceEqual(model, []) self.assertEqual(len(model), len(model._other_data))
def test_append(self): model = PyListModel([]) model.append(1) self.assertSequenceEqual(model, [1]) model.append(2) self.assertSequenceEqual(model, [1, 2]) self.assertEqual(len(model), len(model._other_data))
def test_insert_delete_rows(self): model = PyListModel([1, 2, 3, 4]) success = model.insertRows(0, 3) self.assertIs(success, True) self.assertSequenceEqual(model, [None, None, None, 1, 2, 3, 4]) success = model.removeRows(3, 4) self.assertIs(success, True) self.assertSequenceEqual(model, [None, None, None]) self.assertFalse(model.insertRows(0, 1, model.index(0))) self.assertFalse(model.removeRows(0, 1, model.index(0)))
def test_list_specials(self): # Essentially tested in other tests, but let's do it explicitly, too # __len__ self.assertEqual(len(self.model), 4) # __contains__ self.assertTrue(2 in self.model) self.assertFalse(5 in self.model) # __iter__ self.assertSequenceEqual(self.model, [1, 2, 3, 4]) # __bool__ self.assertTrue(bool(self.model)) self.assertFalse(bool(PyListModel()))
def test_wrap(self): model = PyListModel() s = [1, 2] model.wrap(s) self.assertSequenceEqual(model, [1, 2]) model.append(3) self.assertEqual(s, [1, 2, 3]) self.assertEqual(len(model._other_data), 3) s.append(5) self.assertRaises(RuntimeError, model._is_index_valid, 0)
def data(self, index, role=Qt.DisplayRole): if self._is_index_valid(index): var = self[index.row()] if var is None and role == Qt.DisplayRole: return self.placeholder or "None" if not isinstance(var, Variable): return super().data(index, role) elif role == Qt.DisplayRole: return var.name elif role == Qt.DecorationRole: return gui.attributeIconDict[var] elif role == Qt.ToolTipRole: return self.variable_tooltip(var) elif role == gui.TableVariable: return var else: return PyListModel.data(self, index, role)
def setUpClass(cls): cls.model = PyListModel([1, 2, 3, 4])
def test_moveRows(self): model = PyListModel([1, 2, 3, 4]) for i in range(model.rowCount()): model.setData(model.index(i), str(i + 1), Qt.UserRole) def modeldata(role): return [model.index(i).data(role) for i in range(model.rowCount())] def userdata(): return modeldata(Qt.UserRole) def editdata(): return modeldata(Qt.EditRole) r = model.moveRows(QModelIndex(), 1, 1, QModelIndex(), 0) self.assertIs(r, True) self.assertSequenceEqual(editdata(), [2, 1, 3, 4]) self.assertSequenceEqual(userdata(), ["2", "1", "3", "4"]) r = model.moveRows(QModelIndex(), 1, 2, QModelIndex(), 4) self.assertIs(r, True) self.assertSequenceEqual(editdata(), [2, 4, 1, 3]) self.assertSequenceEqual(userdata(), ["2", "4", "1", "3"]) r = model.moveRows(QModelIndex(), 3, 1, QModelIndex(), 0) self.assertIs(r, True) self.assertSequenceEqual(editdata(), [3, 2, 4, 1]) self.assertSequenceEqual(userdata(), ["3", "2", "4", "1"]) r = model.moveRows(QModelIndex(), 2, 1, QModelIndex(), 2) self.assertIs(r, False) model = PyListModel([]) r = model.moveRows(QModelIndex(), 0, 0, QModelIndex(), 0) self.assertIs(r, False)
def test_sort(self): model = PyListModel([3, 1, 4, 2]) model._other_data = list("abcd") model.sort() self.assertSequenceEqual(model, [1, 2, 3, 4]) self.assertSequenceEqual(model._other_data, "bdac")
def test_reverse(self): model = PyListModel([1, 2, 3, 4]) model._other_data = list("abcd") model.reverse() self.assertSequenceEqual(model, [4, 3, 2, 1]) self.assertSequenceEqual(model._other_data, "dcba")
def test_pop(self): model = PyListModel([1, 2, 3, 2, 4]) model._other_data = list("abcde") model.pop(1) self.assertSequenceEqual(model, [1, 3, 2, 4]) self.assertSequenceEqual(model._other_data, "acde")
def test_dropMimeData(self): model = PyListModel([1, 2]) model.setData(model.index(0), "a", Qt.UserRole) mime = model.mimeData([model.index(0)]) self.assertTrue( model.dropMimeData(mime, Qt.CopyAction, 2, -1, model.index(-1, -1)) ) self.assertEqual(len(model), 3) self.assertEqual( model.itemData(model.index(2)), {Qt.DisplayRole: 1, Qt.EditRole: 1, Qt.UserRole: "a"} )
def __init__(self): super().__init__() #: widget's runtime state self.__state = State.NoState self.corpus = None self.n_text_categories = 0 self.n_text_data = 0 self.skipped_documents = [] self.__invalidated = False self.__pendingTask = None layout = QGridLayout() layout.setSpacing(4) gui.widgetBox(self.controlArea, orientation=layout, box='Source') source_box = gui.radioButtons(None, self, "source", box=True, callback=self.start, addToLayout=False) rb_button = gui.appendRadioButton(source_box, "Folder:", addToLayout=False) layout.addWidget(rb_button, 0, 0, Qt.AlignVCenter) box = gui.hBox(None, addToLayout=False, margin=0) box.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) self.recent_cb = QComboBox( sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon, minimumContentsLength=16, acceptDrops=True ) self.recent_cb.installEventFilter(self) self.recent_cb.activated[int].connect(self.__onRecentActivated) browseaction = QAction( "Open/Load Documents", self, iconText="\N{HORIZONTAL ELLIPSIS}", icon=self.style().standardIcon(QStyle.SP_DirOpenIcon), toolTip="Select a folder from which to load the documents" ) browseaction.triggered.connect(self.__runOpenDialog) reloadaction = QAction( "Reload", self, icon=self.style().standardIcon(QStyle.SP_BrowserReload), toolTip="Reload current document set" ) reloadaction.triggered.connect(self.reload) self.__actions = namespace( browse=browseaction, reload=reloadaction, ) browsebutton = QPushButton( browseaction.iconText(), icon=browseaction.icon(), toolTip=browseaction.toolTip(), clicked=browseaction.trigger, default=False, autoDefault=False, ) reloadbutton = QPushButton( reloadaction.iconText(), icon=reloadaction.icon(), clicked=reloadaction.trigger, default=False, autoDefault=False, ) box.layout().addWidget(self.recent_cb) layout.addWidget(box, 0, 1) layout.addWidget(browsebutton, 0, 2) layout.addWidget(reloadbutton, 0, 3) rb_button = gui.appendRadioButton(source_box, "URL:", addToLayout=False) layout.addWidget(rb_button, 3, 0, Qt.AlignVCenter) self.url_combo = url_combo = QComboBox() url_model = PyListModel() url_model.wrap(self.recent_urls) url_combo.setLineEdit(LineEditSelectOnFocus()) url_combo.setModel(url_model) url_combo.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) url_combo.setEditable(True) url_combo.setInsertPolicy(url_combo.InsertAtTop) url_edit = url_combo.lineEdit() l, t, r, b = url_edit.getTextMargins() url_edit.setTextMargins(l + 5, t, r, b) layout.addWidget(url_combo, 3, 1, 1, 3) url_combo.activated.connect(self._url_set) # whit completer we set that combo box is case sensitive when # matching the history completer = QCompleter() completer.setCaseSensitivity(Qt.CaseSensitive) url_combo.setCompleter(completer) self.addActions([browseaction, reloadaction]) reloadaction.changed.connect( lambda: reloadbutton.setEnabled(reloadaction.isEnabled()) ) box = gui.vBox(self.controlArea, "Info") self.infostack = QStackedWidget() self.info_area = QLabel( text="No document set selected", wordWrap=True ) self.progress_widget = QProgressBar( minimum=0, maximum=100 ) self.cancel_button = QPushButton( "Cancel", icon=self.style().standardIcon(QStyle.SP_DialogCancelButton), default=False, autoDefault=False, ) self.cancel_button.clicked.connect(self.cancel) w = QWidget() vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) hlayout = QHBoxLayout() hlayout.setContentsMargins(0, 0, 0, 0) hlayout.addWidget(self.progress_widget) hlayout.addWidget(self.cancel_button) vlayout.addLayout(hlayout) self.pathlabel = TextLabel() self.pathlabel.setTextElideMode(Qt.ElideMiddle) self.pathlabel.setAttribute(Qt.WA_MacSmallSize) vlayout.addWidget(self.pathlabel) w.setLayout(vlayout) self.infostack.addWidget(self.info_area) self.infostack.addWidget(w) box.layout().addWidget(self.infostack) self.__initRecentItemsModel() self.__invalidated = True self.__executor = ThreadExecutor(self) QApplication.postEvent(self, QEvent(RuntimeEvent.Init))
def test_delitem(self): model = PyListModel([1, 2, 3, 4]) model._other_data = list("abcd") del model[1] self.assertSequenceEqual(model, [1, 3, 4]) self.assertSequenceEqual(model._other_data, "acd") model = PyListModel([1, 2, 3, 4]) model._other_data = list("abcd") del model[1:3] self.assertSequenceEqual(model, [1, 4]) self.assertSequenceEqual(model._other_data, "ad") model = PyListModel([1, 2, 3, 4]) model._other_data = list("abcd") del model[:] self.assertSequenceEqual(model, []) self.assertEqual(len(model._other_data), 0) model = PyListModel([1, 2, 3, 4]) with self.assertRaises(IndexError): # non unit strides currently not supported del model[0:-1:2] self.assertEqual(len(model), len(model._other_data))
def test_set_data(self): model = PyListModel([1, 2, 3, 4]) model.setData(model.index(0), None, Qt.EditRole) self.assertIs(model.data(model.index(0), Qt.EditRole), None) model.setData(model.index(1), "This is two", Qt.ToolTipRole) self.assertEqual(model.data(model.index(1), Qt.ToolTipRole), "This is two",) self.assertFalse(model.setData(model.index(5), "foo"))
class OWQuickSelect(widget.OWWidget): name = 'Quick Select' icon = 'icons/QuickSelect.svg' description = 'Select instances with specific feature value.' class Inputs: data = widget.Input("Data", Table) class Outputs: matching = widget.Output("Matching Data", Table, default=True) unmatched = widget.Output("Unmatched Data", Table) annotated = widget.Output(ANNOTATED_DATA_SIGNAL_NAME, Table) class Error(widget.OWWidget.Error): no_categorical = Msg("No categorical variables") want_main_area = False resizing_enabled = False settingsHandler = settings.DomainContextHandler() variable = settings.ContextSetting(None) pending_value = settings.ContextSetting("") def __init__(self): super().__init__() # This is not a setting because openContext cannot retrieve it before # filling the combo. Settings store this as pending_value self.value = "" self.data = None self.n_matched = None form = QFormLayout() gui.widgetBox(self.controlArea, orientation=form) self.var_model = DomainModel(order=DomainModel.MIXED, valid_types=DiscreteVariable) var_combo = gui.comboBox(None, self, "variable", contentsLength=50, model=self.var_model, callback=self._on_variable_changed) self.value_model = PyListModel() value_combo = gui.comboBox(None, self, "value", label="Value: ", model=self.value_model, callback=self._on_value_changed, contentsLength=50, sizePolicy=(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)) form.addRow("Variable:", var_combo) form.addRow("Value:", value_combo) @Inputs.data def set_data(self, data): self.closeContext() self.data = data self.Error.no_categorical.clear() # TODO: Check that contexts are retrieved properly, also when removing # and re-adding a connection if data: self.var_model.set_domain(data.domain) self.info.set_input_summary(len(data), format_summary_details(data)) if not self.var_model.rowCount(): self.data = None self.Error.no_categorical() else: self.var_model.set_domain(None) self.info.set_input_summary(self.info.NoInput) self.variable = self.var_model[0] if self.data else None self.openContext(self.data) self.set_value_list() if self.variable and self.pending_value in self.variable.values: self.value = self.pending_value self.commit() def set_value_list(self): if self.variable is None: self.value_model.clear() self.value = "" else: self.value_model[:] = self.variable.values self.value = self.value_model[0] if self.variable.values else "" def _on_variable_changed(self): self.set_value_list() self.commit() def _on_value_changed(self): self.pending_value = self.value self.commit() def commit(self): if not (self.data and self.variable and self.value): annotated = matching = unmatched = None self.n_matched = None else: column = self.data.get_column_view(self.variable)[0] valind = self.variable.values.index(self.value) mask = column == valind annotated = create_annotated_table(self.data, np.flatnonzero(mask)) matching = self.data[mask] unmatched = self.data[~mask] self.n_matched = len(matching) self.Outputs.matching.send(matching) self.Outputs.unmatched.send(unmatched) self.Outputs.annotated.send(annotated) def send_report(self): if not self.data: return self.report_items( "", [("Filter", f"{self.variable.name} = '{self.value}'"), ("Matching instances", f"{self.n_matched} (out of {len(self.data)})")])
def test_insert(self): model = PyListModel() model.insert(0, 1) self.assertSequenceEqual(model, [1]) self.assertEqual(len(model._other_data), 1) model._other_data = ["a"] model.insert(0, 2) self.assertSequenceEqual(model, [2, 1]) self.assertEqual(model._other_data[1], "a") self.assertNotEqual(model._other_data[0], "a") model._other_data[0] = "b" model.insert(1, 3) self.assertSequenceEqual(model, [2, 3, 1]) self.assertEqual(model._other_data[0], "b") self.assertEqual(model._other_data[2], "a") self.assertNotEqual(model._other_data[1], "b") self.assertNotEqual(model._other_data[1], "a") model._other_data[1] = "c" model.insert(3, 4) self.assertSequenceEqual(model, [2, 3, 1, 4]) self.assertSequenceEqual(model._other_data[:3], ["b", "c", "a"]) model._other_data[3] = "d" model.insert(-1, 5) self.assertSequenceEqual(model, [2, 3, 1, 5, 4]) self.assertSequenceEqual(model._other_data[:3], ["b", "c", "a"]) self.assertEqual(model._other_data[4], "d") self.assertEqual(len(model), len(model._other_data))
def test_mimeData(self): model = PyListModel([1, 2]) model._other_data[:] = [{Qt.UserRole: "a"}, {}] mime = model.mimeData([model.index(0), model.index(1)]) self.assertTrue(mime.hasFormat(PyListModel.MIME_TYPE))
def __init__(self): super().__init__() self.data = None self.test_data = None self.preprocessor = None self.train_data_missing_vals = False self.test_data_missing_vals = False self.scorers = [] self.__pending_comparison_criterion = self.comparison_criterion #: An Ordered dictionary with current inputs and their testing results. self.learners = OrderedDict() # type: Dict[Any, Input] self.__state = State.Waiting # Do we need to [re]test any learners, set by _invalidate and # cleared by __update self.__needupdate = False self.__task = None # type: Optional[TaskState] self.__executor = ThreadExecutor() sbox = gui.vBox(self.controlArea, "Sampling") rbox = gui.radioButtons(sbox, self, "resampling", callback=self._param_changed) gui.appendRadioButton(rbox, "Cross validation") ibox = gui.indentedBox(rbox) gui.comboBox(ibox, self, "n_folds", label="Number of folds: ", items=[str(x) for x in self.NFolds], maximumContentsLength=3, orientation=Qt.Horizontal, callback=self.kfold_changed) gui.checkBox(ibox, self, "cv_stratified", "Stratified", callback=self.kfold_changed) gui.appendRadioButton(rbox, "Cross validation by feature") ibox = gui.indentedBox(rbox) self.feature_model = DomainModel(order=DomainModel.METAS, valid_types=DiscreteVariable) self.features_combo = gui.comboBox(ibox, self, "fold_feature", model=self.feature_model, orientation=Qt.Horizontal, callback=self.fold_feature_changed) gui.appendRadioButton(rbox, "Random sampling") ibox = gui.indentedBox(rbox) gui.comboBox(ibox, self, "n_repeats", label="Repeat train/test: ", items=[str(x) for x in self.NRepeats], maximumContentsLength=3, orientation=Qt.Horizontal, callback=self.shuffle_split_changed) gui.comboBox(ibox, self, "sample_size", label="Training set size: ", items=["{} %".format(x) for x in self.SampleSizes], maximumContentsLength=5, orientation=Qt.Horizontal, callback=self.shuffle_split_changed) gui.checkBox(ibox, self, "shuffle_stratified", "Stratified", callback=self.shuffle_split_changed) gui.appendRadioButton(rbox, "Leave one out") gui.appendRadioButton(rbox, "Test on train data") gui.appendRadioButton(rbox, "Test on test data") self.cbox = gui.vBox(self.controlArea, "Target Class") self.class_selection_combo = gui.comboBox( self.cbox, self, "class_selection", items=[], sendSelectedValue=True, valueType=str, callback=self._on_target_class_changed, contentsLength=8) self.modcompbox = box = gui.vBox(self.controlArea, "Model Comparison") gui.comboBox(box, self, "comparison_criterion", model=PyListModel(), callback=self.update_comparison_table) hbox = gui.hBox(box) gui.checkBox(hbox, self, "use_rope", "Negligible difference: ", callback=self._on_use_rope_changed) gui.lineEdit(hbox, self, "rope", validator=QDoubleValidator(), controlWidth=70, callback=self.update_comparison_table, alignment=Qt.AlignRight) self.controls.rope.setEnabled(self.use_rope) gui.rubber(self.controlArea) self.score_table = ScoreTable(self) self.score_table.shownScoresChanged.connect(self.update_stats_model) view = self.score_table.view view.setSizeAdjustPolicy(view.AdjustToContents) box = gui.vBox(self.mainArea, "Evaluation Results") box.layout().addWidget(self.score_table.view) self.compbox = box = gui.vBox(self.mainArea, box="Model comparison") table = self.comparison_table = QTableWidget( wordWrap=False, editTriggers=QTableWidget.NoEditTriggers, selectionMode=QTableWidget.NoSelection) table.setSizeAdjustPolicy(table.AdjustToContents) header = table.verticalHeader() header.setSectionResizeMode(QHeaderView.Fixed) header.setSectionsClickable(False) header = table.horizontalHeader() header.setTextElideMode(Qt.ElideRight) header.setDefaultAlignment(Qt.AlignCenter) header.setSectionsClickable(False) header.setStretchLastSection(False) header.setSectionResizeMode(QHeaderView.ResizeToContents) avg_width = self.fontMetrics().averageCharWidth() header.setMinimumSectionSize(8 * avg_width) header.setMaximumSectionSize(15 * avg_width) header.setDefaultSectionSize(15 * avg_width) box.layout().addWidget(table) box.layout().addWidget( QLabel( "<small>Table shows probabilities that the score for the model in " "the row is higher than that of the model in the column. " "Small numbers show the probability that the difference is " "negligible.</small>", wordWrap=True))
def __init__(self): super().__init__() self.data = None self.test_data = None self.preprocessor = None self.train_data_missing_vals = False self.test_data_missing_vals = False self.scorers = [] self.__pending_comparison_criterion = self.comparison_criterion #: An Ordered dictionary with current inputs and their testing results. self.learners = OrderedDict() # type: Dict[Any, Input] self.__state = State.Waiting # Do we need to [re]test any learners, set by _invalidate and # cleared by __update self.__needupdate = False self.__task = None # type: Optional[TaskState] self.__executor = ThreadExecutor() sbox = gui.vBox(self.controlArea, "抽样") rbox = gui.radioButtons( sbox, self, "resampling", callback=self._param_changed) gui.appendRadioButton(rbox, "交叉验证(Cross validation)") ibox = gui.indentedBox(rbox) gui.comboBox( ibox, self, "n_folds", label="折叠次数(Number of folds): ", items=[str(x) for x in self.NFolds], maximumContentsLength=3, orientation=Qt.Horizontal, callback=self.kfold_changed) gui.checkBox( ibox, self, "cv_stratified", "分层(Stratified)", callback=self.kfold_changed) gui.appendRadioButton(rbox, "按特征交叉验证(Cross validation by feature)") ibox = gui.indentedBox(rbox) self.feature_model = DomainModel( order=DomainModel.METAS, valid_types=DiscreteVariable) self.features_combo = gui.comboBox( ibox, self, "fold_feature", model=self.feature_model, orientation=Qt.Horizontal, callback=self.fold_feature_changed) gui.appendRadioButton(rbox, "随机抽样(Random sampling)") ibox = gui.indentedBox(rbox) gui.comboBox( ibox, self, "n_repeats", label="重复训练/测试: ", items=[str(x) for x in self.NRepeats], maximumContentsLength=3, orientation=Qt.Horizontal, callback=self.shuffle_split_changed) gui.comboBox( ibox, self, "sample_size", label="训练集大小: ", items=["{} %".format(x) for x in self.SampleSizes], maximumContentsLength=5, orientation=Qt.Horizontal, callback=self.shuffle_split_changed) gui.checkBox( ibox, self, "shuffle_stratified", "分层(Stratified)", callback=self.shuffle_split_changed) gui.appendRadioButton(rbox, "留一法(Leave one out)") gui.appendRadioButton(rbox, "测试训练数据") gui.appendRadioButton(rbox, "测试测试数据") self.cbox = gui.vBox(self.controlArea, "目标类别") self.class_selection_combo = gui.comboBox( self.cbox, self, "class_selection", items=[], sendSelectedValue=True, valueType=str, callback=self._on_target_class_changed, contentsLength=8) self.modcompbox = box = gui.vBox(self.controlArea, "模型比较") gui.comboBox( box, self, "comparison_criterion", model=PyListModel(), callback=self.update_comparison_table) hbox = gui.hBox(box) gui.checkBox(hbox, self, "use_rope", "可忽略区别: ", callback=self._on_use_rope_changed) gui.lineEdit(hbox, self, "rope", validator=QDoubleValidator(), controlWidth=70, callback=self.update_comparison_table, alignment=Qt.AlignRight) self.controls.rope.setEnabled(self.use_rope) gui.rubber(self.controlArea) self.score_table = ScoreTable(self) self.score_table.shownScoresChanged.connect(self.update_stats_model) view = self.score_table.view view.setSizeAdjustPolicy(view.AdjustToContents) box = gui.vBox(self.mainArea, "评价结果") box.layout().addWidget(self.score_table.view) self.compbox = box = gui.vBox(self.mainArea, box='模型比较') table = self.comparison_table = QTableWidget( wordWrap=False, editTriggers=QTableWidget.NoEditTriggers, selectionMode=QTableWidget.NoSelection) table.setSizeAdjustPolicy(table.AdjustToContents) header = table.verticalHeader() header.setSectionResizeMode(QHeaderView.Fixed) header.setSectionsClickable(False) header = table.horizontalHeader() header.setTextElideMode(Qt.ElideRight) header.setDefaultAlignment(Qt.AlignCenter) header.setSectionsClickable(False) header.setStretchLastSection(False) header.setSectionResizeMode(QHeaderView.ResizeToContents) avg_width = self.fontMetrics().averageCharWidth() header.setMinimumSectionSize(8 * avg_width) header.setMaximumSectionSize(15 * avg_width) header.setDefaultSectionSize(15 * avg_width) box.layout().addWidget(table) box.layout().addWidget(QLabel( "<small>此表显示数值为一概率. 此概率表示\"行模型\"的评价指标大于" "\"列模型\"的评价指标. " "值小说明概率很小, 区别可以忽略不计.</small>", wordWrap=True))