diff --git a/conda/meta.yaml b/conda/meta.yaml index 1f1c559fd..6b40efbf9 100644 --- a/conda/meta.yaml +++ b/conda/meta.yaml @@ -24,15 +24,15 @@ requirements: run: - python >=3.8 - numpy >=1.20.0 - - orange3 >=3.32.0 - - orange-canvas-core >=0.1.24 - - orange-widget-base >=4.16.1 - - scipy >=1.4.0 + - orange3 >=3.34.0 + - orange-canvas-core >=0.1.28 + - orange-widget-base >=4.19.0 + - scipy >=1.9.0 - scikit-learn>=1.0.1 - spectral >=0.22.3,!=0.23 - serverfiles >=0.2 - - AnyQt >=0.0.6 - - pyqtgraph >=0.11.1,!=0.12.4 + - AnyQt >=0.1.0 + - pyqtgraph >=0.12.2,!=0.12.4 - colorcet - h5py - extranormal3 >=0.0.3 diff --git a/orangecontrib/spectroscopy/preprocess/__init__.py b/orangecontrib/spectroscopy/preprocess/__init__.py index 5895e261b..f23c22211 100644 --- a/orangecontrib/spectroscopy/preprocess/__init__.py +++ b/orangecontrib/spectroscopy/preprocess/__init__.py @@ -29,7 +29,7 @@ class PCADenoisingFeature(SelectColumn): - pass + InheritEq = True class _PCAReconstructCommon(CommonDomain): @@ -79,7 +79,7 @@ def __call__(self, data): class GaussianFeature(SelectColumn): - pass + InheritEq = True class _GaussianCommon(CommonDomainOrderUnknowns): @@ -131,7 +131,7 @@ def __call__(self, data): class SavitzkyGolayFeature(SelectColumn): - pass + InheritEq = True class _SavitzkyGolayCommon(CommonDomainOrderUnknowns): @@ -147,6 +147,15 @@ def transformed(self, X, wavenumbers): polyorder=self.polyorder, deriv=self.deriv, mode="nearest") + def __eq__(self, other): + return super().__eq__(other) \ + and self.window == other.window \ + and self.polyorder == other.polyorder \ + and self.deriv == other.deriv + + def __hash__(self): + return hash((super().__hash__(), self.window, self.polyorder, self.deriv)) + class SavitzkyGolayFiltering(Preprocess): """ @@ -169,7 +178,7 @@ def __call__(self, data): class RubberbandBaselineFeature(SelectColumn): - pass + InheritEq = True class _RubberbandBaselineCommon(CommonDomainOrder): @@ -233,7 +242,7 @@ def __call__(self, data): class LinearBaselineFeature(SelectColumn): - pass + InheritEq = True class _LinearBaselineCommon(CommonDomainOrderUnknowns): @@ -276,7 +285,7 @@ def __call__(self, data): class NormalizeFeature(SelectColumn): - pass + InheritEq = True class _NormalizeCommon(CommonDomain): @@ -333,6 +342,18 @@ def transformed(self, data): replace_infs(data.X) return data.X + def __eq__(self, other): + return super().__eq__(other) \ + and self.method == other.method \ + and self.lower == other.lower \ + and self.upper == other.upper \ + and self.int_method == other.int_method \ + and self.attr == other.attr + + def __hash__(self): + return hash((super().__hash__(), self.method, self.lower, + self.upper, self.int_method, self.attr)) + class Normalize(Preprocess): # Normalization methods @@ -412,7 +433,7 @@ def features_with_interpolation(points, kind="linear", domain=None, handle_nans= class InterpolatedFeature(SelectColumn): - pass + InheritEq = True class _InterpolateCommon: @@ -449,6 +470,18 @@ def __call__(self, data): interpfn = interp1d_wo_unknowns_scipy return interpfn(x, ys, self.points, kind=self.kind) + def __eq__(self, other): + return type(self) is type(other) \ + and np.all(self.points == other.points) \ + and self.kind == other.kind \ + and self.domain == other.domain \ + and self.handle_nans == other.handle_nans \ + and self.interpfn == other.interpfn + + def __hash__(self): + return hash((type(self), tuple(self.points[:5]), self.kind, + self.domain, self.handle_nans, self.interpfn)) + class Interpolate(Preprocess): """ @@ -512,7 +545,7 @@ def __call__(self, data): ######################################### XAS normalization ########## class XASnormalizationFeature(SelectColumn): - pass + InheritEq = True class _XASnormalizationCommon(CommonDomainOrderUnknowns): @@ -574,7 +607,7 @@ class NoEdgejumpProvidedException(PreprocessException): class ExtractEXAFSFeature(SelectColumn): - pass + InheritEq = True class EdgeJumpException(PreprocessException): @@ -698,7 +731,7 @@ def __call__(self, data): class CurveShiftFeature(SelectColumn): - pass + InheritEq = True class _CurveShiftCommon(CommonDomain): @@ -726,7 +759,7 @@ def __call__(self, data): class DespikeFeature(SelectColumn): - pass + InheritEq = True class _DespikeCommon(CommonDomainOrderUnknowns): @@ -804,7 +837,7 @@ def __call__(self, data): class SpSubtractFeature(SelectColumn): - pass + InheritEq = True class _SpSubtractCommon(CommonDomainRef): diff --git a/orangecontrib/spectroscopy/preprocess/als/__init__.py b/orangecontrib/spectroscopy/preprocess/als/__init__.py index 6ebf2d89d..46ad912ce 100644 --- a/orangecontrib/spectroscopy/preprocess/als/__init__.py +++ b/orangecontrib/spectroscopy/preprocess/als/__init__.py @@ -11,7 +11,7 @@ class ALSFeature(SelectColumn): - pass + InheritEq = True class ALSCommon(CommonDomainOrderUnknowns): @@ -54,7 +54,7 @@ def __call__(self, data): class ARPLSFeature(SelectColumn): - pass + InheritEq = True class ARPLSCommon(CommonDomainOrderUnknowns): @@ -100,7 +100,7 @@ def __call__(self, data): class AIRPLSFeature(SelectColumn): - pass + InheritEq = True class AIRPLSCommon(CommonDomainOrderUnknowns): diff --git a/orangecontrib/spectroscopy/preprocess/emsc.py b/orangecontrib/spectroscopy/preprocess/emsc.py index 57ffc4aae..6c7ffefb6 100644 --- a/orangecontrib/spectroscopy/preprocess/emsc.py +++ b/orangecontrib/spectroscopy/preprocess/emsc.py @@ -54,11 +54,11 @@ def weighted_wavenumbers(weights, wavenumbers): class EMSCFeature(SelectColumn): - pass + InheritEq = True class EMSCModel(SelectColumn): - pass + InheritEq = True class _EMSC(CommonDomainOrderUnknowns): diff --git a/orangecontrib/spectroscopy/preprocess/integrate.py b/orangecontrib/spectroscopy/preprocess/integrate.py index 59f0b09bd..18061c0b7 100644 --- a/orangecontrib/spectroscopy/preprocess/integrate.py +++ b/orangecontrib/spectroscopy/preprocess/integrate.py @@ -72,17 +72,25 @@ def compute(self, data, common): x_s, y_s = self.extract_data(data, common) return self.compute_integral(x_s, y_s) + def __eq__(self, other): + return super().__eq__(other) \ + and self.limits == other.limits + + def __hash__(self): + return hash((super().__hash__(), tuple(self.limits))) + class IntegrateFeatureEdgeBaseline(IntegrateFeature): """ A linear edge-to-edge baseline subtraction. """ name = "Integral from baseline" + InheritEq = True @staticmethod def parameters(): return (("Low limit", "Low limit for integration (inclusive)"), ("High limit", "High limit for integration (inclusive)"), - ) + ) def compute_baseline(self, x, y): if np.any(np.isnan(y)): @@ -105,6 +113,7 @@ def compute_draw_info(self, x, ys): class IntegrateFeatureSeparateBaseline(IntegrateFeature): name = "Integral from separate baseline" + InheritEq = True @staticmethod def parameters(): @@ -148,6 +157,7 @@ class IntegrateFeatureSimple(IntegrateFeatureEdgeBaseline): """ A simple y=0 integration on the provided data window. """ name = "Integral from 0" + InheritEq = True def compute_baseline(self, x_s, y_s): return np.zeros(y_s.shape) @@ -157,12 +167,13 @@ class IntegrateFeaturePeakEdgeBaseline(IntegrateFeature): """ The maximum baseline-subtracted peak height in the provided window. """ name = "Peak from baseline" + InheritEq = True @staticmethod def parameters(): return (("Low limit", "Low limit for integration (inclusive)"), ("High limit", "High limit for integration (inclusive)"), - ) + ) def compute_baseline(self, x, y): return edge_baseline(x, y) @@ -186,6 +197,7 @@ class IntegrateFeaturePeakSimple(IntegrateFeaturePeakEdgeBaseline): """ The maximum peak height in the provided data window. """ name = "Peak from 0" + InheritEq = True def compute_baseline(self, x_s, y_s): return np.zeros(y_s.shape) @@ -195,12 +207,13 @@ class IntegrateFeaturePeakXEdgeBaseline(IntegrateFeature): """ The X-value of the maximum baseline-subtracted peak height in the provided window. """ name = "X-value of maximum from baseline" + InheritEq = True @staticmethod def parameters(): return (("Low limit", "Low limit for integration (inclusive)"), ("High limit", "High limit for integration (inclusive)"), - ) + ) def compute_baseline(self, x, y): return edge_baseline(x, y) @@ -231,6 +244,7 @@ class IntegrateFeaturePeakXSimple(IntegrateFeaturePeakXEdgeBaseline): """ The X-value of the maximum peak height in the provided data window. """ name = "X-value of maximum from 0" + InheritEq = True def compute_baseline(self, x_s, y_s): return np.zeros(y_s.shape) @@ -240,11 +254,12 @@ class IntegrateFeatureAtPeak(IntegrateFeature): """ Find the closest x and return the value there. """ name = "Closest value" + InheritEq = True @staticmethod def parameters(): return (("Closest to", "Nearest value"), - ) + ) def extract_data(self, data, common): data, x, x_sorter = common @@ -275,6 +290,14 @@ def transformed(self, data): x_sorter = np.argsort(x) return data, x, x_sorter + def __eq__(self, other): + # pylint: disable=useless-parent-delegation + return super().__eq__(other) + + def __hash__(self): + # pylint: disable=useless-parent-delegation + return super().__hash__() + class Integrate(Preprocess): diff --git a/orangecontrib/spectroscopy/preprocess/me_emsc.py b/orangecontrib/spectroscopy/preprocess/me_emsc.py index a75dde8bd..eb8eaa244 100644 --- a/orangecontrib/spectroscopy/preprocess/me_emsc.py +++ b/orangecontrib/spectroscopy/preprocess/me_emsc.py @@ -88,11 +88,11 @@ def cal_ncomp(reference, wavenumbers, explainedVarLim, alpha0, gamma): class ME_EMSCFeature(SelectColumn): - pass + InheritEq = True class ME_EMSCModel(SelectColumn): - pass + InheritEq = True class _ME_EMSC(CommonDomainOrderUnknowns): diff --git a/orangecontrib/spectroscopy/preprocess/transform.py b/orangecontrib/spectroscopy/preprocess/transform.py index d330df68e..89ba8c212 100644 --- a/orangecontrib/spectroscopy/preprocess/transform.py +++ b/orangecontrib/spectroscopy/preprocess/transform.py @@ -19,7 +19,7 @@ class SpecTypes(Enum): class AbsorbanceFeature(SelectColumn): - pass + InheritEq = True class _AbsorbanceCommon(CommonDomainRef): @@ -40,6 +40,14 @@ def transformed(self, data): # Replace infs from either np.true_divide or np.log10 return replace_infs(absd) + def __eq__(self, other): + # pylint: disable=useless-parent-delegation + return super().__eq__(other) + + def __hash__(self): + # pylint: disable=useless-parent-delegation + return super().__hash__() + class TransformOptionalReference(Preprocess): @@ -76,7 +84,7 @@ class Absorbance(TransformOptionalReference): class TransmittanceFeature(SelectColumn): - pass + InheritEq = True class _TransmittanceCommon(CommonDomainRef): @@ -97,6 +105,14 @@ def transformed(self, data): # Replace infs from either np.true_divide or np.log10 return replace_infs(transd) + def __eq__(self, other): + # pylint: disable=useless-parent-delegation + return super().__eq__(other) + + def __hash__(self): + # pylint: disable=useless-parent-delegation + return super().__hash__() + class Transmittance(TransformOptionalReference): """ diff --git a/orangecontrib/spectroscopy/preprocess/utils.py b/orangecontrib/spectroscopy/preprocess/utils.py index 863513baa..000c55984 100644 --- a/orangecontrib/spectroscopy/preprocess/utils.py +++ b/orangecontrib/spectroscopy/preprocess/utils.py @@ -1,3 +1,5 @@ +from typing import Optional + import numpy as np from Orange.data import Table, Domain from Orange.data.util import SharedComputeValue @@ -52,13 +54,20 @@ def __init__(self, feature, commonfn): def compute(self, data, common): return common[:, self.feature] + def __eq__(self, other): + return super().__eq__(other) \ + and self.feature == other.feature + + def __hash__(self): + return hash((super().__hash__(), self.feature)) + class CommonDomain: """A utility class that helps constructing common transformation for SharedComputeValue features. It does the domain transformation (input domain needs to be the same as it was with training data). """ - def __init__(self, domain): + def __init__(self, domain: Domain): self.domain = domain def __call__(self, data): @@ -73,14 +82,21 @@ def transform_domain(self, data): def transformed(self, data): raise NotImplemented + def __eq__(self, other): + return type(self) is type(other) \ + and self.domain == other.domain + + def __hash__(self): + return hash((type(self), self.domain)) + class CommonDomainRef(CommonDomain): """CommonDomain which also ensures reference domain transformation""" - def __init__(self, reference, domain): + def __init__(self, reference: Table, domain: Domain): super().__init__(domain) self.reference = reference - def interpolate_extend_to(self, interpolate, wavenumbers): + def interpolate_extend_to(self, interpolate: Table, wavenumbers): """ Interpolate data to given wavenumbers and extend the possibly nan-edges with the nearest values. @@ -91,6 +107,14 @@ def interpolate_extend_to(self, interpolate, wavenumbers): X, _ = nan_extend_edges_and_interpolate(wavenumbers, X) return X + def __eq__(self, other): + return super().__eq__(other) \ + and reference_eq_X(self.reference, other.reference) + + def __hash__(self): + domain = self.reference.domain if self.reference is not None else None + return hash((super().__hash__(), domain)) + class CommonDomainOrder(CommonDomain): """CommonDomain + it also handles wavenumber order. @@ -116,6 +140,14 @@ def _restore_order(self, X, mon, xsind, xc): def transformed(self, X, wavenumbers): raise NotImplemented + def __eq__(self, other): + # pylint: disable=useless-parent-delegation + return super().__eq__(other) + + def __hash__(self): + # pylint: disable=useless-parent-delegation + return super().__hash__() + class CommonDomainOrderUnknowns(CommonDomainOrder): """CommonDomainOrder + it also handles unknown values: it interpolates @@ -152,6 +184,24 @@ def __call__(self, data): # restore order return self._restore_order(X, mon, xsind, xc) + def __eq__(self, other): + # pylint: disable=useless-parent-delegation + return super().__eq__(other) + + def __hash__(self): + # pylint: disable=useless-parent-delegation + return super().__hash__() + + +def reference_eq_X(first: Optional[Table], second: Optional[Table]): + if first is second: + return True + elif first is None or second is None: + return False + else: + return first.domain.attributes == second.domain.attributes \ + and np.array_equal(first.X, second.X) + def nan_extend_edges_and_interpolate(xs, X): """ diff --git a/orangecontrib/spectroscopy/tests/test_integrate.py b/orangecontrib/spectroscopy/tests/test_integrate.py index ca5c621bf..1c3cb53b5 100644 --- a/orangecontrib/spectroscopy/tests/test_integrate.py +++ b/orangecontrib/spectroscopy/tests/test_integrate.py @@ -148,3 +148,24 @@ def test_metas_output(self): self.assertTrue("0 - 5" in metavars and "0 - 6" in metavars) self.assertEqual(i[0]["0 - 5"], 8) self.assertEqual(i[0]["0 - 6"], 3) + + def test_eq(self): + data = Table.from_numpy(None, [[1, 2, 3, 1, 1, 1]]) + i1 = Integrate(methods=Integrate.Simple, limits=[[0, 5]])(data) + i2 = Integrate(methods=Integrate.Simple, limits=[[0, 6]])(data) + self.assertNotEqual(i1.domain[0], i2.domain[0]) + i3 = Integrate(methods=Integrate.Simple, limits=[[0, 6], [0, 5]])(data) + self.assertNotEqual(i1.domain[0], i3.domain[0]) + self.assertEqual(i1.domain[0], i3.domain[1]) + i4 = Integrate(methods=Integrate.Baseline, limits=[[0, 5]])(data) + self.assertNotEqual(i1.domain[0], i4.domain[0]) + + # different domain should mean different integrals + data2 = Table.from_numpy(None, [[1, 2, 3, 1, 1, 1, 1]]) + ii1 = Integrate(methods=Integrate.Simple, limits=[[0, 5]])(data2) + self.assertNotEqual(i1.domain[0], ii1.domain[0]) + + # same domain -> same integrals + data3 = Table.from_numpy(None, [[1, 2, 3, 22, 1, 2]]) + iii1 = Integrate(methods=Integrate.Simple, limits=[[0, 5]])(data3) + self.assertEqual(i1.domain[0], iii1.domain[0]) diff --git a/orangecontrib/spectroscopy/tests/test_interpolate.py b/orangecontrib/spectroscopy/tests/test_interpolate.py index 444e3044f..f0e2aaf96 100644 --- a/orangecontrib/spectroscopy/tests/test_interpolate.py +++ b/orangecontrib/spectroscopy/tests/test_interpolate.py @@ -179,6 +179,21 @@ def test_nan_extend_edges_and_interpolate_mixed(self): v, n = nan_extend_edges_and_interpolate(xsm, ysm) np.testing.assert_equal(v[:, mix], exp) + def test_eq(self): + data = Orange.data.Table("iris") + i1 = Interpolate([0, 1])(data) + i2 = Interpolate([0, 1])(data) + self.assertEqual(i1.domain, i2.domain) + i3 = Interpolate([0, 1.1])(data) + self.assertNotEqual(i1.domain[0], i3.domain[0]) + i4 = Interpolate([0, 1], kind="quadratic")(data) + self.assertNotEqual(i1.domain[0], i4.domain[0]) + + # different domain + titanic = Orange.data.Table("titanic") + it1 = Interpolate([0, 1])(titanic) + self.assertNotEqual(i1.domain[0], it1.domain[0]) + class TestInterpolateToDomain(unittest.TestCase): diff --git a/orangecontrib/spectroscopy/tests/test_preprocess.py b/orangecontrib/spectroscopy/tests/test_preprocess.py index 59d3b87c6..99e1062b5 100644 --- a/orangecontrib/spectroscopy/tests/test_preprocess.py +++ b/orangecontrib/spectroscopy/tests/test_preprocess.py @@ -202,6 +202,22 @@ def test_roundtrip(self): calcdata = Absorbance()(Transmittance()(data)) np.testing.assert_allclose(data.X, calcdata.X) + def test_eq(self): + data = SMALL_COLLAGEN + t1 = Transmittance()(data) + t2 = Transmittance()(data) + self.assertEqual(t1.domain, t2.domain) + data2 = Table.from_numpy(None, [[1.0, 2.0, 3.0, 4.0]]) + t3 = Transmittance()(data2) + self.assertNotEqual(t1.domain, t3.domain) + t4 = Transmittance(reference=data2)(data) + self.assertNotEqual(t1.domain, t4.domain) + t5 = Transmittance(reference=data2)(data[:1]) + self.assertGreater(len(t4), len(t5)) + self.assertEqual(t4.domain, t5.domain) + a = Absorbance()(data) + self.assertNotEqual(a.domain, t1.domain) + class TestAbsorbance(unittest.TestCase): @@ -221,6 +237,20 @@ def test_roundtrip(self): calcdata = Transmittance()(Absorbance()(data)) np.testing.assert_allclose(data.X, calcdata.X) + def test_eq(self): + data = SMALL_COLLAGEN + t1 = Absorbance()(data) + t2 = Absorbance()(data) + self.assertEqual(t1.domain, t2.domain) + data2 = Table.from_numpy(None, [[1.0, 2.0, 3.0, 4.0]]) + t3 = Absorbance()(data2) + self.assertNotEqual(t1.domain, t3.domain) + t4 = Absorbance(reference=data2)(data) + self.assertNotEqual(t1.domain, t4.domain) + t5 = Absorbance(reference=data2)(data[:1]) + self.assertGreater(len(t4), len(t5)) + self.assertEqual(t4.domain, t5.domain) + class TestSavitzkyGolay(unittest.TestCase): @@ -242,6 +272,24 @@ def test_simple(self): np.testing.assert_almost_equal(fdata.X, [[4.86857143, 3.47428571, 1.49428571, 0.32857143]]) + def test_eq(self): + data = Table.from_numpy(None, [[2, 1, 2, 2, 3]]) + p1 = SavitzkyGolayFiltering(window=5, polyorder=2, deriv=0)(data) + p2 = SavitzkyGolayFiltering(window=5, polyorder=2, deriv=1)(data) + p3 = SavitzkyGolayFiltering(window=5, polyorder=3, deriv=0)(data) + p4 = SavitzkyGolayFiltering(window=7, polyorder=2, deriv=0)(data) + self.assertNotEqual(p1.domain, p2.domain) + self.assertNotEqual(p1.domain, p3.domain) + self.assertNotEqual(p1.domain, p4.domain) + + s1 = SavitzkyGolayFiltering(window=5, polyorder=2, deriv=0)(data) + self.assertEqual(p1.domain, s1.domain) + + # even if the data set is different features should be the same + data2 = Table.from_numpy(None, [[2, 1, 3, 4, 3]]) + s2 = SavitzkyGolayFiltering(window=5, polyorder=2, deriv=0)(data2) + self.assertEqual(p1.domain, s2.domain) + class TestGaussian(unittest.TestCase): @@ -399,6 +447,26 @@ def test_SNV_norm(self): p = Normalize(method=Normalize.SNV, lower=0, upper=2)(data) np.testing.assert_equal(p.X, q) + def test_eq(self): + data = Table.from_numpy(None, [[2, 1, 2, 2, 3]]) + p1 = Normalize(method=Normalize.MinMax)(data) + p2 = Normalize(method=Normalize.SNV)(data) + p3 = Normalize(method=Normalize.MinMax)(data) + self.assertNotEqual(p1.domain, p2.domain) + self.assertEqual(p1.domain, p3.domain) + + p1 = Normalize(method=Normalize.Area, int_method=Integrate.PeakMax, + lower=0, upper=4)(data) + p2 = Normalize(method=Normalize.Area, int_method=Integrate.Baseline, + lower=0, upper=4)(data) + p3 = Normalize(method=Normalize.Area, int_method=Integrate.PeakMax, + lower=1, upper=4)(data) + p4 = Normalize(method=Normalize.Area, int_method=Integrate.PeakMax, + lower=0, upper=4)(data) + self.assertNotEqual(p1.domain, p2.domain) + self.assertNotEqual(p1.domain, p3.domain) + self.assertEqual(p1.domain, p4.domain) + class TestNormalizeReference(unittest.TestCase): diff --git a/orangecontrib/spectroscopy/tests/test_preprocess_utils.py b/orangecontrib/spectroscopy/tests/test_preprocess_utils.py new file mode 100644 index 000000000..884eeb1bf --- /dev/null +++ b/orangecontrib/spectroscopy/tests/test_preprocess_utils.py @@ -0,0 +1,27 @@ +from unittest import TestCase + +from Orange.data import Table + +from orangecontrib.spectroscopy.preprocess.utils import reference_eq_X + + +class TestEq(TestCase): + + @classmethod + def setUpClass(cls): + cls.iris = Table("iris") + cls.iris2 = Table("iris") + cls.iris_changed = Table("iris") + with cls.iris_changed.unlocked(): + cls.iris_changed[0][0] = 42 + + def test_reference_eq_X_none(self): + data = self.iris + self.assertTrue(reference_eq_X(None, None)) + self.assertFalse(reference_eq_X(data, None)) + self.assertFalse(reference_eq_X(None, data)) + + def test_reference_eq_X_same(self): + self.assertTrue(reference_eq_X(self.iris, self.iris)) + self.assertTrue(reference_eq_X(self.iris, self.iris2)) + self.assertFalse(reference_eq_X(self.iris, self.iris_changed)) diff --git a/setup.py b/setup.py index 1b8a2aadf..99f5da8c6 100644 --- a/setup.py +++ b/setup.py @@ -128,15 +128,15 @@ def include_documentation(local_dir, install_dir): 'setuptools>=36.3', # same as for Orange 3.28 'pip>=9.0', # same as for Orange 3.28 'numpy>=1.20.0', - 'Orange3>=3.32.0', - 'orange-canvas-core>=0.1.24', - 'orange-widget-base>=4.16.1', - 'scipy>=1.4.0', + 'Orange3>=3.34.0', + 'orange-canvas-core>=0.1.28', + 'orange-widget-base>=4.19.0', + 'scipy>=1.9.0', 'scikit-learn>=1.0.1', 'spectral>=0.22.3,!=0.23', 'serverfiles>=0.2', - 'AnyQt>=0.0.6', - 'pyqtgraph>=0.11.1,!=0.12.4', # https://github.com/pyqtgraph/pyqtgraph/issues/2237 + 'AnyQt>=0.1.0', + 'pyqtgraph>=0.12.2,!=0.12.4', # https://github.com/pyqtgraph/pyqtgraph/issues/2237 'colorcet', 'h5py', 'extranormal3 >=0.0.3', diff --git a/tox.ini b/tox.ini index 7c86b8dad..9e59a56a4 100644 --- a/tox.ini +++ b/tox.ini @@ -23,13 +23,13 @@ setenv = deps = pyqt5==5.12.* pyqtwebengine==5.12.* - oldest: orange3==3.32.0 - oldest: orange-canvas-core==0.1.24 - oldest: orange-widget-base==4.16.1 + oldest: orange3==3.34.0 + oldest: orange-canvas-core==0.1.28 + oldest: orange-widget-base==4.19.0 oldest: scikit-learn~=1.0.1 oldest: numpy~=1.20.0 - oldest: pyqtgraph==0.11.1 - oldest: scipy~=1.4.0 + oldest: pyqtgraph==0.12.2 + oldest: scipy~=1.9.0 oldest: pandas~=1.3.0 oldest: spectral~=0.22.3 oldest: lmfit~=1.0.2