Skip to content

Commit 752abbd

Browse files
committed
callback: Rename to progress_callback
1 parent 30ccc07 commit 752abbd

File tree

8 files changed

+93
-87
lines changed

8 files changed

+93
-87
lines changed

Orange/base.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
from Orange.data import Table, Storage, Instance, Value
1111
from Orange.data.filter import HasClass
1212
from Orange.data.table import DomainTransformationError
13-
from Orange.data.util import one_hot, progress_callback, dummy_callback
13+
from Orange.data.util import one_hot
1414
from Orange.misc.wrapper_meta import WrapperMeta
1515
from Orange.preprocess import Continuize, RemoveNaNColumns, SklImpute, Normalize
1616
from Orange.statistics.util import all_nan
17-
from Orange.util import Reprable, OrangeDeprecationWarning
17+
from Orange.util import Reprable, OrangeDeprecationWarning, wrap_callback, \
18+
dummy_callback
1819

1920
__all__ = ["Learner", "Model", "SklLearner", "SklModel",
2021
"ReprableWithPreprocessors"]
@@ -102,7 +103,7 @@ def fit_storage(self, data):
102103
X, Y, W = data.X, data.Y, data.W if data.has_weights() else None
103104
return self.fit(X, Y, W)
104105

105-
def __call__(self, data, callback=None):
106+
def __call__(self, data, progress_callback=None):
106107
if not self.check_learner_adequacy(data.domain):
107108
raise ValueError(self.learner_adequacy_err_msg)
108109

@@ -112,33 +113,33 @@ def __call__(self, data, callback=None):
112113
data = Table(data.domain, [data])
113114
origdata = data
114115

115-
if callback is None:
116-
callback = dummy_callback
117-
callback(0, "Preprocessing...")
116+
if progress_callback is None:
117+
progress_callback = dummy_callback
118+
progress_callback(0, "Preprocessing...")
118119
try:
119-
cb = progress_callback(callback, end=0.1)
120-
data = self.preprocess(data, callback=cb)
120+
cb = wrap_callback(progress_callback, end=0.1)
121+
data = self.preprocess(data, progress_callback=cb)
121122
except TypeError:
122123
data = self.preprocess(data)
123-
warnings.warn("A keyword argument 'callback' has been added to the"
124-
" preprocess() signature. Implementing the method "
125-
"without the argument is deprecated and will result "
126-
"in an error in the future.",
124+
warnings.warn("A keyword argument 'progress_callback' has been "
125+
"added to the preprocess() signature. Implementing "
126+
"the method without the argument is deprecated and "
127+
"will result in an error in the future.",
127128
OrangeDeprecationWarning)
128129

129130
if len(data.domain.class_vars) > 1 and not self.supports_multiclass:
130131
raise TypeError("%s doesn't support multiple class variables" %
131132
self.__class__.__name__)
132133

133-
callback(0.1, "Fitting...")
134+
progress_callback(0.1, "Fitting...")
134135
model = self._fit_model(data)
135136
model.used_vals = [np.unique(y).astype(int) for y in data.Y[:, None].T]
136137
model.domain = data.domain
137138
model.supports_multiclass = self.supports_multiclass
138139
model.name = self.name
139140
model.original_domain = origdomain
140141
model.original_data = origdata
141-
callback(1)
142+
progress_callback(1)
142143
return model
143144

144145
def _fit_model(self, data):
@@ -148,15 +149,15 @@ def _fit_model(self, data):
148149
X, Y, W = data.X, data.Y, data.W if data.has_weights() else None
149150
return self.fit(X, Y, W)
150151

151-
def preprocess(self, data, callback=None):
152+
def preprocess(self, data, progress_callback=None):
152153
"""Apply the `preprocessors` to the data"""
153-
if callback is None:
154-
callback = dummy_callback
154+
if progress_callback is None:
155+
progress_callback = dummy_callback
155156
n_pps = len(list(self.active_preprocessors))
156157
for i, pp in enumerate(self.active_preprocessors):
157-
callback(i / n_pps)
158+
progress_callback(i / n_pps)
158159
data = pp(data)
159-
callback(1)
160+
progress_callback(1)
160161
return data
161162

162163
@property
@@ -489,8 +490,8 @@ def _get_sklparams(self, values):
489490
raise TypeError("Wrapper does not define '__wraps__'")
490491
return params
491492

492-
def preprocess(self, data, callback=None):
493-
data = super().preprocess(data, callback)
493+
def preprocess(self, data, progress_callback=None):
494+
data = super().preprocess(data, progress_callback)
494495

495496
if any(v.is_discrete and len(v.values) > 2
496497
for v in data.domain.attributes):
@@ -499,8 +500,8 @@ def preprocess(self, data, callback=None):
499500

500501
return data
501502

502-
def __call__(self, data, callback=None):
503-
m = super().__call__(data, callback)
503+
def __call__(self, data, progress_callback=None):
504+
m = super().__call__(data, progress_callback)
504505
m.params = self.params
505506
return m
506507

Orange/classification/outlier_detection.py

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
from Orange.data import Table, Domain, DiscreteVariable, ContinuousVariable, \
1313
Variable
1414
from Orange.data.table import DomainTransformationError
15-
from Orange.data.util import get_unique_names, progress_callback, \
16-
dummy_callback
15+
from Orange.data.util import get_unique_names
1716
from Orange.preprocess import AdaptiveNormalize
1817
from Orange.statistics.util import all_nan
18+
from Orange.util import wrap_callback, dummy_callback
1919

2020
__all__ = ["LocalOutlierFactorLearner", "IsolationForestLearner",
2121
"EllipticEnvelopeLearner", "OneClassSVMLearner"]
@@ -32,43 +32,45 @@ def predict(self, X: np.ndarray) -> np.ndarray:
3232
pred[pred == -1] = 0
3333
return pred[:, None]
3434

35-
def __call__(self, data: Table, callback: Callable = None) -> Table:
35+
def __call__(self, data: Table, progress_callback: Callable = None) \
36+
-> Table:
3637
assert isinstance(data, Table)
3738
assert self.outlier_var is not None
3839

3940
domain = Domain(data.domain.attributes, data.domain.class_vars,
4041
data.domain.metas + (self.outlier_var,))
41-
if callback is None:
42-
callback = dummy_callback
43-
callback(0, "Preprocessing...")
42+
if progress_callback is None:
43+
progress_callback = dummy_callback
44+
progress_callback(0, "Preprocessing...")
4445
self._cached_data = self.data_to_model_domain(
45-
data, progress_callback(callback, end=0.1))
46-
callback(0.1, "Predicting...")
46+
data, wrap_callback(progress_callback, end=0.1))
47+
progress_callback(0.1, "Predicting...")
4748
metas = np.hstack((data.metas, self.predict(self._cached_data.X)))
48-
callback(1)
49+
progress_callback(1)
4950
return Table.from_numpy(domain, data.X, data.Y, metas)
5051

51-
def data_to_model_domain(self, data: Table, callback: Callable) -> Table:
52+
def data_to_model_domain(self, data: Table, progress_callback: Callable) \
53+
-> Table:
5254
if data.domain == self.domain:
5355
return data
5456

55-
callback(0)
57+
progress_callback(0)
5658
if self.original_domain.attributes != data.domain.attributes \
5759
and data.X.size \
5860
and not all_nan(data.X):
59-
callback(0.5)
61+
progress_callback(0.5)
6062
new_data = data.transform(self.original_domain)
6163
if all_nan(new_data.X):
6264
raise DomainTransformationError(
6365
"domain transformation produced no defined values")
64-
callback(0.75)
66+
progress_callback(0.75)
6567
data = new_data.transform(self.domain)
66-
callback(1)
68+
progress_callback(1)
6769
return data
6870

69-
callback(0.5)
71+
progress_callback(0.5)
7072
data = data.transform(self.domain)
71-
callback(1)
73+
progress_callback(1)
7274
return data
7375

7476

@@ -166,8 +168,9 @@ def mahalanobis(self, observations: np.ndarray) -> np.ndarray:
166168
"""
167169
return self.skl_model.mahalanobis(observations)[:, None]
168170

169-
def __call__(self, data: Table, callback: Callable = None) -> Table:
170-
pred = super().__call__(data, callback)
171+
def __call__(self, data: Table, progress_callback: Callable = None) \
172+
-> Table:
173+
pred = super().__call__(data, progress_callback)
171174
domain = Domain(pred.domain.attributes, pred.domain.class_vars,
172175
pred.domain.metas + (self.mahal_var,))
173176
metas = np.hstack((pred.metas, self.mahalanobis(self._cached_data.X)))

Orange/data/tests/test_util.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from Orange.data import Domain, ContinuousVariable
44
from Orange.data.util import get_unique_names, get_unique_names_duplicates, \
5-
get_unique_names_domain, progress_callback
5+
get_unique_names_domain
66

77

88
class TestGetUniqueNames(unittest.TestCase):
@@ -115,21 +115,5 @@ def test_get_unique_names_domain(self):
115115
self.assertEqual(renamed, [])
116116

117117

118-
class TestProgressCallback(unittest.TestCase):
119-
def test_wrap(self):
120-
def func(i):
121-
return i
122-
123-
f = progress_callback(func, start=0, end=0.8)
124-
self.assertEqual(f(0), 0)
125-
self.assertEqual(round(f(0.1), 2), 0.08)
126-
self.assertEqual(f(1), 0.8)
127-
128-
f = progress_callback(func, start=0.1, end=0.8)
129-
self.assertEqual(f(0), 0.1)
130-
self.assertEqual(f(0.1), 0.17)
131-
self.assertEqual(f(1), 0.8)
132-
133-
134118
if __name__ == "__main__":
135119
unittest.main()

Orange/data/util.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import re
55
from collections import Counter, defaultdict
66
from itertools import chain
7-
from functools import wraps
87

98
import numpy as np
109
import bottleneck as bn
@@ -251,26 +250,3 @@ def get_unique_names_domain(attributes, class_vars=(), metas=()):
251250
for old, new in zip(all_names, unique_names)
252251
if new != old))
253252
return (attributes, class_vars, metas), renamed
254-
255-
256-
def progress_callback(callback, start=0, end=1):
257-
"""
258-
Wraps a callback function to allocate it end-start proportion of
259-
the progress.
260-
261-
:param callback: callable
262-
:param start: float
263-
:param end: float
264-
:return: callable
265-
"""
266-
@wraps(callback)
267-
def func(i, *args, **kwargs):
268-
x = start + i * (end - start)
269-
return callback(x, *args, **kwargs)
270-
return func
271-
272-
273-
def dummy_callback(*_, **__):
274-
""" A dummy callable. """
275-
return 1
276-

Orange/modelling/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ def _fit_model(self, data):
4141
X, Y, W = data.X, data.Y, data.W if data.has_weights() else None
4242
return learner.fit(X, Y, W)
4343

44-
def preprocess(self, data, callback=None):
45-
return self.get_learner(data).preprocess(data, callback)
44+
def preprocess(self, data, progress_callback=None):
45+
return self.get_learner(data).preprocess(data, progress_callback)
4646

4747
def get_learner(self, problem_type):
4848
"""Get the learner for a given problem type.

Orange/tests/test_util.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from Orange.data.util import vstack, hstack, array_equal
1212
from Orange.statistics.util import stats
1313
from Orange.tests.test_statistics import dense_sparse
14+
from Orange.util import wrap_callback
1415

1516
SOMETHING = 0xf00babe
1617

@@ -158,3 +159,21 @@ def test_csc_unordered_array_equal(self):
158159
a1 = sp.csc_matrix(([1, 4, 5], [0, 0, 1], [0, 1, 1, 3]), shape=(2, 3))
159160
a2 = sp.csc_matrix(([1, 5, 4], [0, 1, 0], [0, 1, 1, 3]), shape=(2, 3))
160161
self.assertTrue(array_equal(a1, a2))
162+
163+
def test_wrap_callback(self):
164+
def func(i):
165+
return i
166+
167+
f = wrap_callback(func, start=0, end=0.8)
168+
self.assertEqual(f(0), 0)
169+
self.assertEqual(round(f(0.1), 2), 0.08)
170+
self.assertEqual(f(1), 0.8)
171+
172+
f = wrap_callback(func, start=0.1, end=0.8)
173+
self.assertEqual(f(0), 0.1)
174+
self.assertEqual(f(0.1), 0.17)
175+
self.assertEqual(f(1), 0.8)
176+
177+
178+
if __name__ == "__main__":
179+
unittest.main()

Orange/util.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,29 @@ def __repr__(self):
416416
name, ", ".join("{}={!r}".format(f, v) for f, _, v in self._reprable_items())
417417
)
418418

419+
420+
def wrap_callback(progress_callback, start=0, end=1):
421+
"""
422+
Wraps a progress callback function to allocate it end-start proportion
423+
of an execution time.
424+
425+
:param progress_callback: callable
426+
:param start: float
427+
:param end: float
428+
:return: callable
429+
"""
430+
@wraps(progress_callback)
431+
def func(progress, *args, **kwargs):
432+
adjusted_progress = start + progress * (end - start)
433+
return progress_callback(adjusted_progress, *args, **kwargs)
434+
return func
435+
436+
437+
def dummy_callback(*_, **__):
438+
""" A dummy callable. """
439+
return 1
440+
441+
419442
# For best result, keep this at the bottom
420443
__all__ = export_globals(globals(), __name__)
421444

Orange/widgets/data/owoutliers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from Orange.classification import OneClassSVMLearner, EllipticEnvelopeLearner,\
1313
LocalOutlierFactorLearner, IsolationForestLearner
1414
from Orange.data import Table
15-
from Orange.data.util import progress_callback
15+
from Orange.util import wrap_callback
1616
from Orange.widgets import gui
1717
from Orange.widgets.settings import Setting
1818
from Orange.widgets.utils.concurrent import TaskState, ConcurrentWidgetMixin
@@ -40,8 +40,8 @@ def callback(i: float, status=""):
4040
raise Exception
4141

4242
callback(0, "Initializing...")
43-
model = learner(data, progress_callback(callback, end=0.6))
44-
pred = model(data, progress_callback(callback, start=0.6, end=0.99))
43+
model = learner(data, wrap_callback(callback, end=0.6))
44+
pred = model(data, wrap_callback(callback, start=0.6, end=0.99))
4545

4646
col = pred.get_column_view(model.outlier_var)[0]
4747
inliers_ind = np.where(col == 1)[0]

0 commit comments

Comments
 (0)