Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 30 additions & 31 deletions Orange/widgets/data/owrank.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,30 +49,31 @@ def from_variable(cls, variable):
cls.REGRESSION if isinstance(variable, ContinuousVariable) else
cls.UNSUPERVISED)

ScoreMeta = namedtuple("score_meta", ["name", "shortname", "scorer", 'problem_type', 'is_default'])
ScoreMeta = namedtuple("score_meta", ["name", "shortname", "scorer",
'problem_type', 'is_default', "id"])

# Default scores.
CLS_SCORES = [
ScoreMeta("Information Gain", "Info. gain",
score.InfoGain, ProblemType.CLASSIFICATION, False),
score.InfoGain, ProblemType.CLASSIFICATION, False, 1),
ScoreMeta("Information Gain Ratio", "Gain ratio",
score.GainRatio, ProblemType.CLASSIFICATION, True),
score.GainRatio, ProblemType.CLASSIFICATION, True, 2),
ScoreMeta("Gini Decrease", "Gini",
score.Gini, ProblemType.CLASSIFICATION, True),
score.Gini, ProblemType.CLASSIFICATION, True, 3),
ScoreMeta("ANOVA", "ANOVA",
score.ANOVA, ProblemType.CLASSIFICATION, False),
score.ANOVA, ProblemType.CLASSIFICATION, False, 4),
ScoreMeta("χ²", "χ²",
score.Chi2, ProblemType.CLASSIFICATION, False),
score.Chi2, ProblemType.CLASSIFICATION, False, 5),
ScoreMeta("ReliefF", "ReliefF",
score.ReliefF, ProblemType.CLASSIFICATION, False),
score.ReliefF, ProblemType.CLASSIFICATION, False, 6),
ScoreMeta("FCBF", "FCBF",
score.FCBF, ProblemType.CLASSIFICATION, False)
score.FCBF, ProblemType.CLASSIFICATION, False, 7)
]
REG_SCORES = [
ScoreMeta("Univariate Regression", "Univar. reg.",
score.UnivariateLinearRegression, ProblemType.REGRESSION, True),
score.UnivariateLinearRegression, ProblemType.REGRESSION, True, 8),
ScoreMeta("RReliefF", "RReliefF",
score.RReliefF, ProblemType.REGRESSION, True)
score.RReliefF, ProblemType.REGRESSION, True, 9)
]
SCORES = CLS_SCORES + REG_SCORES

Expand Down Expand Up @@ -230,7 +231,7 @@ class Outputs:
sorting = Setting((0, enum2int(Qt.DescendingOrder)))
selected_methods = Setting(set())

settings_version = 4
settings_version = 5
settingsHandler = DomainContextHandler()
selected_attrs = ContextSetting([], schema_only=True)
selectionMethod = ContextSetting(SelectNBest)
Expand Down Expand Up @@ -261,7 +262,7 @@ def __init__(self):
self.methods_results = {}

if not self.selected_methods:
self.selected_methods = {method.name for method in SCORES
self.selected_methods = {method.id for method in SCORES
if method.is_default}

# GUI
Expand Down Expand Up @@ -292,8 +293,8 @@ def _set_select_manual():
box.layout().addWidget(QCheckBox(
method.name, self,
objectName=method.shortname, # To be easily found in tests
checked=method.name in self.selected_methods,
stateChanged=partial(self.methodSelectionChanged, method_name=method.name)))
checked=method.id in self.selected_methods,
stateChanged=partial(self.methodSelectionChanged, method_id=method.id)))
gui.rubber(box)

gui.rubber(self.controlArea)
Expand Down Expand Up @@ -400,7 +401,7 @@ def set_learner(self, index, scorer):
self.scorers[index] = ScoreMeta(
scorer.name, scorer.name, scorer,
ProblemType.from_variable(scorer.class_type),
False
False, 100 + index
)
self.scorers_results = {}

Expand All @@ -409,7 +410,7 @@ def insert_learner(self, index: int, scorer):
self.scorers.insert(index, ScoreMeta(
scorer.name, scorer.name, scorer,
ProblemType.from_variable(scorer.class_type),
False
False, 100 + index
))
self.scorers_results = {}

Expand All @@ -423,7 +424,7 @@ def _get_methods(self):
method
for method in SCORES
if (
method.name in self.selected_methods
method.id in self.selected_methods
and method.problem_type == self.problem_type_mode
and (
not issparse(self.data.X)
Expand Down Expand Up @@ -568,12 +569,12 @@ def headerClick(self, index):
sort_column = self.ranksModel.sortColumn() - 2 # -2 for name and '#' columns
self.sorting = (sort_column, sort_order)

def methodSelectionChanged(self, state: int, method_name):
def methodSelectionChanged(self, state: int, method_id: int):
state = Qt.CheckState(state)
if state == Qt.Checked:
self.selected_methods.add(method_name)
elif method_name in self.selected_methods:
self.selected_methods.remove(method_name)
self.selected_methods.add(method_id)
else:
self.selected_methods.discard(method_id)

self.update_scores()

Expand Down Expand Up @@ -649,6 +650,13 @@ def migrate_settings(cls, settings, version):
column, order = settings["sorting"]
settings["sorting"] = (column, enum2int(order))

if version < 5 and "selected_methods" in settings:
selected_names = settings["selected_methods"]
settings["selected_methods"] = {
method.id for method in SCORES
if method.name in selected_names
}

@classmethod
def migrate_context(cls, context, version):
if version is None or version < 3:
Expand All @@ -659,15 +667,6 @@ def migrate_context(cls, context, version):

if __name__ == "__main__": # pragma: no cover
from Orange.classification import RandomForestLearner
previewer = WidgetPreview(OWRank)
previewer.run(Table("heart_disease.tab"), no_exit=True)
previewer.send_signals(
set_learner=(RandomForestLearner(), (3, 'Learner', None)))
previewer.run()

# pylint: disable=pointless-string-statement
"""
WidgetPreview(OWRank).run(
set_learner=(RandomForestLearner(), (3, 'Learner', None)),
insert_learner=(0, RandomForestLearner()),
set_data=Table("heart_disease.tab"))
"""
14 changes: 13 additions & 1 deletion Orange/widgets/data/tests/test_owrank.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from Orange.projection import PCA
from Orange.widgets import gui
from Orange.widgets.data.owrank import OWRank, ProblemType, CLS_SCORES, \
REG_SCORES, RankTableModel
REG_SCORES, RankTableModel, SCORES
from Orange.widgets.tests.base import WidgetTest, datasets
from Orange.widgets.widget import AttributeList

Expand All @@ -38,6 +38,11 @@ def score_data(self, data, feature=None):
return np.ones((1, len(data.domain.attributes)))


class TestScoreMeta(unittest.TestCase):
def test_unique_ids(self):
self.assertEqual(len({score.id for score in SCORES}), len(SCORES))


class TestRankModel(GuiTest):
def setUp(self):
attributes = [DiscreteVariable("ann", values=tuple("ab")),
Expand Down Expand Up @@ -646,6 +651,13 @@ def test_concurrent_cancel(self):
output = self.get_output(self.widget.Outputs.reduced_data)
self.assertEqual(len(output), len(self.housing))

def test_migration_to_5(self):
settings = {
'selected_methods': {'Information Gain', 'ANOVA', 'FCBF', 'RReliefF'}
}
OWRank.migrate_settings(settings, version=4)
self.assertEqual(settings["selected_methods"], {1, 4, 7, 9})


if __name__ == "__main__":
unittest.main()
3 changes: 2 additions & 1 deletion i18n/si/msgs.jaml
Original file line number Diff line number Diff line change
Expand Up @@ -7854,6 +7854,7 @@ widgets/data/owrank.py:
scorer: false
problem_type: false
is_default: false
id: false
Information Gain: Informacijski prispevek
Info. gain: Inf. prisp
Information Gain Ratio: Delež inform. prispevka
Expand Down Expand Up @@ -7921,9 +7922,9 @@ widgets/data/owrank.py:
def `migrate_settings`:
headerState: false
sorting: false
selected_methods: false
__main__: false
heart_disease.tab: false
Learner: false
widgets/data/owsave.py:
~{os.sep}: false
class `OWSave`:
Expand Down
Loading