{
    "file_diffs": [
        {
            "old_file_content": "\"\"\"\nPreprocess\n----------\n\n\"\"\"\nimport numpy as np\nimport bottleneck as bn\nimport scipy.sparse as sp\nfrom sklearn.impute import SimpleImputer\n\nimport Orange.data\nfrom Orange.data.filter import HasClass\nfrom Orange.statistics import distribution\nfrom Orange.util import Reprable, Enum, deprecated\nfrom . import impute, discretize, transformation\n\n__all__ = [\"Continuize\", \"Discretize\", \"Impute\", \"RemoveNaNRows\",\n           \"SklImpute\", \"Normalize\", \"Randomize\", \"Preprocess\",\n           \"RemoveConstant\", \"RemoveNaNClasses\", \"RemoveNaNColumns\",\n           \"ProjectPCA\", \"ProjectCUR\", \"Scale\", \"RemoveSparse\",\n           \"AdaptiveNormalize\"]\n\n\nclass Preprocess(Reprable):\n    \"\"\"\n    A generic preprocessor base class.\n\n    Methods\n    -------\n    __call__(data: Table) -> Table\n        Return preprocessed data.\n    \"\"\"\n    def __call__(self, data):\n        raise NotImplementedError(\"Subclasses need to implement __call__\")\n\n\nclass Continuize(Preprocess):\n    MultinomialTreatment = Enum(\n        \"Continuize\",\n        (\"Indicators\", \"FirstAsBase\", \"FrequentAsBase\", \"Remove\",\n         \"RemoveMultinomial\", \"ReportError\", \"AsOrdinal\", \"AsNormalizedOrdinal\",\n         \"Leave\"),\n        qualname=\"Continuize.MultinomialTreatment\")\n    (Indicators, FirstAsBase, FrequentAsBase, Remove, RemoveMultinomial,\n     ReportError, AsOrdinal, AsNormalizedOrdinal, Leave) = MultinomialTreatment\n\n    def __init__(self, zero_based=True,\n                 multinomial_treatment=Indicators):\n        self.zero_based = zero_based\n        self.multinomial_treatment = multinomial_treatment\n\n    def __call__(self, data):\n        from . import continuize\n\n        continuizer = continuize.DomainContinuizer(\n            zero_based=self.zero_based,\n            multinomial_treatment=self.multinomial_treatment)\n        domain = continuizer(data)\n        return data.transform(domain)\n\n\nclass Discretize(Preprocess):\n    \"\"\"\n    Construct a discretizer, a preprocessor for discretization of\n    continuous features.\n\n    Parameters\n    ----------\n    method : discretization method (default: Orange.preprocess.discretize.Discretization)\n\n    remove_const : bool (default=True)\n        Determines whether the features with constant values are removed\n        during discretization.\n    \"\"\"\n\n    def __init__(self, method=None, remove_const=True,\n                 discretize_classes=False, discretize_metas=False):\n        self.method = method\n        self.remove_const = remove_const\n        self.discretize_classes = discretize_classes\n        self.discretize_metas = discretize_metas\n\n    def __call__(self, data):\n        \"\"\"\n        Compute and apply discretization of the given data. Returns a new\n        data table.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            A data table to be discretized.\n        \"\"\"\n\n        def transform(var):\n            if var.is_continuous:\n                new_var = method(data, var)\n                if new_var is not None and \\\n                        (len(new_var.values) >= 2 or not self.remove_const):\n                    return new_var\n                else:\n                    return None\n            else:\n                return var\n\n        def discretized(vars_, do_discretize):\n            if do_discretize:\n                vars_ = (transform(var) for var in vars_)\n                vars_ = [var for var in vars_ if var is not None]\n            return vars_\n\n        method = self.method or discretize.EqualFreq()\n        domain = Orange.data.Domain(\n            discretized(data.domain.attributes, True),\n            discretized(data.domain.class_vars, self.discretize_classes),\n            discretized(data.domain.metas, self.discretize_metas))\n        return data.transform(domain)\n\n\nclass Impute(Preprocess):\n    \"\"\"\n    Construct a imputer, a preprocessor for imputation of missing values in\n    the data table.\n\n    Parameters\n    ----------\n    method : imputation method (default: Orange.preprocess.impute.Average())\n    \"\"\"\n\n    def __init__(self, method=Orange.preprocess.impute.Average()):\n        self.method = method\n\n    def __call__(self, data):\n        \"\"\"\n        Apply an imputation method to the given dataset. Returns a new\n        data table with missing values replaced by their imputations.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            An input data table.\n        \"\"\"\n\n        method = self.method or impute.Average()\n        newattrs = [method(data, var) for var in data.domain.attributes]\n        domain = Orange.data.Domain(\n            newattrs, data.domain.class_vars, data.domain.metas)\n        return data.transform(domain)\n\n\nclass SklImpute(Preprocess):\n    __wraps__ = SimpleImputer\n\n    def __init__(self, strategy='mean'):\n        self.strategy = strategy\n\n    def __call__(self, data):\n        from Orange.data.sql.table import SqlTable\n        if isinstance(data, SqlTable):\n            return Impute()(data)\n        imputer = SimpleImputer(strategy=self.strategy)\n        X = imputer.fit_transform(data.X)\n        # Create new variables with appropriate `compute_value`, but\n        # drop the ones which do not have valid `imputer.statistics_`\n        # (i.e. all NaN columns). `sklearn.preprocessing.Imputer` already\n        # drops them from the transformed X.\n        features = [impute.Average()(data, var, value)\n                    for var, value in zip(data.domain.attributes,\n                                          imputer.statistics_)\n                    if not np.isnan(value)]\n        assert X.shape[1] == len(features)\n        domain = Orange.data.Domain(features, data.domain.class_vars,\n                                    data.domain.metas)\n        new_data = data.transform(domain)\n        new_data.X = X\n        return new_data\n\n\nclass RemoveConstant(Preprocess):\n    \"\"\"\n    Construct a preprocessor that removes features with constant values\n    from the dataset.\n    \"\"\"\n\n    def __call__(self, data):\n        \"\"\"\n        Remove columns with constant values from the dataset and return\n        the resulting data table.\n\n        Parameters\n        ----------\n        data : an input dataset\n        \"\"\"\n\n        oks = np.logical_and(~bn.allnan(data.X, axis=0),\n                             bn.nanmin(data.X, axis=0) != bn.nanmax(data.X, axis=0))\n        atts = [data.domain.attributes[i] for i, ok in enumerate(oks) if ok]\n        domain = Orange.data.Domain(atts, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\nclass RemoveNaNRows(Preprocess):\n    _reprable_module = True\n\n    def __call__(self, data):\n        mask = np.isnan(data.X)\n        mask = np.any(mask, axis=1)\n        return data[~mask]\n\n\nclass RemoveNaNColumns(Preprocess):\n    \"\"\"\n    Remove features from the data domain if they contain\n    `threshold` or more unknown values.\n\n    `threshold` can be an integer or a float in the range (0, 1) representing\n    the fraction of the data size. When not provided, columns with only missing\n    values are removed (default).\n    \"\"\"\n    def __init__(self, threshold=None):\n        self.threshold = threshold\n\n    def __call__(self, data, threshold=None):\n        # missing entries in sparse data are treated as zeros so we skip removing NaNs\n        if sp.issparse(data.X):\n            return data\n\n        if threshold is None:\n            threshold = data.X.shape[0] if self.threshold is None else \\\n                        self.threshold\n        if isinstance(threshold, float):\n            threshold = threshold * data.X.shape[0]\n        nans = np.sum(np.isnan(data.X), axis=0)\n        att = [a for a, n in zip(data.domain.attributes, nans) if n < threshold]\n        domain = Orange.data.Domain(att, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\n@deprecated(\"Orange.data.filter.HasClas\")\nclass RemoveNaNClasses(Preprocess):\n    \"\"\"\n    Construct preprocessor that removes examples with missing class\n    from the dataset.\n    \"\"\"\n\n    def __call__(self, data):\n        \"\"\"\n        Remove rows that contain NaN in any class variable from the dataset\n        and return the resulting data table.\n\n        Parameters\n        ----------\n        data : an input dataset\n\n        Returns\n        -------\n        data : dataset without rows with missing classes\n        \"\"\"\n        return HasClass()(data)\n\n\nclass Normalize(Preprocess):\n    \"\"\"\n    Construct a preprocessor for normalization of features.\n    Given a data table, preprocessor returns a new table in\n    which the continuous attributes are normalized.\n\n    Parameters\n    ----------\n    zero_based : bool (default=True)\n        Only used when `norm_type=NormalizeBySpan`.\n\n        Determines the value used as the “low” value of the variable.\n        It determines the interval for normalized continuous variables\n        (either [-1, 1] or [0, 1]).\n\n    norm_type : NormTypes (default: Normalize.NormalizeBySD)\n        Normalization type. If Normalize.NormalizeBySD, the values are\n        replaced with standardized values by subtracting the average\n        value and dividing by the standard deviation.\n        Attribute zero_based has no effect on this standardization.\n\n        If Normalize.NormalizeBySpan, the values are replaced with\n        normalized values by subtracting min value of the data and\n        dividing by span (max - min).\n\n    transform_class : bool (default=False)\n        If True the class is normalized as well.\n\n    center : bool (default=True)\n        Only used when `norm_type=NormalizeBySD`.\n\n        Whether or not to center the data so it has mean zero.\n\n    normalize_datetime : bool (default=False)\n\n\n    Examples\n    --------\n    >>> from Orange.data import Table\n    >>> from Orange.preprocess import Normalize\n    >>> data = Table(\"iris\")\n    >>> normalizer = Normalize(norm_type=Normalize.NormalizeBySpan)\n    >>> normalized_data = normalizer(data)\n    \"\"\"\n    Type = Enum(\"Normalize\", (\"NormalizeBySpan\", \"NormalizeBySD\"),\n                qualname=\"Normalize.Type\")\n    NormalizeBySpan, NormalizeBySD = Type\n\n    def __init__(self,\n                 zero_based=True,\n                 norm_type=NormalizeBySD,\n                 transform_class=False,\n                 center=True,\n                 normalize_datetime=False):\n        self.zero_based = zero_based\n        self.norm_type = norm_type\n        self.transform_class = transform_class\n        self.center = center\n        self.normalize_datetime = normalize_datetime\n\n    def __call__(self, data):\n        \"\"\"\n        Compute and apply normalization of the given data. Returns a new\n        data table.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            A data table to be normalized.\n\n        Returns\n        -------\n        data : Orange.data.Table\n            Normalized data table.\n        \"\"\"\n        from . import normalize\n\n        if all(a.attributes.get('skip-normalization', False)\n               for a in data.domain.attributes if a.is_continuous):\n            # Skip normalization for datasets where all features are marked as already normalized.\n            # Required for SVMs (with normalizer as their default preprocessor) on sparse data to\n            # retain sparse structure. Normalizing sparse data would otherwise result in a dense\n            # matrix, which requires too much memory. For example, this is used for Bag of Words\n            # models where normalization is not really needed.\n            return data\n\n        normalizer = normalize.Normalizer(\n            zero_based=self.zero_based,\n            norm_type=self.norm_type,\n            transform_class=self.transform_class,\n            center=self.center,\n            normalize_datetime=self.normalize_datetime\n        )\n        return normalizer(data)\n\n\nclass Randomize(Preprocess):\n    \"\"\"\n    Construct a preprocessor for randomization of classes,\n    attributes and/or metas.\n    Given a data table, preprocessor returns a new table in\n    which the data is shuffled.\n\n    Parameters\n    ----------\n\n    rand_type : RandTypes (default: Randomize.RandomizeClasses)\n        Randomization type. If Randomize.RandomizeClasses, classes\n        are shuffled.\n        If Randomize.RandomizeAttributes, attributes are shuffled.\n        If Randomize.RandomizeMetas, metas are shuffled.\n\n    rand_seed : int (optional)\n        Random seed\n\n    Examples\n    --------\n    >>> from Orange.data import Table\n    >>> from Orange.preprocess import Randomize\n    >>> data = Table(\"iris\")\n    >>> randomizer = Randomize(Randomize.RandomizeClasses)\n    >>> randomized_data = randomizer(data)\n    \"\"\"\n    Type = Enum(\"Randomize\",\n                dict(RandomizeClasses=1,\n                     RandomizeAttributes=2,\n                     RandomizeMetas=4),\n                type=int,\n                qualname=\"Randomize.Type\")\n    RandomizeClasses, RandomizeAttributes, RandomizeMetas = Type\n\n    def __init__(self, rand_type=RandomizeClasses, rand_seed=None):\n        self.rand_type = rand_type\n        self.rand_seed = rand_seed\n\n    def __call__(self, data):\n        \"\"\"\n        Apply randomization of the given data. Returns a new\n        data table.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            A data table to be randomized.\n\n        Returns\n        -------\n        data : Orange.data.Table\n            Randomized data table.\n        \"\"\"\n        new_data = data.copy()\n        rstate = np.random.RandomState(self.rand_seed)\n        # ensure the same seed is not used to shuffle X and Y at the same time\n        r1, r2, r3 = rstate.randint(0, 2 ** 32 - 1, size=3, dtype=np.int64)\n        if self.rand_type & Randomize.RandomizeClasses:\n            new_data.Y = self.randomize(new_data.Y, r1)\n        if self.rand_type & Randomize.RandomizeAttributes:\n            new_data.X = self.randomize(new_data.X, r2)\n        if self.rand_type & Randomize.RandomizeMetas:\n            new_data.metas = self.randomize(new_data.metas, r3)\n        return new_data\n\n    @staticmethod\n    def randomize(table, rand_state=None):\n        rstate = np.random.RandomState(rand_state)\n        if sp.issparse(table):\n            table = table.tocsc()  # type: sp.spmatrix\n            for i in range(table.shape[1]):\n                permutation = rstate.permutation(table.shape[0])\n                col_indices = \\\n                    table.indices[table.indptr[i]: table.indptr[i + 1]]\n                col_indices[:] = permutation[col_indices]\n        elif len(table.shape) > 1:\n            for i in range(table.shape[1]):\n                rstate.shuffle(table[:, i])\n        else:\n            rstate.shuffle(table)\n        return table\n\n\nclass ProjectPCA(Preprocess):\n\n    def __init__(self, n_components=None):\n        self.n_components = n_components\n\n    def __call__(self, data):\n        pca = Orange.projection.PCA(n_components=self.n_components)(data)\n        return pca(data)\n\n\nclass ProjectCUR(Preprocess):\n\n    def __init__(self, rank=3, max_error=1):\n        self.rank = rank\n        self.max_error = max_error\n\n    def __call__(self, data):\n        rank = min(self.rank, min(data.X.shape)-1)\n        cur = Orange.projection.CUR(\n            rank=rank, max_error=self.max_error,\n            compute_U=False,\n        )(data)\n        return cur(data)\n\n\nclass Scale(Preprocess):\n    \"\"\"\n    Scale data preprocessor.  Scales data so that its distribution remains\n    the same but its location on the axis changes.\n    \"\"\"\n    class _MethodEnum(Enum):\n        def __call__(self, *args, **kwargs):\n            return getattr(Scale, '_' + self.name)(*args, **kwargs)\n\n    CenteringType = _MethodEnum(\"Scale\", (\"NoCentering\", \"Mean\", \"Median\"),\n                                qualname=\"Scale.CenteringType\")\n    ScalingType = _MethodEnum(\"Scale\", (\"NoScaling\", \"Std\", \"Span\"),\n                              qualname=\"Scale.ScalingType\")\n    NoCentering, Mean, Median = CenteringType\n    NoScaling, Std, Span = ScalingType\n\n    @staticmethod\n    def _Mean(dist):\n        values, counts = np.array(dist)\n        return np.average(values, weights=counts)\n\n    @staticmethod\n    def _Median(dist):\n        values, counts = np.array(dist)\n        cumdist = np.cumsum(counts)\n        if cumdist[-1] > 0:\n            cumdist /= cumdist[-1]\n        return np.interp(.5, cumdist, values)\n\n    @staticmethod\n    def _Std(dist):\n        values, counts = np.array(dist)\n        mean = np.average(values, weights=counts)\n        diff = values - mean\n        return np.sqrt(np.average(diff ** 2, weights=counts))\n\n    @staticmethod\n    def _Span(dist):\n        values = np.array(dist[0])\n        return np.max(values) - np.min(values)\n\n    def __init__(self, center=Mean, scale=Std):\n        self.center = center\n        self.scale = scale\n\n    def __call__(self, data):\n        if self.center is None and self.scale is None:\n            return data\n\n        def transform(var):\n            dist = distribution.get_distribution(data, var)\n            if self.center != self.NoCentering:\n                c = self.center(dist)\n                dist[0, :] -= c\n            else:\n                c = 0\n\n            if self.scale != self.NoScaling:\n                s = self.scale(dist)\n                if s < 1e-15:\n                    s = 1\n            else:\n                s = 1\n            factor = 1 / s\n            transformed_var = var.copy(\n                compute_value=transformation.Normalizer(var, c, factor))\n            return transformed_var\n\n        newvars = []\n        for var in data.domain.attributes:\n            if var.is_continuous:\n                newvars.append(transform(var))\n            else:\n                newvars.append(var)\n        domain = Orange.data.Domain(newvars, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\nclass PreprocessorList(Preprocess):\n    \"\"\"\n    Store a list of preprocessors and on call apply them to the dataset.\n\n    Parameters\n    ----------\n    preprocessors : list\n        A list of preprocessors.\n    \"\"\"\n\n    def __init__(self, preprocessors=()):\n        self.preprocessors = list(preprocessors)\n\n    def __call__(self, data):\n        \"\"\"\n        Applies a list of preprocessors to the dataset.\n\n        Parameters\n        ----------\n        data : an input data table\n        \"\"\"\n\n        for pp in self.preprocessors:\n            data = pp(data)\n        return data\n\nclass RemoveSparse(Preprocess):\n    \"\"\"\n    Filter out the features with too many nan's or 0. Threshold is user defined.\n\n    Parameters\n    ----------\n    filter_0: bool\n        filter out by zeros or nan's\n    fixed_threshold: bool\n        threshold is either a fixed number of elements or percentage\n    threshold: int\n        kept as is if fixed threshold or the percent is used to calculate\n        the appropriate number of elements\n    \"\"\"\n\n    def __init__(self, filter_0=True, fixed_threshold=False, threshold=5):\n        self.filter_0 = filter_0\n        self.fixed_threshold = fixed_threshold\n        self.threshold = threshold\n\n    def __call__(self, data):\n        if self.fixed_threshold:\n            tailored_threshold = self.threshold\n        else:\n            tailored_threshold = np.ceil(self.threshold/100 * data.X.shape[0])\n\n        if self.filter_0:\n            if sp.issparse(data.X):\n                data_csc = sp.csc_matrix(data.X)\n                h, w = data_csc.shape\n                sparsness = [(h - data_csc[:, i].count_nonzero()) for i in range(w)]\n            else:\n                sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)\n        else: # filter by nans\n            if sp.issparse(data.X):\n                sparsness = np.sum(np.isnan(data.X.data), axis=0)\n            else:\n                sparsness = np.sum(np.isnan(data.X), axis=0)\n        att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]\n        domain = Orange.data.Domain(att, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\nclass AdaptiveNormalize(Preprocess):\n    \"\"\"\n    Construct a preprocessors that normalizes or merely scales the data.\n    If the input is sparse, data is only scaled, to avoid turning it to\n    dense. Parameters are diveded to those passed to Normalize or Scale\n    class. Scaling takes only scale parameter.\n     If the user wants to have more options with scaling,\n    they should use the preprocessing widget.\n    For more details, check Scale and Normalize widget.\n\n    Parameters\n    ----------\n\n    zero_based : bool (default=True)\n        passed to Normalize\n\n    norm_type : NormTypes (default: Normalize.NormalizeBySD)\n        passed to Normalize\n\n    transform_class : bool (default=False)\n        passed to Normalize\n\n    center : bool(default=True)\n        passed to Normalize\n\n    normalize_datetime : bool (default=False)\n        passed to Normalize\n\n    scale : ScaleTypes (default: Scale.Span)\n        passed to Scale\n    \"\"\"\n\n    def __init__(self,\n                 zero_based=True,\n                 norm_type=Normalize.NormalizeBySD,\n                 transform_class=False,\n                 normalize_datetime=False,\n                 center=True,\n                 scale=Scale.Span):\n        self.normalize_pps = Normalize(zero_based,\n                                       norm_type,\n                                       transform_class,\n                                       center,\n                                       normalize_datetime)\n        self.scale_pps = Scale(center=Scale.NoCentering, scale=scale)\n\n    def __call__(self, data):\n        if sp.issparse(data.X):\n            return self.scale_pps(data)\n        return self.normalize_pps(data)\n",
            "new_file_content": "\"\"\"\nPreprocess\n----------\n\n\"\"\"\nimport numpy as np\nimport bottleneck as bn\nimport scipy.sparse as sp\nfrom sklearn.impute import SimpleImputer\n\nimport Orange.data\nfrom Orange.data.filter import HasClass\nfrom Orange.statistics import distribution\nfrom Orange.util import Reprable, Enum, deprecated\nfrom . import impute, discretize, transformation\n\n__all__ = [\"Continuize\", \"Discretize\", \"Impute\", \"RemoveNaNRows\",\n           \"SklImpute\", \"Normalize\", \"Randomize\", \"Preprocess\",\n           \"RemoveConstant\", \"RemoveNaNClasses\", \"RemoveNaNColumns\",\n           \"ProjectPCA\", \"ProjectCUR\", \"Scale\", \"RemoveSparse\",\n           \"AdaptiveNormalize\"]\n\n\nclass Preprocess(Reprable):\n    \"\"\"\n    A generic preprocessor base class.\n\n    Methods\n    -------\n    __call__(data: Table) -> Table\n        Return preprocessed data.\n    \"\"\"\n    def __call__(self, data):\n        raise NotImplementedError(\"Subclasses need to implement __call__\")\n\n\nclass Continuize(Preprocess):\n    MultinomialTreatment = Enum(\n        \"Continuize\",\n        (\"Indicators\", \"FirstAsBase\", \"FrequentAsBase\", \"Remove\",\n         \"RemoveMultinomial\", \"ReportError\", \"AsOrdinal\", \"AsNormalizedOrdinal\",\n         \"Leave\"),\n        qualname=\"Continuize.MultinomialTreatment\")\n    (Indicators, FirstAsBase, FrequentAsBase, Remove, RemoveMultinomial,\n     ReportError, AsOrdinal, AsNormalizedOrdinal, Leave) = MultinomialTreatment\n\n    def __init__(self, zero_based=True,\n                 multinomial_treatment=Indicators):\n        self.zero_based = zero_based\n        self.multinomial_treatment = multinomial_treatment\n\n    def __call__(self, data):\n        from . import continuize\n\n        continuizer = continuize.DomainContinuizer(\n            zero_based=self.zero_based,\n            multinomial_treatment=self.multinomial_treatment)\n        domain = continuizer(data)\n        return data.transform(domain)\n\n\nclass Discretize(Preprocess):\n    \"\"\"\n    Construct a discretizer, a preprocessor for discretization of\n    continuous features.\n\n    Parameters\n    ----------\n    method : discretization method (default: Orange.preprocess.discretize.Discretization)\n\n    remove_const : bool (default=True)\n        Determines whether the features with constant values are removed\n        during discretization.\n    \"\"\"\n\n    def __init__(self, method=None, remove_const=True,\n                 discretize_classes=False, discretize_metas=False):\n        self.method = method\n        self.remove_const = remove_const\n        self.discretize_classes = discretize_classes\n        self.discretize_metas = discretize_metas\n\n    def __call__(self, data):\n        \"\"\"\n        Compute and apply discretization of the given data. Returns a new\n        data table.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            A data table to be discretized.\n        \"\"\"\n\n        def transform(var):\n            if var.is_continuous:\n                new_var = method(data, var)\n                if new_var is not None and \\\n                        (len(new_var.values) >= 2 or not self.remove_const):\n                    return new_var\n                else:\n                    return None\n            else:\n                return var\n\n        def discretized(vars_, do_discretize):\n            if do_discretize:\n                vars_ = (transform(var) for var in vars_)\n                vars_ = [var for var in vars_ if var is not None]\n            return vars_\n\n        method = self.method or discretize.EqualFreq()\n        domain = Orange.data.Domain(\n            discretized(data.domain.attributes, True),\n            discretized(data.domain.class_vars, self.discretize_classes),\n            discretized(data.domain.metas, self.discretize_metas))\n        return data.transform(domain)\n\n\nclass Impute(Preprocess):\n    \"\"\"\n    Construct a imputer, a preprocessor for imputation of missing values in\n    the data table.\n\n    Parameters\n    ----------\n    method : imputation method (default: Orange.preprocess.impute.Average())\n    \"\"\"\n\n    def __init__(self, method=Orange.preprocess.impute.Average()):\n        self.method = method\n\n    def __call__(self, data):\n        \"\"\"\n        Apply an imputation method to the given dataset. Returns a new\n        data table with missing values replaced by their imputations.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            An input data table.\n        \"\"\"\n\n        method = self.method or impute.Average()\n        newattrs = [method(data, var) for var in data.domain.attributes]\n        domain = Orange.data.Domain(\n            newattrs, data.domain.class_vars, data.domain.metas)\n        return data.transform(domain)\n\n\nclass SklImpute(Preprocess):\n    __wraps__ = SimpleImputer\n\n    def __init__(self, strategy='mean'):\n        self.strategy = strategy\n\n    def __call__(self, data):\n        from Orange.data.sql.table import SqlTable\n        if isinstance(data, SqlTable):\n            return Impute()(data)\n        imputer = SimpleImputer(strategy=self.strategy)\n        X = imputer.fit_transform(data.X)\n        # Create new variables with appropriate `compute_value`, but\n        # drop the ones which do not have valid `imputer.statistics_`\n        # (i.e. all NaN columns). `sklearn.preprocessing.Imputer` already\n        # drops them from the transformed X.\n        features = [impute.Average()(data, var, value)\n                    for var, value in zip(data.domain.attributes,\n                                          imputer.statistics_)\n                    if not np.isnan(value)]\n        assert X.shape[1] == len(features)\n        domain = Orange.data.Domain(features, data.domain.class_vars,\n                                    data.domain.metas)\n        new_data = data.transform(domain)\n        new_data.X = X\n        return new_data\n\n\nclass RemoveConstant(Preprocess):\n    \"\"\"\n    Construct a preprocessor that removes features with constant values\n    from the dataset.\n    \"\"\"\n\n    def __call__(self, data):\n        \"\"\"\n        Remove columns with constant values from the dataset and return\n        the resulting data table.\n\n        Parameters\n        ----------\n        data : an input dataset\n        \"\"\"\n\n        oks = np.logical_and(~bn.allnan(data.X, axis=0),\n                             bn.nanmin(data.X, axis=0) != bn.nanmax(data.X, axis=0))\n        atts = [data.domain.attributes[i] for i, ok in enumerate(oks) if ok]\n        domain = Orange.data.Domain(atts, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\nclass RemoveNaNRows(Preprocess):\n    _reprable_module = True\n\n    def __call__(self, data):\n        mask = np.isnan(data.X)\n        mask = np.any(mask, axis=1)\n        return data[~mask]\n\n\nclass RemoveNaNColumns(Preprocess):\n    \"\"\"\n    Remove features from the data domain if they contain\n    `threshold` or more unknown values.\n\n    `threshold` can be an integer or a float in the range (0, 1) representing\n    the fraction of the data size. When not provided, columns with only missing\n    values are removed (default).\n    \"\"\"\n    def __init__(self, threshold=None):\n        self.threshold = threshold\n\n    def __call__(self, data, threshold=None):\n        # missing entries in sparse data are treated as zeros so we skip removing NaNs\n        if sp.issparse(data.X):\n            return data\n\n        if threshold is None:\n            threshold = data.X.shape[0] if self.threshold is None else \\\n                        self.threshold\n        if isinstance(threshold, float):\n            threshold = threshold * data.X.shape[0]\n        nans = np.sum(np.isnan(data.X), axis=0)\n        att = [a for a, n in zip(data.domain.attributes, nans) if n < threshold]\n        domain = Orange.data.Domain(att, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\n@deprecated(\"Orange.data.filter.HasClas\")\nclass RemoveNaNClasses(Preprocess):\n    \"\"\"\n    Construct preprocessor that removes examples with missing class\n    from the dataset.\n    \"\"\"\n\n    def __call__(self, data):\n        \"\"\"\n        Remove rows that contain NaN in any class variable from the dataset\n        and return the resulting data table.\n\n        Parameters\n        ----------\n        data : an input dataset\n\n        Returns\n        -------\n        data : dataset without rows with missing classes\n        \"\"\"\n        return HasClass()(data)\n\n\nclass Normalize(Preprocess):\n    \"\"\"\n    Construct a preprocessor for normalization of features.\n    Given a data table, preprocessor returns a new table in\n    which the continuous attributes are normalized.\n\n    Parameters\n    ----------\n    zero_based : bool (default=True)\n        Only used when `norm_type=NormalizeBySpan`.\n\n        Determines the value used as the “low” value of the variable.\n        It determines the interval for normalized continuous variables\n        (either [-1, 1] or [0, 1]).\n\n    norm_type : NormTypes (default: Normalize.NormalizeBySD)\n        Normalization type. If Normalize.NormalizeBySD, the values are\n        replaced with standardized values by subtracting the average\n        value and dividing by the standard deviation.\n        Attribute zero_based has no effect on this standardization.\n\n        If Normalize.NormalizeBySpan, the values are replaced with\n        normalized values by subtracting min value of the data and\n        dividing by span (max - min).\n\n    transform_class : bool (default=False)\n        If True the class is normalized as well.\n\n    center : bool (default=True)\n        Only used when `norm_type=NormalizeBySD`.\n\n        Whether or not to center the data so it has mean zero.\n\n    normalize_datetime : bool (default=False)\n\n\n    Examples\n    --------\n    >>> from Orange.data import Table\n    >>> from Orange.preprocess import Normalize\n    >>> data = Table(\"iris\")\n    >>> normalizer = Normalize(norm_type=Normalize.NormalizeBySpan)\n    >>> normalized_data = normalizer(data)\n    \"\"\"\n    Type = Enum(\"Normalize\", (\"NormalizeBySpan\", \"NormalizeBySD\"),\n                qualname=\"Normalize.Type\")\n    NormalizeBySpan, NormalizeBySD = Type\n\n    def __init__(self,\n                 zero_based=True,\n                 norm_type=NormalizeBySD,\n                 transform_class=False,\n                 center=True,\n                 normalize_datetime=False):\n        self.zero_based = zero_based\n        self.norm_type = norm_type\n        self.transform_class = transform_class\n        self.center = center\n        self.normalize_datetime = normalize_datetime\n\n    def __call__(self, data):\n        \"\"\"\n        Compute and apply normalization of the given data. Returns a new\n        data table.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            A data table to be normalized.\n\n        Returns\n        -------\n        data : Orange.data.Table\n            Normalized data table.\n        \"\"\"\n        from . import normalize\n\n        if all(a.attributes.get('skip-normalization', False)\n               for a in data.domain.attributes if a.is_continuous):\n            # Skip normalization for datasets where all features are marked as already normalized.\n            # Required for SVMs (with normalizer as their default preprocessor) on sparse data to\n            # retain sparse structure. Normalizing sparse data would otherwise result in a dense\n            # matrix, which requires too much memory. For example, this is used for Bag of Words\n            # models where normalization is not really needed.\n            return data\n\n        normalizer = normalize.Normalizer(\n            zero_based=self.zero_based,\n            norm_type=self.norm_type,\n            transform_class=self.transform_class,\n            center=self.center,\n            normalize_datetime=self.normalize_datetime\n        )\n        return normalizer(data)\n\n\nclass Randomize(Preprocess):\n    \"\"\"\n    Construct a preprocessor for randomization of classes,\n    attributes and/or metas.\n    Given a data table, preprocessor returns a new table in\n    which the data is shuffled.\n\n    Parameters\n    ----------\n\n    rand_type : RandTypes (default: Randomize.RandomizeClasses)\n        Randomization type. If Randomize.RandomizeClasses, classes\n        are shuffled.\n        If Randomize.RandomizeAttributes, attributes are shuffled.\n        If Randomize.RandomizeMetas, metas are shuffled.\n\n    rand_seed : int (optional)\n        Random seed\n\n    Examples\n    --------\n    >>> from Orange.data import Table\n    >>> from Orange.preprocess import Randomize\n    >>> data = Table(\"iris\")\n    >>> randomizer = Randomize(Randomize.RandomizeClasses)\n    >>> randomized_data = randomizer(data)\n    \"\"\"\n    Type = Enum(\"Randomize\",\n                dict(RandomizeClasses=1,\n                     RandomizeAttributes=2,\n                     RandomizeMetas=4),\n                type=int,\n                qualname=\"Randomize.Type\")\n    RandomizeClasses, RandomizeAttributes, RandomizeMetas = Type\n\n    def __init__(self, rand_type=RandomizeClasses, rand_seed=None):\n        self.rand_type = rand_type\n        self.rand_seed = rand_seed\n\n    def __call__(self, data):\n        \"\"\"\n        Apply randomization of the given data. Returns a new\n        data table.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            A data table to be randomized.\n\n        Returns\n        -------\n        data : Orange.data.Table\n            Randomized data table.\n        \"\"\"\n        new_data = data.copy()\n        rstate = np.random.RandomState(self.rand_seed)\n        # ensure the same seed is not used to shuffle X and Y at the same time\n        r1, r2, r3 = rstate.randint(0, 2 ** 32 - 1, size=3, dtype=np.int64)\n        if self.rand_type & Randomize.RandomizeClasses:\n            new_data.Y = self.randomize(new_data.Y, r1)\n        if self.rand_type & Randomize.RandomizeAttributes:\n            new_data.X = self.randomize(new_data.X, r2)\n        if self.rand_type & Randomize.RandomizeMetas:\n            new_data.metas = self.randomize(new_data.metas, r3)\n        return new_data\n\n    @staticmethod\n    def randomize(table, rand_state=None):\n        rstate = np.random.RandomState(rand_state)\n        if sp.issparse(table):\n            table = table.tocsc()  # type: sp.spmatrix\n            for i in range(table.shape[1]):\n                permutation = rstate.permutation(table.shape[0])\n                col_indices = \\\n                    table.indices[table.indptr[i]: table.indptr[i + 1]]\n                col_indices[:] = permutation[col_indices]\n        elif len(table.shape) > 1:\n            for i in range(table.shape[1]):\n                rstate.shuffle(table[:, i])\n        else:\n            rstate.shuffle(table)\n        return table\n\n\nclass ProjectPCA(Preprocess):\n\n    def __init__(self, n_components=None):\n        self.n_components = n_components\n\n    def __call__(self, data):\n        pca = Orange.projection.PCA(n_components=self.n_components)(data)\n        return pca(data)\n\n\nclass ProjectCUR(Preprocess):\n\n    def __init__(self, rank=3, max_error=1):\n        self.rank = rank\n        self.max_error = max_error\n\n    def __call__(self, data):\n        rank = min(self.rank, min(data.X.shape)-1)\n        cur = Orange.projection.CUR(\n            rank=rank, max_error=self.max_error,\n            compute_U=False,\n        )(data)\n        return cur(data)\n\n\nclass Scale(Preprocess):\n    \"\"\"\n    Scale data preprocessor.  Scales data so that its distribution remains\n    the same but its location on the axis changes.\n    \"\"\"\n    class _MethodEnum(Enum):\n        def __call__(self, *args, **kwargs):\n            return getattr(Scale, '_' + self.name)(*args, **kwargs)\n\n    CenteringType = _MethodEnum(\"Scale\", (\"NoCentering\", \"Mean\", \"Median\"),\n                                qualname=\"Scale.CenteringType\")\n    ScalingType = _MethodEnum(\"Scale\", (\"NoScaling\", \"Std\", \"Span\"),\n                              qualname=\"Scale.ScalingType\")\n    NoCentering, Mean, Median = CenteringType\n    NoScaling, Std, Span = ScalingType\n\n    @staticmethod\n    def _Mean(dist):\n        values, counts = np.array(dist)\n        return np.average(values, weights=counts)\n\n    @staticmethod\n    def _Median(dist):\n        values, counts = np.array(dist)\n        cumdist = np.cumsum(counts)\n        if cumdist[-1] > 0:\n            cumdist /= cumdist[-1]\n        return np.interp(.5, cumdist, values)\n\n    @staticmethod\n    def _Std(dist):\n        values, counts = np.array(dist)\n        mean = np.average(values, weights=counts)\n        diff = values - mean\n        return np.sqrt(np.average(diff ** 2, weights=counts))\n\n    @staticmethod\n    def _Span(dist):\n        values = np.array(dist[0])\n        return np.max(values) - np.min(values)\n\n    def __init__(self, center=Mean, scale=Std):\n        self.center = center\n        self.scale = scale\n\n    def __call__(self, data):\n        if self.center is None and self.scale is None:\n            return data\n\n        def transform(var):\n            dist = distribution.get_distribution(data, var)\n            if self.center != self.NoCentering:\n                c = self.center(dist)\n                dist[0, :] -= c\n            else:\n                c = 0\n\n            if self.scale != self.NoScaling:\n                s = self.scale(dist)\n                if s < 1e-15:\n                    s = 1\n            else:\n                s = 1\n            factor = 1 / s\n            transformed_var = var.copy(\n                compute_value=transformation.Normalizer(var, c, factor))\n            return transformed_var\n\n        newvars = []\n        for var in data.domain.attributes:\n            if var.is_continuous:\n                newvars.append(transform(var))\n            else:\n                newvars.append(var)\n        domain = Orange.data.Domain(newvars, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\nclass PreprocessorList(Preprocess):\n    \"\"\"\n    Store a list of preprocessors and on call apply them to the dataset.\n\n    Parameters\n    ----------\n    preprocessors : list\n        A list of preprocessors.\n    \"\"\"\n\n    def __init__(self, preprocessors=()):\n        self.preprocessors = list(preprocessors)\n\n    def __call__(self, data):\n        \"\"\"\n        Applies a list of preprocessors to the dataset.\n\n        Parameters\n        ----------\n        data : an input data table\n        \"\"\"\n\n        for pp in self.preprocessors:\n            data = pp(data)\n        return data\n\nclass RemoveSparse(Preprocess):\n    \"\"\"\n    Filter out the features with too many nan's or 0. Threshold is user defined.\n\n    Parameters\n    ----------\n    filter_0: bool\n        filter out by zeros or nan's\n    fixed_threshold: bool\n        threshold is either a fixed number of elements or percentage\n    threshold: int\n        kept as is if fixed threshold or the percent is used to calculate\n        the appropriate number of elements\n    \"\"\"\n\n    def __init__(self, filter_0=True, fixed_threshold=False, threshold=5):\n        self.filter_0 = filter_0\n        self.fixed_threshold = fixed_threshold\n        self.threshold = threshold\n\n    def __call__(self, data):\n        if self.fixed_threshold:\n            tailored_threshold = self.threshold\n        else:\n            tailored_threshold = np.ceil(self.threshold/100 * data.X.shape[0])\n\n        if self.filter_0:\n            if sp.issparse(data.X):\n                data_csc = sp.csc_matrix(data.X)\n                h, w = data_csc.shape\n                sparsness = [(h - data_csc[:, i].count_nonzero()) for i in range(w)]\n            else:\n                sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)\n        else: # filter by nans\n            if sp.issparse(data.X):\n                data_csc = sp.csc_matrix(data.X)\n                sparsness = [np.sum(np.isnan(data.X[:, i].data)) for i in range(data_csc.shape[1])]\n            else:\n                sparsness = np.sum(np.isnan(data.X), axis=0)\n        att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]\n        domain = Orange.data.Domain(att, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\nclass AdaptiveNormalize(Preprocess):\n    \"\"\"\n    Construct a preprocessors that normalizes or merely scales the data.\n    If the input is sparse, data is only scaled, to avoid turning it to\n    dense. Parameters are diveded to those passed to Normalize or Scale\n    class. Scaling takes only scale parameter.\n     If the user wants to have more options with scaling,\n    they should use the preprocessing widget.\n    For more details, check Scale and Normalize widget.\n\n    Parameters\n    ----------\n\n    zero_based : bool (default=True)\n        passed to Normalize\n\n    norm_type : NormTypes (default: Normalize.NormalizeBySD)\n        passed to Normalize\n\n    transform_class : bool (default=False)\n        passed to Normalize\n\n    center : bool(default=True)\n        passed to Normalize\n\n    normalize_datetime : bool (default=False)\n        passed to Normalize\n\n    scale : ScaleTypes (default: Scale.Span)\n        passed to Scale\n    \"\"\"\n\n    def __init__(self,\n                 zero_based=True,\n                 norm_type=Normalize.NormalizeBySD,\n                 transform_class=False,\n                 normalize_datetime=False,\n                 center=True,\n                 scale=Scale.Span):\n        self.normalize_pps = Normalize(zero_based,\n                                       norm_type,\n                                       transform_class,\n                                       center,\n                                       normalize_datetime)\n        self.scale_pps = Scale(center=Scale.NoCentering, scale=scale)\n\n    def __call__(self, data):\n        if sp.issparse(data.X):\n            return self.scale_pps(data)\n        return self.normalize_pps(data)\n",
            "header": {
                "file": {
                    "path": "Orange/preprocess/preprocess.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "ed46ba931",
                "new_commit_hash": "97c63228a",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/preprocess/preprocess.py"
            },
            "plus_file": {
                "path": "b/Orange/preprocess/preprocess.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 605,
                            "length": 7
                        },
                        "new_range": {
                            "start": 605,
                            "length": 8
                        },
                        "section": "class RemoveSparse(Preprocess):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "                sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)",
                                "type": "context"
                            },
                            {
                                "content": "        else: # filter by nans",
                                "type": "context"
                            },
                            {
                                "content": "            if sp.issparse(data.X):",
                                "type": "context"
                            },
                            {
                                "content": "                sparsness = np.sum(np.isnan(data.X.data), axis=0)",
                                "type": "deleted"
                            },
                            {
                                "content": "                data_csc = sp.csc_matrix(data.X)",
                                "type": "added"
                            },
                            {
                                "content": "                sparsness = [np.sum(np.isnan(data.X[:, i].data)) for i in range(data_csc.shape[1])]",
                                "type": "added"
                            },
                            {
                                "content": "            else:",
                                "type": "context"
                            },
                            {
                                "content": "                sparsness = np.sum(np.isnan(data.X), axis=0)",
                                "type": "context"
                            },
                            {
                                "content": "        att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/preprocess/preprocess.py",
                            "type": "method",
                            "name": "RemoveSparse.__call__",
                            "content": "class RemoveSparse(Preprocess):\n    \"\"\"\n    Filter out the features with too many nan's or 0. Threshold is user defined.\n\n    Parameters\n    ----------\n    filter_0: bool\n        filter out by zeros or nan's\n    fixed_threshold: bool\n        threshold is either a fixed number of elements or percentage\n    threshold: int\n        kept as is if fixed threshold or the percent is used to calculate\n        the appropriate number of elements\n    \"\"\"\n\n    def __init__(self, filter_0=True, fixed_threshold=False, threshold=5):\n        self.filter_0 = filter_0\n        self.fixed_threshold = fixed_threshold\n        self.threshold = threshold\n\n    def __call__(self, data):\n        if self.fixed_threshold:\n            tailored_threshold = self.threshold\n        else:\n            tailored_threshold = np.ceil(self.threshold/100 * data.X.shape[0])\n\n        if self.filter_0:\n            if sp.issparse(data.X):\n                data_csc = sp.csc_matrix(data.X)\n                h, w = data_csc.shape\n                sparsness = [(h - data_csc[:, i].count_nonzero()) for i in range(w)]\n            else:\n                sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)\n        else: # filter by nans\n            if sp.issparse(data.X):\n                sparsness = np.sum(np.isnan(data.X.data), axis=0)\n            else:\n                sparsness = np.sum(np.isnan(data.X), axis=0)\n        att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]\n        domain = Orange.data.Domain(att, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 593,
                            "end_lineno": 614,
                            "parent": {
                                "file_name": "Orange/preprocess/preprocess.py",
                                "type": "class",
                                "name": "RemoveSparse",
                                "content": "class RemoveSparse(Preprocess):\n    \"\"\"\n    Filter out the features with too many nan's or 0. Threshold is user defined.\n\n    Parameters\n    ----------\n    filter_0: bool\n        filter out by zeros or nan's\n    fixed_threshold: bool\n        threshold is either a fixed number of elements or percentage\n    threshold: int\n        kept as is if fixed threshold or the percent is used to calculate\n        the appropriate number of elements\n    \"\"\"\n\n    def __init__(self, filter_0=True, fixed_threshold=False, threshold=5):\n        self.filter_0 = filter_0\n        self.fixed_threshold = fixed_threshold\n        self.threshold = threshold\n\n    def __call__(self, data):\n        if self.fixed_threshold:\n            tailored_threshold = self.threshold\n        else:\n            tailored_threshold = np.ceil(self.threshold/100 * data.X.shape[0])\n\n        if self.filter_0:\n            if sp.issparse(data.X):\n                data_csc = sp.csc_matrix(data.X)\n                h, w = data_csc.shape\n                sparsness = [(h - data_csc[:, i].count_nonzero()) for i in range(w)]\n            else:\n                sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)\n        else: # filter by nans\n            if sp.issparse(data.X):\n                sparsness = np.sum(np.isnan(data.X.data), axis=0)\n            else:\n                sparsness = np.sum(np.isnan(data.X), axis=0)\n        att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]\n        domain = Orange.data.Domain(att, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 573,
                                "end_lineno": 614,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "Orange/preprocess/preprocess.py",
                            "type": "class",
                            "name": "RemoveSparse",
                            "content": "class RemoveSparse(Preprocess):\n    \"\"\"\n    Filter out the features with too many nan's or 0. Threshold is user defined.\n\n    Parameters\n    ----------\n    filter_0: bool\n        filter out by zeros or nan's\n    fixed_threshold: bool\n        threshold is either a fixed number of elements or percentage\n    threshold: int\n        kept as is if fixed threshold or the percent is used to calculate\n        the appropriate number of elements\n    \"\"\"\n\n    def __init__(self, filter_0=True, fixed_threshold=False, threshold=5):\n        self.filter_0 = filter_0\n        self.fixed_threshold = fixed_threshold\n        self.threshold = threshold\n\n    def __call__(self, data):\n        if self.fixed_threshold:\n            tailored_threshold = self.threshold\n        else:\n            tailored_threshold = np.ceil(self.threshold/100 * data.X.shape[0])\n\n        if self.filter_0:\n            if sp.issparse(data.X):\n                data_csc = sp.csc_matrix(data.X)\n                h, w = data_csc.shape\n                sparsness = [(h - data_csc[:, i].count_nonzero()) for i in range(w)]\n            else:\n                sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)\n        else: # filter by nans\n            if sp.issparse(data.X):\n                sparsness = np.sum(np.isnan(data.X.data), axis=0)\n            else:\n                sparsness = np.sum(np.isnan(data.X), axis=0)\n        att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]\n        domain = Orange.data.Domain(att, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 573,
                            "end_lineno": 614,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring\n\nimport os\nimport pickle\nimport unittest\nfrom unittest.mock import Mock\n\nimport numpy as np\nfrom scipy.sparse import csr_matrix\n\nfrom Orange.data import Table, Domain, ContinuousVariable\nfrom Orange.preprocess import EntropyMDL, DoNotImpute, Default, Average, \\\n    SelectRandomFeatures, EqualFreq, RemoveNaNColumns, DropInstances, \\\n    EqualWidth, SelectBestFeatures, RemoveNaNRows, Preprocess, Scale, \\\n    Randomize, Continuize, Discretize, Impute, SklImpute, Normalize, \\\n    ProjectCUR, ProjectPCA, RemoveConstant, AdaptiveNormalize, RemoveSparse\nfrom Orange.util import OrangeDeprecationWarning\n\n\nclass TestPreprocess(unittest.TestCase):\n    def test_read_data_calls_reader(self):\n        class MockPreprocessor(Preprocess):\n            __init__ = Mock(return_value=None)\n            __call__ = Mock()\n            @classmethod\n            def reset(cls):\n                cls.__init__.reset_mock()\n                cls.__call__.reset_mock()\n\n        table = Mock(Table)\n        MockPreprocessor(1, 2, a=3)(table)\n        MockPreprocessor.__init__.assert_called_with(1, 2, a=3)\n        MockPreprocessor.__call__.assert_called_with(table)\n        MockPreprocessor.reset()\n\n        MockPreprocessor(1, 2, a=3)\n        MockPreprocessor.__init__.assert_called_with(1, 2, a=3)\n        self.assertEqual(MockPreprocessor.__call__.call_count, 0)\n\n        MockPreprocessor(a=3)\n        MockPreprocessor.__init__.assert_called_with(a=3)\n        self.assertEqual(MockPreprocessor.__call__.call_count, 0)\n\n        MockPreprocessor()\n        MockPreprocessor.__init__.assert_called_with()\n        self.assertEqual(MockPreprocessor.__call__.call_count, 0)\n\n\nclass TestRemoveConstant(unittest.TestCase):\n    def test_remove_columns(self):\n        X = np.random.rand(6, 5)\n        X[:, (1, 3)] = 5\n        X[3, 1] = np.nan\n        X[1, 1] = np.nan\n        X[:, 4] = np.nan\n        data = Table(X)\n        d = RemoveConstant()(data)\n        self.assertEqual(len(d.domain.attributes), 2)\n\n        pp_rc = RemoveConstant()\n        d = pp_rc(data)\n        self.assertEqual(len(d.domain.attributes), 2)\n\n    def test_nothing_to_remove(self):\n        data = Table(\"iris\")\n        d = RemoveConstant()(data)\n        self.assertEqual(len(d.domain.attributes), 4)\n\n\nclass TestRemoveNaNRows(unittest.TestCase):\n    def test_remove_row(self):\n        data = Table(\"iris\")\n        data.X[0, 0] = np.nan\n        pp_data = RemoveNaNRows()(data)\n        self.assertEqual(len(pp_data), len(data) - 1)\n        self.assertFalse(np.isnan(pp_data.X).any())\n\n\nclass TestRemoveNaNColumns(unittest.TestCase):\n    def test_column_filtering(self):\n        data = Table(\"iris\")\n        data.X[:, (1, 3)] = np.NaN\n\n        new_data = RemoveNaNColumns()(data)\n        self.assertEqual(len(new_data.domain.attributes),\n                         len(data.domain.attributes) - 2)\n\n        data = Table(\"iris\")\n        data.X[0, 0] = np.NaN\n        new_data = RemoveNaNColumns()(data)\n        self.assertEqual(len(new_data.domain.attributes),\n                         len(data.domain.attributes))\n\n    def test_column_filtering_sparse(self):\n        data = Table(\"iris\")\n        data.X = csr_matrix(data.X)\n\n        new_data = RemoveNaNColumns()(data)\n        self.assertEqual(data, new_data)\n\n\nclass TestScaling(unittest.TestCase):\n    @classmethod\n    def setUpClass(cls):\n        cls.table = Table([[1, 2, 3],\n                           [2, 3, 4],\n                           [3, 4, 5],\n                           [4, 5, 6]])\n\n    def test_scaling_mean_span(self):\n        table = Scale(center=Scale.Mean, scale=Scale.Span)(self.table)\n        np.testing.assert_almost_equal(np.mean(table, 0), 0)\n        np.testing.assert_almost_equal(np.ptp(table, 0), 1)\n\n    def test_scaling_median_stddev(self):\n        table = Scale(center=Scale.Median, scale=Scale.Std)(self.table)\n        np.testing.assert_almost_equal(np.std(table, 0), 1)\n        # NB: This test just covers. The following fails. You figure it out.\n        # np.testing.assert_almost_equal(np.median(table, 0), 0)\n\n\nclass TestReprs(unittest.TestCase):\n    def test_reprs(self):\n        preprocs = [Continuize, Discretize, Impute, SklImpute, Normalize,\n                    Randomize, ProjectPCA, ProjectCUR, Scale,\n                    EqualFreq, EqualWidth, EntropyMDL, SelectBestFeatures,\n                    SelectRandomFeatures, RemoveNaNColumns, DoNotImpute, DropInstances,\n                    Average, Default, RemoveSparse]\n\n        for preproc in preprocs:\n            repr_str = repr(preproc())\n            new_preproc = eval(repr_str)\n            self.assertEqual(repr(new_preproc), repr_str)\n\n\nclass TestEnumPickling(unittest.TestCase):\n    def test_continuize_pickling(self):\n        c = Continuize(multinomial_treatment=Continuize.FirstAsBase)\n        s = pickle.dumps(c, -1)\n        c1 = pickle.loads(s)\n        self.assertIs(c1.multinomial_treatment, c.multinomial_treatment)\n\n    def test_randomize_pickling(self):\n        c = Randomize(rand_type=Randomize.RandomizeMetas)\n        s = pickle.dumps(c, -1)\n        c1 = pickle.loads(s)\n        self.assertIs(c1.rand_type, c.rand_type)\n\n    def test_scaling_pickling(self):\n        c = Scale(center=Scale.Median, scale=Scale.Span)\n        s = pickle.dumps(c, -1)\n        c1 = pickle.loads(s)\n        self.assertIs(c1.center, c.center)\n        self.assertIs(c1.scale, c.scale)\n\n\nclass TestAdaptiveNormalize(unittest.TestCase):\n    \"\"\"\n    Checks if output for sparse data is the same as for Scale\n    preprocessor. For dense data the output should match that\n     of Normalize preprocessor.\n    \"\"\"\n\n    def setUp(self):\n        self.data = Table(\"iris\")\n\n    def test_dense_pps(self):\n        true_out = Normalize()(self.data)\n        out = AdaptiveNormalize()(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_sparse_pps(self):\n        self.data.X = csr_matrix(self.data.X)\n        out = AdaptiveNormalize()(self.data)\n        true_out = Scale(center=Scale.NoCentering, scale=Scale.Span)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n        self.data = self.data.X.toarray()\n\n\nclass TestRemoveSparse(unittest.TestCase):\n\n    def setUp(self):\n        domain = Domain([ContinuousVariable('a'), ContinuousVariable('b')])\n        self.data = Table.from_numpy(domain, np.zeros((3, 2)))\n\n    def test_0_dense(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(True, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 2)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_0_sparse(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(True, False, 0.5)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 1)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_dense(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_sparse(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\nif __name__ == '__main__':\n    unittest.main()\n",
            "new_file_content": "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring\n\nimport os\nimport pickle\nimport unittest\nfrom unittest.mock import Mock\n\nimport numpy as np\nfrom scipy.sparse import csr_matrix\n\nfrom Orange.data import Table, Domain, ContinuousVariable\nfrom Orange.preprocess import EntropyMDL, DoNotImpute, Default, Average, \\\n    SelectRandomFeatures, EqualFreq, RemoveNaNColumns, DropInstances, \\\n    EqualWidth, SelectBestFeatures, RemoveNaNRows, Preprocess, Scale, \\\n    Randomize, Continuize, Discretize, Impute, SklImpute, Normalize, \\\n    ProjectCUR, ProjectPCA, RemoveConstant, AdaptiveNormalize, RemoveSparse\nfrom Orange.util import OrangeDeprecationWarning\n\n\nclass TestPreprocess(unittest.TestCase):\n    def test_read_data_calls_reader(self):\n        class MockPreprocessor(Preprocess):\n            __init__ = Mock(return_value=None)\n            __call__ = Mock()\n            @classmethod\n            def reset(cls):\n                cls.__init__.reset_mock()\n                cls.__call__.reset_mock()\n\n        table = Mock(Table)\n        MockPreprocessor(1, 2, a=3)(table)\n        MockPreprocessor.__init__.assert_called_with(1, 2, a=3)\n        MockPreprocessor.__call__.assert_called_with(table)\n        MockPreprocessor.reset()\n\n        MockPreprocessor(1, 2, a=3)\n        MockPreprocessor.__init__.assert_called_with(1, 2, a=3)\n        self.assertEqual(MockPreprocessor.__call__.call_count, 0)\n\n        MockPreprocessor(a=3)\n        MockPreprocessor.__init__.assert_called_with(a=3)\n        self.assertEqual(MockPreprocessor.__call__.call_count, 0)\n\n        MockPreprocessor()\n        MockPreprocessor.__init__.assert_called_with()\n        self.assertEqual(MockPreprocessor.__call__.call_count, 0)\n\n\nclass TestRemoveConstant(unittest.TestCase):\n    def test_remove_columns(self):\n        X = np.random.rand(6, 5)\n        X[:, (1, 3)] = 5\n        X[3, 1] = np.nan\n        X[1, 1] = np.nan\n        X[:, 4] = np.nan\n        data = Table(X)\n        d = RemoveConstant()(data)\n        self.assertEqual(len(d.domain.attributes), 2)\n\n        pp_rc = RemoveConstant()\n        d = pp_rc(data)\n        self.assertEqual(len(d.domain.attributes), 2)\n\n    def test_nothing_to_remove(self):\n        data = Table(\"iris\")\n        d = RemoveConstant()(data)\n        self.assertEqual(len(d.domain.attributes), 4)\n\n\nclass TestRemoveNaNRows(unittest.TestCase):\n    def test_remove_row(self):\n        data = Table(\"iris\")\n        data.X[0, 0] = np.nan\n        pp_data = RemoveNaNRows()(data)\n        self.assertEqual(len(pp_data), len(data) - 1)\n        self.assertFalse(np.isnan(pp_data.X).any())\n\n\nclass TestRemoveNaNColumns(unittest.TestCase):\n    def test_column_filtering(self):\n        data = Table(\"iris\")\n        data.X[:, (1, 3)] = np.NaN\n\n        new_data = RemoveNaNColumns()(data)\n        self.assertEqual(len(new_data.domain.attributes),\n                         len(data.domain.attributes) - 2)\n\n        data = Table(\"iris\")\n        data.X[0, 0] = np.NaN\n        new_data = RemoveNaNColumns()(data)\n        self.assertEqual(len(new_data.domain.attributes),\n                         len(data.domain.attributes))\n\n    def test_column_filtering_sparse(self):\n        data = Table(\"iris\")\n        data.X = csr_matrix(data.X)\n\n        new_data = RemoveNaNColumns()(data)\n        self.assertEqual(data, new_data)\n\n\nclass TestScaling(unittest.TestCase):\n    @classmethod\n    def setUpClass(cls):\n        cls.table = Table([[1, 2, 3],\n                           [2, 3, 4],\n                           [3, 4, 5],\n                           [4, 5, 6]])\n\n    def test_scaling_mean_span(self):\n        table = Scale(center=Scale.Mean, scale=Scale.Span)(self.table)\n        np.testing.assert_almost_equal(np.mean(table, 0), 0)\n        np.testing.assert_almost_equal(np.ptp(table, 0), 1)\n\n    def test_scaling_median_stddev(self):\n        table = Scale(center=Scale.Median, scale=Scale.Std)(self.table)\n        np.testing.assert_almost_equal(np.std(table, 0), 1)\n        # NB: This test just covers. The following fails. You figure it out.\n        # np.testing.assert_almost_equal(np.median(table, 0), 0)\n\n\nclass TestReprs(unittest.TestCase):\n    def test_reprs(self):\n        preprocs = [Continuize, Discretize, Impute, SklImpute, Normalize,\n                    Randomize, ProjectPCA, ProjectCUR, Scale,\n                    EqualFreq, EqualWidth, EntropyMDL, SelectBestFeatures,\n                    SelectRandomFeatures, RemoveNaNColumns, DoNotImpute, DropInstances,\n                    Average, Default, RemoveSparse]\n\n        for preproc in preprocs:\n            repr_str = repr(preproc())\n            new_preproc = eval(repr_str)\n            self.assertEqual(repr(new_preproc), repr_str)\n\n\nclass TestEnumPickling(unittest.TestCase):\n    def test_continuize_pickling(self):\n        c = Continuize(multinomial_treatment=Continuize.FirstAsBase)\n        s = pickle.dumps(c, -1)\n        c1 = pickle.loads(s)\n        self.assertIs(c1.multinomial_treatment, c.multinomial_treatment)\n\n    def test_randomize_pickling(self):\n        c = Randomize(rand_type=Randomize.RandomizeMetas)\n        s = pickle.dumps(c, -1)\n        c1 = pickle.loads(s)\n        self.assertIs(c1.rand_type, c.rand_type)\n\n    def test_scaling_pickling(self):\n        c = Scale(center=Scale.Median, scale=Scale.Span)\n        s = pickle.dumps(c, -1)\n        c1 = pickle.loads(s)\n        self.assertIs(c1.center, c.center)\n        self.assertIs(c1.scale, c.scale)\n\n\nclass TestAdaptiveNormalize(unittest.TestCase):\n    \"\"\"\n    Checks if output for sparse data is the same as for Scale\n    preprocessor. For dense data the output should match that\n     of Normalize preprocessor.\n    \"\"\"\n\n    def setUp(self):\n        self.data = Table(\"iris\")\n\n    def test_dense_pps(self):\n        true_out = Normalize()(self.data)\n        out = AdaptiveNormalize()(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_sparse_pps(self):\n        self.data.X = csr_matrix(self.data.X)\n        out = AdaptiveNormalize()(self.data)\n        true_out = Scale(center=Scale.NoCentering, scale=Scale.Span)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n        self.data = self.data.X.toarray()\n\n\nclass TestRemoveSparse(unittest.TestCase):\n\n    def setUp(self):\n        domain = Domain([ContinuousVariable('a'), ContinuousVariable('b')])\n        self.data = Table.from_numpy(domain, np.zeros((3, 2)))\n\n    def test_0_dense(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(True, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 2)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_0_sparse(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(True, False, 0.5)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 1)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_dense(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_sparse(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\nif __name__ == '__main__':\n    unittest.main()\n",
            "header": {
                "file": {
                    "path": "Orange/tests/test_preprocess.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "65dc540c1",
                "new_commit_hash": "00858d327",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/tests/test_preprocess.py"
            },
            "plus_file": {
                "path": "b/Orange/tests/test_preprocess.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 221,
                            "length": 6
                        },
                        "new_range": {
                            "start": 221,
                            "length": 8
                        },
                        "section": "class TestRemoveSparse(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.data.X[:, 0] = 7",
                                "type": "context"
                            },
                            {
                                "content": "        true_out = self.data[:, 0]",
                                "type": "context"
                            },
                            {
                                "content": "        true_out.X = true_out.X.reshape(-1, 1)",
                                "type": "context"
                            },
                            {
                                "content": "        self.data.X = csr_matrix(self.data.X)",
                                "type": "added"
                            },
                            {
                                "content": "        true_out.X = csr_matrix(true_out.X)",
                                "type": "added"
                            },
                            {
                                "content": "        out = RemoveSparse(False, False, 0.5)(self.data)",
                                "type": "context"
                            },
                            {
                                "content": "        np.testing.assert_array_equal(out, true_out)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/tests/test_preprocess.py",
                            "type": "method",
                            "name": "TestRemoveSparse.test_nan_sparse",
                            "content": "class TestRemoveSparse(unittest.TestCase):\n\n    def setUp(self):\n        domain = Domain([ContinuousVariable('a'), ContinuousVariable('b')])\n        self.data = Table.from_numpy(domain, np.zeros((3, 2)))\n\n    def test_0_dense(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(True, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 2)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_0_sparse(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(True, False, 0.5)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 1)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_dense(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_sparse(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 219,
                            "end_lineno": 230,
                            "parent": {
                                "file_name": "Orange/tests/test_preprocess.py",
                                "type": "class",
                                "name": "TestRemoveSparse",
                                "content": "class TestRemoveSparse(unittest.TestCase):\n\n    def setUp(self):\n        domain = Domain([ContinuousVariable('a'), ContinuousVariable('b')])\n        self.data = Table.from_numpy(domain, np.zeros((3, 2)))\n\n    def test_0_dense(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(True, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 2)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_0_sparse(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(True, False, 0.5)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 1)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_dense(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_sparse(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 181,
                                "end_lineno": 230,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "Orange/tests/test_preprocess.py",
                            "type": "class",
                            "name": "TestRemoveSparse",
                            "content": "class TestRemoveSparse(unittest.TestCase):\n\n    def setUp(self):\n        domain = Domain([ContinuousVariable('a'), ContinuousVariable('b')])\n        self.data = Table.from_numpy(domain, np.zeros((3, 2)))\n\n    def test_0_dense(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(True, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 2)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_0_sparse(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(True, False, 0.5)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 1)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_dense(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_sparse(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 181,
                            "end_lineno": 230,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring\nimport numpy as np\n\nfrom Orange.data import Table\nfrom Orange.preprocess import (\n    Randomize, Scale, Discretize, Continuize, Impute, ProjectPCA, \\\n         ProjectCUR, RemoveSparse\n)\nfrom Orange.preprocess import discretize, impute, fss, score\nfrom Orange.widgets.data import owpreprocess\nfrom Orange.widgets.data.owpreprocess import OWPreprocess, \\\n    UnivariateFeatureSelect, Scale as ScaleEditor\nfrom Orange.widgets.tests.base import WidgetTest, datasets\n\n\nclass TestOWPreprocess(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(OWPreprocess)\n        self.zoo = Table(\"zoo\")\n\n    def test_randomize(self):\n        saved = {\"preprocessors\": [(\"orange.preprocess.randomize\",\n                                    {\"rand_type\": Randomize.RandomizeClasses,\n                                     \"rand_seed\": 1})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, self.zoo)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        r = Randomize(Randomize.RandomizeClasses, rand_seed=1)\n        expected = r(self.zoo)\n\n        np.testing.assert_array_equal(expected.X, output.X)\n        np.testing.assert_array_equal(expected.Y, output.Y)\n        np.testing.assert_array_equal(expected.metas, output.metas)\n\n        np.testing.assert_array_equal(self.zoo.X, output.X)\n        np.testing.assert_array_equal(self.zoo.metas, output.metas)\n        self.assertFalse(np.array_equal(self.zoo.Y, output.Y))\n\n    def test_remove_sparse(self):\n        data = Table(\"iris\")\n        idx = int(data.X.shape[0]/10)\n        data.X[:idx+1, 0] = np.zeros((idx+1,))\n        saved = {\"preprocessors\": [(\"orange.preprocess.remove_sparse\",\n                                    {'filter0': True, 'useFixedThreshold': False,\n                                     'percThresh':10, 'fixedThresh': 50})]}\n        model = self.widget.load(saved)\n\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        np.testing.assert_array_equal(output.X, data.X[:, 1:])\n        np.testing.assert_array_equal(output.Y, data.Y)\n        np.testing.assert_array_equal(output.metas, data.metas)\n\n    def test_normalize(self):\n        data = Table(\"iris\")\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"method\": ScaleEditor.NormalizeBySD})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        np.testing.assert_allclose(output.X.mean(0), 0, atol=1e-7)\n        np.testing.assert_allclose(output.X.std(0), 1, atol=1e-7)\n\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"method\": ScaleEditor.CenterByMean})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        np.testing.assert_allclose(output.X.mean(0), 0, atol=1e-7)\n        self.assertTrue((output.X.std(0) > 0).all())\n\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"method\": ScaleEditor.ScaleBySD})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertTrue((output.X.mean(0) != 0).all())\n        np.testing.assert_allclose(output.X.std(0), 1, atol=1e-7)\n\n        saved = {\"preprocessors\":\n                 [(\"orange.preprocess.scale\",\n                   {\"method\": ScaleEditor.NormalizeBySpan_ZeroBased})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertAlmostEqual(output.X.min(), 0)\n        self.assertAlmostEqual(output.X.max(), 1)\n\n        saved = {\"preprocessors\":\n                 [(\"orange.preprocess.scale\",\n                   {\"method\": ScaleEditor.NormalizeSpan_NonZeroBased})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertAlmostEqual(output.X.min(), -1)\n        self.assertAlmostEqual(output.X.max(), 1)\n\n    def test_select_features(self):\n        data = Table(\"iris\")\n        saved = {\"preprocessors\": [(\"orange.preprocess.fss\",\n                                    {\"strategy\": UnivariateFeatureSelect.Fixed,\n                                     \"k\": 2})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertEqual(len(output.domain.attributes), 2)\n\n        saved = {\"preprocessors\": [\n            (\"orange.preprocess.fss\",\n             {\"strategy\": UnivariateFeatureSelect.Proportion,\n              \"p\": 75})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertEqual(len(output.domain.attributes), 3)\n\n    def test_data_column_nans(self):\n        \"\"\"\n        ZeroDivisonError - Weights sum to zero, can't be normalized\n        In case when all rows in a column are NaN then it throws that error.\n        GH-2064\n        \"\"\"\n        table = datasets.data_one_column_nans()\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"center\": Scale.CenteringType.Mean,\n                                     \"scale\": Scale.ScalingType.Std})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, table)\n\n\n# Test for editors\nclass TestDiscretizeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.DiscretizeEditor()\n        self.assertEqual(widget.parameters(),\n                         {\"method\": owpreprocess.DiscretizeEditor.EqualFreq,\n                          \"n\": 4})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Discretize)\n        self.assertIsInstance(p.method, discretize.EqualFreq)\n        widget.setParameters(\n            {\"method\": owpreprocess.DiscretizeEditor.EntropyMDL}\n        )\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Discretize)\n        self.assertIsInstance(p.method, discretize.EntropyMDL)\n\n        widget.setParameters(\n            {\"method\": owpreprocess.DiscretizeEditor.EqualWidth,\n             \"n\": 10}\n        )\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Discretize)\n        self.assertIsInstance(p.method, discretize.EqualWidth)\n        self.assertEqual(p.method.n, 10)\n\n\nclass TestContinuizeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.ContinuizeEditor()\n        self.assertEqual(widget.parameters(),\n                         {\"multinomial_treatment\": Continuize.Indicators})\n\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Continuize)\n        self.assertEqual(p.multinomial_treatment, Continuize.Indicators)\n\n        widget.setParameters(\n            {\"multinomial_treatment\": Continuize.FrequentAsBase})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Continuize)\n        self.assertEqual(p.multinomial_treatment, Continuize.FrequentAsBase)\n\n\nclass TestImputeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.ImputeEditor()\n        self.assertEqual(widget.parameters(),\n                         {\"method\": owpreprocess.ImputeEditor.Average})\n        widget.setParameters(\n            {\"method\": owpreprocess.ImputeEditor.Average}\n        )\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Impute)\n        self.assertIsInstance(p.method, impute.Average)\n\n\nclass TestFeatureSelectEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.FeatureSelectEditor()\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectBestFeatures)\n        self.assertIsInstance(p.method, score.InfoGain)\n        self.assertEqual(p.k, 10)\n\n        widget.setParameters({\"k\": 9999})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectBestFeatures)\n        self.assertEqual(p.k, 9999)\n\n\nclass TestRandomFeatureSelectEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.RandomFeatureSelectEditor()\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectRandomFeatures)\n        self.assertEqual(p.k, 10)\n\n        widget.setParameters({\"strategy\": owpreprocess.RandomFeatureSelectEditor.Fixed,\n                              \"k\": 9999})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectRandomFeatures)\n        self.assertEqual(p.k, 9999)\n\n        widget.setParameters(\n            {\"strategy\": owpreprocess.RandomFeatureSelectEditor.Percentage,\n             \"p\": 25})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectRandomFeatures)\n        self.assertEqual(p.k, 0.25)\n\n\nclass TestRandomizeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.Randomize()\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Randomize)\n        self.assertEqual(p.rand_type, Randomize.RandomizeClasses)\n\n        widget.setParameters({\"rand_type\": Randomize.RandomizeAttributes})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Randomize)\n        self.assertEqual(p.rand_type, Randomize.RandomizeAttributes)\n\n\nclass TestPCAEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.PCA()\n        self.assertEqual(widget.parameters(),\n                         {\"n_components\": 10})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectPCA)\n        self.assertEqual(p.n_components, 10)\n\n        widget.setParameters({\"n_components\": 5})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectPCA)\n        self.assertEqual(p.n_components, 5)\n\n\nclass TestCUREditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.CUR()\n        self.assertEqual(widget.parameters(),\n                         {\"rank\": 10, \"max_error\": 1})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectCUR)\n        self.assertEqual(p.rank, 10)\n        self.assertEqual(p.max_error, 1)\n\n        widget.setParameters({\"rank\": 9999})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectCUR)\n        self.assertEqual(p.rank, 9999)\n\n        widget.setParameters({\"rank\": 5, \"max_error\": 0.5})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectCUR)\n        self.assertEqual(p.rank, 5)\n        self.assertEqual(p.max_error, 0.5)\n\nclass TestRemoveSparseEditor(WidgetTest):\n\n    def test_editor(self):\n        widget = owpreprocess.RemoveSparseEditor()\n        self.assertEqual(widget.parameters(), {\"fixedThresh\" : 50,\n                                               \"percThresh\": 5,\n                                               \"filter0\" : True,\n                                               \"useFixedThreshold\": False})\n\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, False)\n        self.assertEqual(p.filter_0, True)\n        self.assertEqual(p.threshold, 5)\n\n        widget.setParameters({\"useFixedThreshold\" : True})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, True)\n",
            "new_file_content": "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring\nimport numpy as np\n\nfrom Orange.data import Table\nfrom Orange.preprocess import (\n    Randomize, Scale, Discretize, Continuize, Impute, ProjectPCA, \\\n         ProjectCUR, RemoveSparse\n)\nfrom Orange.preprocess import discretize, impute, fss, score\nfrom Orange.widgets.data import owpreprocess\nfrom Orange.widgets.data.owpreprocess import OWPreprocess, \\\n    UnivariateFeatureSelect, Scale as ScaleEditor\nfrom Orange.widgets.tests.base import WidgetTest, datasets\n\n\nclass TestOWPreprocess(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(OWPreprocess)\n        self.zoo = Table(\"zoo\")\n\n    def test_randomize(self):\n        saved = {\"preprocessors\": [(\"orange.preprocess.randomize\",\n                                    {\"rand_type\": Randomize.RandomizeClasses,\n                                     \"rand_seed\": 1})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, self.zoo)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        r = Randomize(Randomize.RandomizeClasses, rand_seed=1)\n        expected = r(self.zoo)\n\n        np.testing.assert_array_equal(expected.X, output.X)\n        np.testing.assert_array_equal(expected.Y, output.Y)\n        np.testing.assert_array_equal(expected.metas, output.metas)\n\n        np.testing.assert_array_equal(self.zoo.X, output.X)\n        np.testing.assert_array_equal(self.zoo.metas, output.metas)\n        self.assertFalse(np.array_equal(self.zoo.Y, output.Y))\n\n    def test_remove_sparse(self):\n        data = Table(\"iris\")\n        idx = int(data.X.shape[0]/10)\n        data.X[:idx+1, 0] = np.zeros((idx+1,))\n        saved = {\"preprocessors\": [(\"orange.preprocess.remove_sparse\",\n                                    {'filter0': True, 'useFixedThreshold': False,\n                                     'percThresh':10, 'fixedThresh': 50})]}\n        model = self.widget.load(saved)\n\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        np.testing.assert_array_equal(output.X, data.X[:, 1:])\n        np.testing.assert_array_equal(output.Y, data.Y)\n        np.testing.assert_array_equal(output.metas, data.metas)\n\n    def test_normalize(self):\n        data = Table(\"iris\")\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"method\": ScaleEditor.NormalizeBySD})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        np.testing.assert_allclose(output.X.mean(0), 0, atol=1e-7)\n        np.testing.assert_allclose(output.X.std(0), 1, atol=1e-7)\n\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"method\": ScaleEditor.CenterByMean})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        np.testing.assert_allclose(output.X.mean(0), 0, atol=1e-7)\n        self.assertTrue((output.X.std(0) > 0).all())\n\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"method\": ScaleEditor.ScaleBySD})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertTrue((output.X.mean(0) != 0).all())\n        np.testing.assert_allclose(output.X.std(0), 1, atol=1e-7)\n\n        saved = {\"preprocessors\":\n                 [(\"orange.preprocess.scale\",\n                   {\"method\": ScaleEditor.NormalizeBySpan_ZeroBased})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertAlmostEqual(output.X.min(), 0)\n        self.assertAlmostEqual(output.X.max(), 1)\n\n        saved = {\"preprocessors\":\n                 [(\"orange.preprocess.scale\",\n                   {\"method\": ScaleEditor.NormalizeSpan_NonZeroBased})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertAlmostEqual(output.X.min(), -1)\n        self.assertAlmostEqual(output.X.max(), 1)\n\n    def test_select_features(self):\n        data = Table(\"iris\")\n        saved = {\"preprocessors\": [(\"orange.preprocess.fss\",\n                                    {\"strategy\": UnivariateFeatureSelect.Fixed,\n                                     \"k\": 2})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertEqual(len(output.domain.attributes), 2)\n\n        saved = {\"preprocessors\": [\n            (\"orange.preprocess.fss\",\n             {\"strategy\": UnivariateFeatureSelect.Proportion,\n              \"p\": 75})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertEqual(len(output.domain.attributes), 3)\n\n    def test_data_column_nans(self):\n        \"\"\"\n        ZeroDivisonError - Weights sum to zero, can't be normalized\n        In case when all rows in a column are NaN then it throws that error.\n        GH-2064\n        \"\"\"\n        table = datasets.data_one_column_nans()\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"center\": Scale.CenteringType.Mean,\n                                     \"scale\": Scale.ScalingType.Std})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, table)\n\n\n# Test for editors\nclass TestDiscretizeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.DiscretizeEditor()\n        self.assertEqual(widget.parameters(),\n                         {\"method\": owpreprocess.DiscretizeEditor.EqualFreq,\n                          \"n\": 4})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Discretize)\n        self.assertIsInstance(p.method, discretize.EqualFreq)\n        widget.setParameters(\n            {\"method\": owpreprocess.DiscretizeEditor.EntropyMDL}\n        )\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Discretize)\n        self.assertIsInstance(p.method, discretize.EntropyMDL)\n\n        widget.setParameters(\n            {\"method\": owpreprocess.DiscretizeEditor.EqualWidth,\n             \"n\": 10}\n        )\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Discretize)\n        self.assertIsInstance(p.method, discretize.EqualWidth)\n        self.assertEqual(p.method.n, 10)\n\n\nclass TestContinuizeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.ContinuizeEditor()\n        self.assertEqual(widget.parameters(),\n                         {\"multinomial_treatment\": Continuize.Indicators})\n\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Continuize)\n        self.assertEqual(p.multinomial_treatment, Continuize.Indicators)\n\n        widget.setParameters(\n            {\"multinomial_treatment\": Continuize.FrequentAsBase})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Continuize)\n        self.assertEqual(p.multinomial_treatment, Continuize.FrequentAsBase)\n\n\nclass TestImputeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.ImputeEditor()\n        self.assertEqual(widget.parameters(),\n                         {\"method\": owpreprocess.ImputeEditor.Average})\n        widget.setParameters(\n            {\"method\": owpreprocess.ImputeEditor.Average}\n        )\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Impute)\n        self.assertIsInstance(p.method, impute.Average)\n\n\nclass TestFeatureSelectEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.FeatureSelectEditor()\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectBestFeatures)\n        self.assertIsInstance(p.method, score.InfoGain)\n        self.assertEqual(p.k, 10)\n\n        widget.setParameters({\"k\": 9999})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectBestFeatures)\n        self.assertEqual(p.k, 9999)\n\n\nclass TestRandomFeatureSelectEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.RandomFeatureSelectEditor()\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectRandomFeatures)\n        self.assertEqual(p.k, 10)\n\n        widget.setParameters({\"strategy\": owpreprocess.RandomFeatureSelectEditor.Fixed,\n                              \"k\": 9999})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectRandomFeatures)\n        self.assertEqual(p.k, 9999)\n\n        widget.setParameters(\n            {\"strategy\": owpreprocess.RandomFeatureSelectEditor.Percentage,\n             \"p\": 25})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectRandomFeatures)\n        self.assertEqual(p.k, 0.25)\n\n\nclass TestRandomizeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.Randomize()\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Randomize)\n        self.assertEqual(p.rand_type, Randomize.RandomizeClasses)\n\n        widget.setParameters({\"rand_type\": Randomize.RandomizeAttributes})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Randomize)\n        self.assertEqual(p.rand_type, Randomize.RandomizeAttributes)\n\n\nclass TestPCAEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.PCA()\n        self.assertEqual(widget.parameters(),\n                         {\"n_components\": 10})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectPCA)\n        self.assertEqual(p.n_components, 10)\n\n        widget.setParameters({\"n_components\": 5})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectPCA)\n        self.assertEqual(p.n_components, 5)\n\n\nclass TestCUREditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.CUR()\n        self.assertEqual(widget.parameters(),\n                         {\"rank\": 10, \"max_error\": 1})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectCUR)\n        self.assertEqual(p.rank, 10)\n        self.assertEqual(p.max_error, 1)\n\n        widget.setParameters({\"rank\": 9999})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectCUR)\n        self.assertEqual(p.rank, 9999)\n\n        widget.setParameters({\"rank\": 5, \"max_error\": 0.5})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectCUR)\n        self.assertEqual(p.rank, 5)\n        self.assertEqual(p.max_error, 0.5)\n\nclass TestRemoveSparseEditor(WidgetTest):\n\n    def test_editor(self):\n        widget = owpreprocess.RemoveSparseEditor()\n        self.assertEqual(widget.parameters(), {\"fixedThresh\" : 50,\n                                               \"percThresh\": 5,\n                                               \"filter0\" : True,\n                                               \"useFixedThreshold\": False})\n\n        p = widget.createinstance(widget.parameters())\n        widget.filterSettingsClicked()\n        self.assertTrue(widget.percSpin.isEnabled())\n        self.assertFalse(widget.fixedSpin.isEnabled())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, False)\n        self.assertEqual(p.filter_0, True)\n        self.assertEqual(p.threshold, 5)\n\n        widget.setParameters({\"useFixedThreshold\" : True,\n                              \"fixedThresh\" : 30,\n                              \"filter0\" : False})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, True)\n        self.assertEqual(p.threshold, 30)\n        self.assertFalse(p.filter_0)\n",
            "header": {
                "file": {
                    "path": "Orange/widgets/data/tests/test_owpreprocess.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "c67a84d52",
                "new_commit_hash": "c46a6bb9c",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/widgets/data/tests/test_owpreprocess.py"
            },
            "plus_file": {
                "path": "b/Orange/widgets/data/tests/test_owpreprocess.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 290,
                            "length": 12
                        },
                        "new_range": {
                            "start": 290,
                            "length": 19
                        },
                        "section": "class TestRemoveSparseEditor(WidgetTest):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "                                               \"useFixedThreshold\": False})",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        p = widget.createinstance(widget.parameters())",
                                "type": "context"
                            },
                            {
                                "content": "        widget.filterSettingsClicked()",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertTrue(widget.percSpin.isEnabled())",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertFalse(widget.fixedSpin.isEnabled())",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertIsInstance(p, RemoveSparse)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(p.fixed_threshold, False)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(p.filter_0, True)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(p.threshold, 5)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        widget.setParameters({\"useFixedThreshold\" : True})",
                                "type": "deleted"
                            },
                            {
                                "content": "        widget.setParameters({\"useFixedThreshold\" : True,",
                                "type": "added"
                            },
                            {
                                "content": "                              \"fixedThresh\" : 30,",
                                "type": "added"
                            },
                            {
                                "content": "                              \"filter0\" : False})",
                                "type": "added"
                            },
                            {
                                "content": "        p = widget.createinstance(widget.parameters())",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertIsInstance(p, RemoveSparse)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(p.fixed_threshold, True)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(p.threshold, 30)",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertFalse(p.filter_0)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/data/tests/test_owpreprocess.py",
                            "type": "class",
                            "name": "TestRemoveSparseEditor",
                            "content": "class TestRemoveSparseEditor(WidgetTest):\n\n    def test_editor(self):\n        widget = owpreprocess.RemoveSparseEditor()\n        self.assertEqual(widget.parameters(), {\"fixedThresh\" : 50,\n                                               \"percThresh\": 5,\n                                               \"filter0\" : True,\n                                               \"useFixedThreshold\": False})\n\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, False)\n        self.assertEqual(p.filter_0, True)\n        self.assertEqual(p.threshold, 5)\n\n        widget.setParameters({\"useFixedThreshold\" : True})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, True)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 283,
                            "end_lineno": 301,
                            "parent": null
                        },
                        {
                            "file_name": "Orange/widgets/data/tests/test_owpreprocess.py",
                            "type": "method",
                            "name": "TestRemoveSparseEditor.test_editor",
                            "content": "class TestRemoveSparseEditor(WidgetTest):\n\n    def test_editor(self):\n        widget = owpreprocess.RemoveSparseEditor()\n        self.assertEqual(widget.parameters(), {\"fixedThresh\" : 50,\n                                               \"percThresh\": 5,\n                                               \"filter0\" : True,\n                                               \"useFixedThreshold\": False})\n\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, False)\n        self.assertEqual(p.filter_0, True)\n        self.assertEqual(p.threshold, 5)\n\n        widget.setParameters({\"useFixedThreshold\" : True})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, True)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 285,
                            "end_lineno": 301,
                            "parent": {
                                "file_name": "Orange/widgets/data/tests/test_owpreprocess.py",
                                "type": "class",
                                "name": "TestRemoveSparseEditor",
                                "content": "class TestRemoveSparseEditor(WidgetTest):\n\n    def test_editor(self):\n        widget = owpreprocess.RemoveSparseEditor()\n        self.assertEqual(widget.parameters(), {\"fixedThresh\" : 50,\n                                               \"percThresh\": 5,\n                                               \"filter0\" : True,\n                                               \"useFixedThreshold\": False})\n\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, False)\n        self.assertEqual(p.filter_0, True)\n        self.assertEqual(p.threshold, 5)\n\n        widget.setParameters({\"useFixedThreshold\" : True})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, True)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 283,
                                "end_lineno": 301,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "ce493b09494c007b27c6fbc5944636136fedd6e3^",
    "new_commit_hash": "ce493b09494c007b27c6fbc5944636136fedd6e3",
    "commit_message": "Add tests",
    "commit_date": "2019-12-13T13:49:40+01:00",
    "metadata": {}
}
{
    "repo_name": "orange3",
    "new_commit_hash": "ce493b09494c007b27c6fbc5944636136fedd6e3",
    "test_file_codes": [
        "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring\n\nimport os\nimport pickle\nimport unittest\nfrom unittest.mock import Mock\n\nimport numpy as np\nfrom scipy.sparse import csr_matrix\n\nfrom Orange.data import Table, Domain, ContinuousVariable\nfrom Orange.preprocess import EntropyMDL, DoNotImpute, Default, Average, \\\n    SelectRandomFeatures, EqualFreq, RemoveNaNColumns, DropInstances, \\\n    EqualWidth, SelectBestFeatures, RemoveNaNRows, Preprocess, Scale, \\\n    Randomize, Continuize, Discretize, Impute, SklImpute, Normalize, \\\n    ProjectCUR, ProjectPCA, RemoveConstant, AdaptiveNormalize, RemoveSparse\nfrom Orange.util import OrangeDeprecationWarning\n\n\nclass TestPreprocess(unittest.TestCase):\n    def test_read_data_calls_reader(self):\n        class MockPreprocessor(Preprocess):\n            __init__ = Mock(return_value=None)\n            __call__ = Mock()\n            @classmethod\n            def reset(cls):\n                cls.__init__.reset_mock()\n                cls.__call__.reset_mock()\n\n        table = Mock(Table)\n        MockPreprocessor(1, 2, a=3)(table)\n        MockPreprocessor.__init__.assert_called_with(1, 2, a=3)\n        MockPreprocessor.__call__.assert_called_with(table)\n        MockPreprocessor.reset()\n\n        MockPreprocessor(1, 2, a=3)\n        MockPreprocessor.__init__.assert_called_with(1, 2, a=3)\n        self.assertEqual(MockPreprocessor.__call__.call_count, 0)\n\n        MockPreprocessor(a=3)\n        MockPreprocessor.__init__.assert_called_with(a=3)\n        self.assertEqual(MockPreprocessor.__call__.call_count, 0)\n\n        MockPreprocessor()\n        MockPreprocessor.__init__.assert_called_with()\n        self.assertEqual(MockPreprocessor.__call__.call_count, 0)\n\n\nclass TestRemoveConstant(unittest.TestCase):\n    def test_remove_columns(self):\n        X = np.random.rand(6, 5)\n        X[:, (1, 3)] = 5\n        X[3, 1] = np.nan\n        X[1, 1] = np.nan\n        X[:, 4] = np.nan\n        data = Table(X)\n        d = RemoveConstant()(data)\n        self.assertEqual(len(d.domain.attributes), 2)\n\n        pp_rc = RemoveConstant()\n        d = pp_rc(data)\n        self.assertEqual(len(d.domain.attributes), 2)\n\n    def test_nothing_to_remove(self):\n        data = Table(\"iris\")\n        d = RemoveConstant()(data)\n        self.assertEqual(len(d.domain.attributes), 4)\n\n\nclass TestRemoveNaNRows(unittest.TestCase):\n    def test_remove_row(self):\n        data = Table(\"iris\")\n        data.X[0, 0] = np.nan\n        pp_data = RemoveNaNRows()(data)\n        self.assertEqual(len(pp_data), len(data) - 1)\n        self.assertFalse(np.isnan(pp_data.X).any())\n\n\nclass TestRemoveNaNColumns(unittest.TestCase):\n    def test_column_filtering(self):\n        data = Table(\"iris\")\n        data.X[:, (1, 3)] = np.NaN\n\n        new_data = RemoveNaNColumns()(data)\n        self.assertEqual(len(new_data.domain.attributes),\n                         len(data.domain.attributes) - 2)\n\n        data = Table(\"iris\")\n        data.X[0, 0] = np.NaN\n        new_data = RemoveNaNColumns()(data)\n        self.assertEqual(len(new_data.domain.attributes),\n                         len(data.domain.attributes))\n\n    def test_column_filtering_sparse(self):\n        data = Table(\"iris\")\n        data.X = csr_matrix(data.X)\n\n        new_data = RemoveNaNColumns()(data)\n        self.assertEqual(data, new_data)\n\n\nclass TestScaling(unittest.TestCase):\n    @classmethod\n    def setUpClass(cls):\n        cls.table = Table([[1, 2, 3],\n                           [2, 3, 4],\n                           [3, 4, 5],\n                           [4, 5, 6]])\n\n    def test_scaling_mean_span(self):\n        table = Scale(center=Scale.Mean, scale=Scale.Span)(self.table)\n        np.testing.assert_almost_equal(np.mean(table, 0), 0)\n        np.testing.assert_almost_equal(np.ptp(table, 0), 1)\n\n    def test_scaling_median_stddev(self):\n        table = Scale(center=Scale.Median, scale=Scale.Std)(self.table)\n        np.testing.assert_almost_equal(np.std(table, 0), 1)\n        # NB: This test just covers. The following fails. You figure it out.\n        # np.testing.assert_almost_equal(np.median(table, 0), 0)\n\n\nclass TestReprs(unittest.TestCase):\n    def test_reprs(self):\n        preprocs = [Continuize, Discretize, Impute, SklImpute, Normalize,\n                    Randomize, ProjectPCA, ProjectCUR, Scale,\n                    EqualFreq, EqualWidth, EntropyMDL, SelectBestFeatures,\n                    SelectRandomFeatures, RemoveNaNColumns, DoNotImpute, DropInstances,\n                    Average, Default, RemoveSparse]\n\n        for preproc in preprocs:\n            repr_str = repr(preproc())\n            new_preproc = eval(repr_str)\n            self.assertEqual(repr(new_preproc), repr_str)\n\n\nclass TestEnumPickling(unittest.TestCase):\n    def test_continuize_pickling(self):\n        c = Continuize(multinomial_treatment=Continuize.FirstAsBase)\n        s = pickle.dumps(c, -1)\n        c1 = pickle.loads(s)\n        self.assertIs(c1.multinomial_treatment, c.multinomial_treatment)\n\n    def test_randomize_pickling(self):\n        c = Randomize(rand_type=Randomize.RandomizeMetas)\n        s = pickle.dumps(c, -1)\n        c1 = pickle.loads(s)\n        self.assertIs(c1.rand_type, c.rand_type)\n\n    def test_scaling_pickling(self):\n        c = Scale(center=Scale.Median, scale=Scale.Span)\n        s = pickle.dumps(c, -1)\n        c1 = pickle.loads(s)\n        self.assertIs(c1.center, c.center)\n        self.assertIs(c1.scale, c.scale)\n\n\nclass TestAdaptiveNormalize(unittest.TestCase):\n    \"\"\"\n    Checks if output for sparse data is the same as for Scale\n    preprocessor. For dense data the output should match that\n     of Normalize preprocessor.\n    \"\"\"\n\n    def setUp(self):\n        self.data = Table(\"iris\")\n\n    def test_dense_pps(self):\n        true_out = Normalize()(self.data)\n        out = AdaptiveNormalize()(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_sparse_pps(self):\n        self.data.X = csr_matrix(self.data.X)\n        out = AdaptiveNormalize()(self.data)\n        true_out = Scale(center=Scale.NoCentering, scale=Scale.Span)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n        self.data = self.data.X.toarray()\n\n\nclass TestRemoveSparse(unittest.TestCase):\n\n    def setUp(self):\n        domain = Domain([ContinuousVariable('a'), ContinuousVariable('b')])\n        self.data = Table.from_numpy(domain, np.zeros((3, 2)))\n\n    def test_0_dense(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(True, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 2)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_0_sparse(self):\n        self.data[1:, 1] = 7\n        true_out = self.data[:, 1]\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(True, False, 0.5)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(True, True, 1)(self.data).X\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_dense(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n    def test_nan_sparse(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n        out = RemoveSparse(False, False, 0.5)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\n        out = RemoveSparse(False, True, 1)(self.data)\n        np.testing.assert_array_equal(out, true_out)\n\nif __name__ == '__main__':\n    unittest.main()\n",
        "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring\nimport numpy as np\n\nfrom Orange.data import Table\nfrom Orange.preprocess import (\n    Randomize, Scale, Discretize, Continuize, Impute, ProjectPCA, \\\n         ProjectCUR, RemoveSparse\n)\nfrom Orange.preprocess import discretize, impute, fss, score\nfrom Orange.widgets.data import owpreprocess\nfrom Orange.widgets.data.owpreprocess import OWPreprocess, \\\n    UnivariateFeatureSelect, Scale as ScaleEditor\nfrom Orange.widgets.tests.base import WidgetTest, datasets\n\n\nclass TestOWPreprocess(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(OWPreprocess)\n        self.zoo = Table(\"zoo\")\n\n    def test_randomize(self):\n        saved = {\"preprocessors\": [(\"orange.preprocess.randomize\",\n                                    {\"rand_type\": Randomize.RandomizeClasses,\n                                     \"rand_seed\": 1})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, self.zoo)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        r = Randomize(Randomize.RandomizeClasses, rand_seed=1)\n        expected = r(self.zoo)\n\n        np.testing.assert_array_equal(expected.X, output.X)\n        np.testing.assert_array_equal(expected.Y, output.Y)\n        np.testing.assert_array_equal(expected.metas, output.metas)\n\n        np.testing.assert_array_equal(self.zoo.X, output.X)\n        np.testing.assert_array_equal(self.zoo.metas, output.metas)\n        self.assertFalse(np.array_equal(self.zoo.Y, output.Y))\n\n    def test_remove_sparse(self):\n        data = Table(\"iris\")\n        idx = int(data.X.shape[0]/10)\n        data.X[:idx+1, 0] = np.zeros((idx+1,))\n        saved = {\"preprocessors\": [(\"orange.preprocess.remove_sparse\",\n                                    {'filter0': True, 'useFixedThreshold': False,\n                                     'percThresh':10, 'fixedThresh': 50})]}\n        model = self.widget.load(saved)\n\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        np.testing.assert_array_equal(output.X, data.X[:, 1:])\n        np.testing.assert_array_equal(output.Y, data.Y)\n        np.testing.assert_array_equal(output.metas, data.metas)\n\n    def test_normalize(self):\n        data = Table(\"iris\")\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"method\": ScaleEditor.NormalizeBySD})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        np.testing.assert_allclose(output.X.mean(0), 0, atol=1e-7)\n        np.testing.assert_allclose(output.X.std(0), 1, atol=1e-7)\n\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"method\": ScaleEditor.CenterByMean})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        np.testing.assert_allclose(output.X.mean(0), 0, atol=1e-7)\n        self.assertTrue((output.X.std(0) > 0).all())\n\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"method\": ScaleEditor.ScaleBySD})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertTrue((output.X.mean(0) != 0).all())\n        np.testing.assert_allclose(output.X.std(0), 1, atol=1e-7)\n\n        saved = {\"preprocessors\":\n                 [(\"orange.preprocess.scale\",\n                   {\"method\": ScaleEditor.NormalizeBySpan_ZeroBased})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertAlmostEqual(output.X.min(), 0)\n        self.assertAlmostEqual(output.X.max(), 1)\n\n        saved = {\"preprocessors\":\n                 [(\"orange.preprocess.scale\",\n                   {\"method\": ScaleEditor.NormalizeSpan_NonZeroBased})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertAlmostEqual(output.X.min(), -1)\n        self.assertAlmostEqual(output.X.max(), 1)\n\n    def test_select_features(self):\n        data = Table(\"iris\")\n        saved = {\"preprocessors\": [(\"orange.preprocess.fss\",\n                                    {\"strategy\": UnivariateFeatureSelect.Fixed,\n                                     \"k\": 2})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertEqual(len(output.domain.attributes), 2)\n\n        saved = {\"preprocessors\": [\n            (\"orange.preprocess.fss\",\n             {\"strategy\": UnivariateFeatureSelect.Proportion,\n              \"p\": 75})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, data)\n        output = self.get_output(self.widget.Outputs.preprocessed_data)\n        self.assertEqual(len(output.domain.attributes), 3)\n\n    def test_data_column_nans(self):\n        \"\"\"\n        ZeroDivisonError - Weights sum to zero, can't be normalized\n        In case when all rows in a column are NaN then it throws that error.\n        GH-2064\n        \"\"\"\n        table = datasets.data_one_column_nans()\n        saved = {\"preprocessors\": [(\"orange.preprocess.scale\",\n                                    {\"center\": Scale.CenteringType.Mean,\n                                     \"scale\": Scale.ScalingType.Std})]}\n        model = self.widget.load(saved)\n        self.widget.set_model(model)\n        self.send_signal(self.widget.Inputs.data, table)\n\n\n# Test for editors\nclass TestDiscretizeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.DiscretizeEditor()\n        self.assertEqual(widget.parameters(),\n                         {\"method\": owpreprocess.DiscretizeEditor.EqualFreq,\n                          \"n\": 4})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Discretize)\n        self.assertIsInstance(p.method, discretize.EqualFreq)\n        widget.setParameters(\n            {\"method\": owpreprocess.DiscretizeEditor.EntropyMDL}\n        )\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Discretize)\n        self.assertIsInstance(p.method, discretize.EntropyMDL)\n\n        widget.setParameters(\n            {\"method\": owpreprocess.DiscretizeEditor.EqualWidth,\n             \"n\": 10}\n        )\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Discretize)\n        self.assertIsInstance(p.method, discretize.EqualWidth)\n        self.assertEqual(p.method.n, 10)\n\n\nclass TestContinuizeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.ContinuizeEditor()\n        self.assertEqual(widget.parameters(),\n                         {\"multinomial_treatment\": Continuize.Indicators})\n\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Continuize)\n        self.assertEqual(p.multinomial_treatment, Continuize.Indicators)\n\n        widget.setParameters(\n            {\"multinomial_treatment\": Continuize.FrequentAsBase})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Continuize)\n        self.assertEqual(p.multinomial_treatment, Continuize.FrequentAsBase)\n\n\nclass TestImputeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.ImputeEditor()\n        self.assertEqual(widget.parameters(),\n                         {\"method\": owpreprocess.ImputeEditor.Average})\n        widget.setParameters(\n            {\"method\": owpreprocess.ImputeEditor.Average}\n        )\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Impute)\n        self.assertIsInstance(p.method, impute.Average)\n\n\nclass TestFeatureSelectEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.FeatureSelectEditor()\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectBestFeatures)\n        self.assertIsInstance(p.method, score.InfoGain)\n        self.assertEqual(p.k, 10)\n\n        widget.setParameters({\"k\": 9999})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectBestFeatures)\n        self.assertEqual(p.k, 9999)\n\n\nclass TestRandomFeatureSelectEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.RandomFeatureSelectEditor()\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectRandomFeatures)\n        self.assertEqual(p.k, 10)\n\n        widget.setParameters({\"strategy\": owpreprocess.RandomFeatureSelectEditor.Fixed,\n                              \"k\": 9999})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectRandomFeatures)\n        self.assertEqual(p.k, 9999)\n\n        widget.setParameters(\n            {\"strategy\": owpreprocess.RandomFeatureSelectEditor.Percentage,\n             \"p\": 25})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, fss.SelectRandomFeatures)\n        self.assertEqual(p.k, 0.25)\n\n\nclass TestRandomizeEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.Randomize()\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Randomize)\n        self.assertEqual(p.rand_type, Randomize.RandomizeClasses)\n\n        widget.setParameters({\"rand_type\": Randomize.RandomizeAttributes})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, Randomize)\n        self.assertEqual(p.rand_type, Randomize.RandomizeAttributes)\n\n\nclass TestPCAEditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.PCA()\n        self.assertEqual(widget.parameters(),\n                         {\"n_components\": 10})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectPCA)\n        self.assertEqual(p.n_components, 10)\n\n        widget.setParameters({\"n_components\": 5})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectPCA)\n        self.assertEqual(p.n_components, 5)\n\n\nclass TestCUREditor(WidgetTest):\n    def test_editor(self):\n        widget = owpreprocess.CUR()\n        self.assertEqual(widget.parameters(),\n                         {\"rank\": 10, \"max_error\": 1})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectCUR)\n        self.assertEqual(p.rank, 10)\n        self.assertEqual(p.max_error, 1)\n\n        widget.setParameters({\"rank\": 9999})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectCUR)\n        self.assertEqual(p.rank, 9999)\n\n        widget.setParameters({\"rank\": 5, \"max_error\": 0.5})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, ProjectCUR)\n        self.assertEqual(p.rank, 5)\n        self.assertEqual(p.max_error, 0.5)\n\nclass TestRemoveSparseEditor(WidgetTest):\n\n    def test_editor(self):\n        widget = owpreprocess.RemoveSparseEditor()\n        self.assertEqual(widget.parameters(), {\"fixedThresh\" : 50,\n                                               \"percThresh\": 5,\n                                               \"filter0\" : True,\n                                               \"useFixedThreshold\": False})\n\n        p = widget.createinstance(widget.parameters())\n        widget.filterSettingsClicked()\n        self.assertTrue(widget.percSpin.isEnabled())\n        self.assertFalse(widget.fixedSpin.isEnabled())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, False)\n        self.assertEqual(p.filter_0, True)\n        self.assertEqual(p.threshold, 5)\n\n        widget.setParameters({\"useFixedThreshold\" : True,\n                              \"fixedThresh\" : 30,\n                              \"filter0\" : False})\n        p = widget.createinstance(widget.parameters())\n        self.assertIsInstance(p, RemoveSparse)\n        self.assertEqual(p.fixed_threshold, True)\n        self.assertEqual(p.threshold, 30)\n        self.assertFalse(p.filter_0)\n"
    ],
    "test_file_names": [
        "test_1.py",
        "test_2.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Starting Orange installation attempts...\nAttempting installation with Python 3.7...\nrunning build_ext\nrunning build_src\nbuild_src\nbuilding extension \"Orange.classification._simple_tree\" sources\nbuilding extension \"Orange.classification._tree_scorers\" sources\nbuilding extension \"Orange.data._valuecount\" sources\nbuilding extension \"Orange.data._contingency\" sources\nbuilding extension \"Orange.data._io\" sources\nbuilding extension \"Orange.data._variable\" sources\nbuilding extension \"Orange.distance._distance\" sources\nbuilding extension \"Orange.preprocess._discretize\" sources\nbuilding extension \"Orange.preprocess._relieff\" sources\nbuilding extension \"Orange.projection._som\" sources\nbuilding extension \"Orange.widgets.utils._grid_density\" sources\nbuild_src: building npy-pkg config files\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmpg9wydjf4/tmp\ncreating /tmp/tmpg9wydjf4/tmp/tmpg9wydjf4\ncompile options: '-MMD -MF /tmp/tmpg9wydjf4/file.c.d -c'\ncc: /tmp/tmpg9wydjf4/file.c\ncustomize UnixCCompiler using build_ext\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmpbavuw1cu/tmp\ncreating /tmp/tmpbavuw1cu/tmp/tmpbavuw1cu\ncompile options: '-MMD -MF /tmp/tmpbavuw1cu/file.c.d -c'\ncc: /tmp/tmpbavuw1cu/file.c\ncustomize UnixCCompiler using build_ext\nbuilding 'Orange.classification._simple_tree' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange\ncreating build/temp.linux-x86_64-3.7/Orange/classification\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/classification/_simple_tree.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/classification/_simple_tree.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/classification/_simple_tree.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.classification._tree_scorers' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/classification/_tree_scorers.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/classification/_tree_scorers.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/classification/_tree_scorers.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._valuecount' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/data\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_valuecount.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_valuecount.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_valuecount.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._contingency' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_contingency.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_contingency.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_contingency.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._io' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_io.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_io.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_io.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._variable' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_variable.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_variable.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_variable.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.distance._distance' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/distance\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/distance/_distance.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/distance/_distance.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/distance/_distance.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.preprocess._discretize' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/preprocess\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/preprocess/_discretize.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/preprocess/_discretize.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/preprocess/_discretize.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.preprocess._relieff' extension\ncompiling C++ sources\nC compiler: c++ -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\nc++: Orange/preprocess/_relieff.cpp\nc++ -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/preprocess/_relieff.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/preprocess/_relieff.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.projection._som' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/projection\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/projection/_som.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/projection/_som.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/projection/_som.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.widgets.utils._grid_density' extension\ncompiling C++ sources\nC compiler: c++ -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/widgets\ncreating build/temp.linux-x86_64-3.7/Orange/widgets/utils\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\nc++: Orange/widgets/utils/_grid_density.cpp\nc++ -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/widgets/utils/_grid_density.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/widgets/utils/_grid_density.cpython-37m-x86_64-linux-gnu.so\nrunning develop\nrunning build_scripts\nrunning egg_info\nrunning build_src\nbuild_src\nbuilding extension \"Orange.classification._simple_tree\" sources\nbuilding extension \"Orange.classification._tree_scorers\" sources\nbuilding extension \"Orange.data._valuecount\" sources\nbuilding extension \"Orange.data._contingency\" sources\nbuilding extension \"Orange.data._io\" sources\nbuilding extension \"Orange.data._variable\" sources\nbuilding extension \"Orange.distance._distance\" sources\nbuilding extension \"Orange.preprocess._discretize\" sources\nbuilding extension \"Orange.preprocess._relieff\" sources\nbuilding extension \"Orange.projection._som\" sources\nbuilding extension \"Orange.widgets.utils._grid_density\" sources\nbuild_src: building npy-pkg config files\ncreating Orange3.egg-info\nwriting Orange3.egg-info/PKG-INFO\nwriting dependency_links to Orange3.egg-info/dependency_links.txt\nwriting entry points to Orange3.egg-info/entry_points.txt\nwriting requirements to Orange3.egg-info/requires.txt\nwriting top-level names to Orange3.egg-info/top_level.txt\nwriting manifest file 'Orange3.egg-info/SOURCES.txt'\nreading manifest file 'Orange3.egg-info/SOURCES.txt'\nreading manifest template 'MANIFEST.in'\nwarning: no files found matching 'README*' under directory 'Orange'\nwarning: no files found matching 'LICENSE' under directory 'Orange'\nwarning: no files found matching '*.basket' under directory 'Orange/datasets'\nwarning: no files found matching '*.js' under directory 'Orange/widgets'\nwarning: no files found matching '*.css' under directory 'Orange/widgets'\nwarning: no files found matching '*.html' under directory 'Orange/widgets'\nwarning: no files found matching 'COPYING'\nadding license file 'LICENSE'\nwriting manifest file 'Orange3.egg-info/SOURCES.txt'\nrunning build_ext\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmp7xquw976/tmp\ncreating /tmp/tmp7xquw976/tmp/tmp7xquw976\ncompile options: '-MMD -MF /tmp/tmp7xquw976/file.c.d -c'\ncc: /tmp/tmp7xquw976/file.c\ncustomize UnixCCompiler using build_ext\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmpjqr00gdz/tmp\ncreating /tmp/tmpjqr00gdz/tmp/tmpjqr00gdz\ncompile options: '-MMD -MF /tmp/tmpjqr00gdz/file.c.d -c'\ncc: /tmp/tmpjqr00gdz/file.c\ncustomize UnixCCompiler using build_ext\nCreating /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/Orange3.egg-link (link to .)\nAdding Orange3 3.24.0.dev0+ce493b0 to easy-install.pth file\nInstalling orange-canvas script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\n\nInstalled /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3\nProcessing dependencies for Orange3==3.24.0.dev0+ce493b0\nSearching for XlsxWriter==3.2.0\nBest match: XlsxWriter 3.2.0\nAdding XlsxWriter 3.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for xlrd==2.0.1\nBest match: xlrd 2.0.1\nAdding xlrd 2.0.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for setuptools==59.8.0\nBest match: setuptools 59.8.0\nAdding setuptools 59.8.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for serverfiles==0.3.1\nBest match: serverfiles 0.3.1\nAdding serverfiles 0.3.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for scipy==1.7.3\nBest match: scipy 1.7.3\nAdding scipy 1.7.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for scikit-learn==1.0.2\nBest match: scikit-learn 1.0.2\nAdding scikit-learn 1.0.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for requests==2.31.0\nBest match: requests 2.31.0\nAdding requests 2.31.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for PyYAML==6.0.1\nBest match: PyYAML 6.0.1\nAdding PyYAML 6.0.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for python-louvain==0.16\nBest match: python-louvain 0.16\nAdding python-louvain 0.16 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for pyqtgraph==0.12.4\nBest match: pyqtgraph 0.12.4\nAdding pyqtgraph 0.12.4 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for pip==24.0\nBest match: pip 24.0\nAdding pip 24.0 to easy-install.pth file\nInstalling pip script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\nInstalling pip3 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\nInstalling pip3.10 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for pandas==1.3.5\nBest match: pandas 1.3.5\nAdding pandas 1.3.5 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for orange-widget-base==4.22.0\nBest match: orange-widget-base 4.22.0\nAdding orange-widget-base 4.22.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for orange-canvas-core==0.1.35\nBest match: orange-canvas-core 0.1.35\nAdding orange-canvas-core 0.1.35 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for openTSNE==1.0.1\nBest match: openTSNE 1.0.1\nAdding openTSNE 1.0.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for numpy==1.17.5\nBest match: numpy 1.17.5\nAdding numpy 1.17.5 to easy-install.pth file\nInstalling f2py script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\nInstalling f2py3 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\nInstalling f2py3.7 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for networkx==2.6.3\nBest match: networkx 2.6.3\nAdding networkx 2.6.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for matplotlib==3.5.3\nBest match: matplotlib 3.5.3\nAdding matplotlib 3.5.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for keyrings.alt==4.2.0\nBest match: keyrings.alt 4.2.0\nAdding keyrings.alt 4.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for keyring==24.1.1\nBest match: keyring 24.1.1\nAdding keyring 24.1.1 to easy-install.pth file\nInstalling keyring script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for joblib==1.3.2\nBest match: joblib 1.3.2\nAdding joblib 1.3.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for docutils==0.20.1\nBest match: docutils 0.20.1\nAdding docutils 0.20.1 to easy-install.pth file\nInstalling docutils script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for chardet==5.2.0\nBest match: chardet 5.2.0\nAdding chardet 5.2.0 to easy-install.pth file\nInstalling chardetect script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for Bottleneck==1.4.0\nBest match: Bottleneck 1.4.0\nAdding Bottleneck 1.4.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for AnyQt==0.2.0\nBest match: AnyQt 0.2.0\nAdding AnyQt 0.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for threadpoolctl==3.1.0\nBest match: threadpoolctl 3.1.0\nAdding threadpoolctl 3.1.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for certifi==2024.12.14\nBest match: certifi 2024.12.14\nAdding certifi 2024.12.14 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for idna==3.10\nBest match: idna 3.10\nAdding idna 3.10 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for urllib3==2.0.7\nBest match: urllib3 2.0.7\nAdding urllib3 2.0.7 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for charset-normalizer==3.4.1\nBest match: charset-normalizer 3.4.1\nAdding charset-normalizer 3.4.1 to easy-install.pth file\nInstalling normalizer script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for python-dateutil==2.9.0.post0\nBest match: python-dateutil 2.9.0.post0\nAdding python-dateutil 2.9.0.post0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for pytz==2024.2\nBest match: pytz 2024.2\nAdding pytz 2024.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for typing-extensions==4.7.1\nBest match: typing-extensions 4.7.1\nAdding typing-extensions 4.7.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for qasync==0.25.0\nBest match: qasync 0.25.0\nAdding qasync 0.25.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for importlib-metadata==6.7.0\nBest match: importlib-metadata 6.7.0\nAdding importlib-metadata 6.7.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for commonmark==0.9.1\nBest match: commonmark 0.9.1\nAdding commonmark 0.9.1 to easy-install.pth file\nInstalling cmark script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for dictdiffer==0.9.0\nBest match: dictdiffer 0.9.0\nAdding dictdiffer 0.9.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for packaging==24.0\nBest match: packaging 24.0\nAdding packaging 24.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for requests-cache==1.1.1\nBest match: requests-cache 1.1.1\nAdding requests-cache 1.1.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for pyparsing==3.1.4\nBest match: pyparsing 3.1.4\nAdding pyparsing 3.1.4 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for kiwisolver==1.4.5\nBest match: kiwisolver 1.4.5\nAdding kiwisolver 1.4.5 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for Pillow==9.5.0\nBest match: Pillow 9.5.0\nAdding Pillow 9.5.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for cycler==0.11.0\nBest match: cycler 0.11.0\nAdding cycler 0.11.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for fonttools==4.38.0\nBest match: fonttools 4.38.0\nAdding fonttools 4.38.0 to easy-install.pth file\nInstalling fonttools script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\nInstalling pyftmerge script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\nInstalling pyftsubset script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\nInstalling ttx script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for jaraco.classes==3.2.3\nBest match: jaraco.classes 3.2.3\nAdding jaraco.classes 3.2.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for importlib-resources==5.12.0\nBest match: importlib-resources 5.12.0\nAdding importlib-resources 5.12.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for jeepney==0.8.0\nBest match: jeepney 0.8.0\nAdding jeepney 0.8.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for SecretStorage==3.3.3\nBest match: SecretStorage 3.3.3\nAdding SecretStorage 3.3.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for six==1.17.0\nBest match: six 1.17.0\nAdding six 1.17.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for zipp==3.15.0\nBest match: zipp 3.15.0\nAdding zipp 3.15.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for url-normalize==1.4.3\nBest match: url-normalize 1.4.3\nAdding url-normalize 1.4.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for cattrs==23.1.2\nBest match: cattrs 23.1.2\nAdding cattrs 23.1.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for platformdirs==4.0.0\nBest match: platformdirs 4.0.0\nAdding platformdirs 4.0.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for attrs==24.2.0\nBest match: attrs 24.2.0\nAdding attrs 24.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for more-itertools==9.1.0\nBest match: more-itertools 9.1.0\nAdding more-itertools 9.1.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for cryptography==44.0.0\nBest match: cryptography 44.0.0\nAdding cryptography 44.0.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for exceptiongroup==1.2.2\nBest match: exceptiongroup 1.2.2\nAdding exceptiongroup 1.2.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for cffi==1.15.1\nBest match: cffi 1.15.1\nAdding cffi 1.15.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nSearching for pycparser==2.21\nBest match: pycparser 2.21\nAdding pycparser 2.21 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages\nFinished processing dependencies for Orange3==3.24.0.dev0+ce493b0\nVerifying Orange installation...\n✅ Orange installation successful!\nSuccessfully installed orange using Python 3.7\n",
    "setup_res_stderr": "Using CPython 3.7.9\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 18 packages in 54ms\nPrepared 18 packages in 14ms\nInstalled 18 packages in 170ms\n + cython==0.29.37\n + exceptiongroup==1.2.2\n + importlib-metadata==6.7.0\n + iniconfig==2.0.0\n + numpy==1.17.5\n + packaging==24.0\n + pluggy==1.2.0\n + pyqt5==5.15.10\n + pyqt5-qt5==5.15.16\n + pyqt5-sip==12.13.0\n + pyqtwebengine==5.15.6\n + pyqtwebengine-qt5==5.15.16\n + pytest==7.4.4\n + setuptools==59.8.0\n + tomli==2.0.1\n + typing-extensions==4.7.1\n + wheel==0.42.0\n + zipp==3.15.0\nResolved 38 packages in 238ms\nInstalled 33 packages in 806ms\n + bottleneck==1.4.0\n + certifi==2024.12.14\n + cffi==1.15.1\n + chardet==5.2.0\n + charset-normalizer==3.4.1\n + cryptography==44.0.0\n + idna==3.10\n + importlib-resources==5.12.0\n + jaraco-classes==3.2.3\n + jeepney==0.8.0\n + joblib==1.3.2\n + keyring==24.1.1\n + keyrings-alt==4.2.0\n + more-itertools==9.1.0\n + networkx==2.6.3\n + opentsne==1.0.1\n + pandas==1.3.5\n + pip==24.0\n + pycparser==2.21\n + python-dateutil==2.9.0.post0\n + python-louvain==0.16\n + pytz==2024.2\n + pyyaml==6.0.1\n + requests==2.31.0\n + scikit-learn==1.0.2\n + scipy==1.7.3\n + secretstorage==3.3.3\n + serverfiles==0.3.1\n + six==1.17.0\n + threadpoolctl==3.1.0\n + urllib3==2.0.7\n + xlrd==2.0.1\n + xlsxwriter==3.2.0\nResolved 34 packages in 121ms\nInstalled 19 packages in 211ms\n + anyqt==0.2.0\n + attrs==24.2.0\n + cattrs==23.1.2\n + commonmark==0.9.1\n + cycler==0.11.0\n + dictdiffer==0.9.0\n + docutils==0.20.1\n + fonttools==4.38.0\n + kiwisolver==1.4.5\n + matplotlib==3.5.3\n + orange-canvas-core==0.1.35\n + orange-widget-base==4.22.0\n + pillow==9.5.0\n + platformdirs==4.0.0\n + pyparsing==3.1.4\n + pyqtgraph==0.12.4\n + qasync==0.25.0\n + requests-cache==1.1.1\n + url-normalize==1.4.3\nResolved 2 packages in 4ms\nInstalled 2 packages in 27ms\n + psycopg2==2.9.9\n + pymssql==2.3.2\nAudited 1 package in 75ms\nAudited 2 packages in 2ms\nOrange/classification/_simple_tree.c: In function ‘gain_ratio_c’:\nOrange/classification/_simple_tree.c:63:9: warning: implicit declaration of function ‘qsort_r’; did you mean ‘qsort’? [-Wimplicit-function-declaration]\n   63 |         qsort_r(base, nel, size, compar, thunk)\n      |         ^~~~~~~\nOrange/classification/_simple_tree.c:147:9: note: in expansion of macro ‘QSORT_R_FUNC’\n  147 |         QSORT_R_FUNC(examples, size, sizeof(struct Example), (void*) &compar_attr, compar_examples);\n      |         ^~~~~~~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/classification/_tree_scorers.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_2find_threshold_entropy’:\nOrange/classification/_tree_scorers.c:3115:27: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 3115 |   __pyx_t_7 = ((__pyx_v_N <= __pyx_v_min_leaf) != 0);\n      |                           ^~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_6find_threshold_MSE’:\nOrange/classification/_tree_scorers.c:4619:27: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 4619 |   __pyx_t_1 = ((__pyx_v_N <= __pyx_v_min_leaf) != 0);\n      |                           ^~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_8find_binarization_MSE’:\nOrange/classification/_tree_scorers.c:5396:43: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 5396 |           for (__pyx_t_22 = 0; __pyx_t_22 < __pyx_t_21; __pyx_t_22+=1) {\n      |                                           ^\nOrange/classification/_tree_scorers.c:5517:39: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 5517 |           __pyx_t_27 = ((__pyx_v_left >= __pyx_v_min_leaf) != 0);\n      |                                       ^~\nOrange/classification/_tree_scorers.c:5523:53: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 5523 |           __pyx_t_27 = (((__pyx_v_N - __pyx_v_left) >= __pyx_v_min_leaf) != 0);\n      |                                                     ^~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_14compute_predictions_csr’:\nOrange/classification/_tree_scorers.c:7051:41: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 7051 |         for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {\n      |                                         ^\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_16compute_predictions_csc’:\nOrange/classification/_tree_scorers.c:7741:41: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 7741 |         for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {\n      |                                         ^\nOrange/classification/_tree_scorers.c:7801:143: warning: comparison of integer expressions of different signedness: ‘__pyx_t_5numpy_int32_t’ {aka ‘int’} and ‘unsigned int’ [-Wsign-compare]\n 7801 |               __pyx_t_17 = (((*((__pyx_t_5numpy_int32_t *) ( /* dim=0 */ (__pyx_v_indices.data + __pyx_t_18 * __pyx_v_indices.strides[0]) ))) != __pyx_v_i) != 0);\n      |                                                                                                                                               ^~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/data/_valuecount.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/data/_contingency.c:598:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nOrange/data/_io.c: In function ‘__pyx_pf_6Orange_4data_3_io_sparse_read_float.constprop’:\nOrange/data/_io.c:3881:24: warning: ‘__pyx_v_decs’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 3881 |           __pyx_v_decs = (__pyx_v_decs / 10.0);\n      |           ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~\nOrange/data/_io.c:4070:24: warning: ‘__pyx_v_value’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4070 |           __pyx_t_10 = PyFloat_FromDouble(__pyx_v_value); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 221, __pyx_L5_error)\n      |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nOrange/data/_io.c:480:40: warning: ‘__pyx_v_attr_index’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n  480 |   #define PyInt_FromLong               PyLong_FromLong\n      |                                        ^~~~~~~~~~~~~~~\nOrange/data/_io.c:1301:7: note: ‘__pyx_v_attr_index’ was declared here\n 1301 |   int __pyx_v_attr_index;\n      |       ^~~~~~~~~~~~~~~~~~\nOrange/data/_io.c:2935:25: warning: ‘__pyx_v_atomp’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 2935 |           __pyx_v_atomp = (__pyx_v_atomp + 1);\n      |           ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/distance/_distance.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/preprocess/_discretize.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/preprocess/_relieff.cpp:581:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/projection/_som.c:598:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pw_6Orange_10projection_4_som_5update_hex’:\nOrange/projection/_som.c:3655:7: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 3655 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c:3654:7: warning: ‘__pyx_v_win_x’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 3654 |   int __pyx_v_win_x;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pw_6Orange_10projection_4_som_7get_winners_sparse’:\nOrange/projection/_som.c:4547:223: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4547 |           *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int16_t *, __pyx_pybuffernd_winners.rcbuffer->pybuffer.buf, __pyx_t_38, __pyx_pybuffernd_winners.diminfo[0].strides, __pyx_t_39, __pyx_pybuffernd_winners.diminfo[1].strides) = __pyx_v_win_y;\n      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~\nOrange/projection/_som.c:4114:7: note: ‘__pyx_v_win_y’ was declared here\n 4114 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c:4536:223: warning: ‘__pyx_v_win_x’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4536 |           *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int16_t *, __pyx_pybuffernd_winners.rcbuffer->pybuffer.buf, __pyx_t_36, __pyx_pybuffernd_winners.diminfo[0].strides, __pyx_t_37, __pyx_pybuffernd_winners.diminfo[1].strides) = __pyx_v_win_x;\n      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~\nOrange/projection/_som.c:4113:7: note: ‘__pyx_v_win_x’ was declared here\n 4113 |   int __pyx_v_win_x;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pf_6Orange_10projection_4_som_8update_sparse.constprop’:\nOrange/projection/_som.c:4746:7: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4746 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c:4745:7: warning: ‘__pyx_v_win_x’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4745 |   int __pyx_v_win_x;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pw_6Orange_10projection_4_som_3update’:\nOrange/projection/_som.c:3141:7: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 3141 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pw_6Orange_10projection_4_som_1get_winners’:\nOrange/projection/_som.c:2964:223: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 2964 |           *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int16_t *, __pyx_pybuffernd_winners.rcbuffer->pybuffer.buf, __pyx_t_27, __pyx_pybuffernd_winners.diminfo[0].strides, __pyx_t_28, __pyx_pybuffernd_winners.diminfo[1].strides) = __pyx_v_win_y;\n      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~\nOrange/projection/_som.c:2665:7: note: ‘__pyx_v_win_y’ was declared here\n 2665 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c:2953:223: warning: ‘__pyx_v_win_x’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 2953 |           *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int16_t *, __pyx_pybuffernd_winners.rcbuffer->pybuffer.buf, __pyx_t_25, __pyx_pybuffernd_winners.diminfo[0].strides, __pyx_t_26, __pyx_pybuffernd_winners.diminfo[1].strides) = __pyx_v_win_x;\n      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~\nOrange/projection/_som.c:2664:7: note: ‘__pyx_v_win_x’ was declared here\n 2664 |   int __pyx_v_win_x;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pf_6Orange_10projection_4_som_10update_sparse_hex.constprop’:\nOrange/projection/_som.c:5515:7: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 5515 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c:5514:7: warning: ‘__pyx_v_win_x’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 5514 |   int __pyx_v_win_x;\n      |       ^~~~~~~~~~~~~\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/setuptools/command/install.py:37: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.\n  setuptools.SetuptoolsDeprecationWarning,\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/setuptools/command/easy_install.py:159: EasyInstallDeprecationWarning: easy_install command is deprecated. Use build and pip and other standards-based tools.\n  EasyInstallDeprecationWarning,\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/setuptools/command/install.py:37: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.\n  setuptools.SetuptoolsDeprecationWarning,\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3/.venv/lib/python3.7/site-packages/setuptools/command/egg_info.py:628: SetuptoolsDeprecationWarning: Custom 'build_py' does not implement 'get_data_files_without_manifest'.\nPlease extend command classes from setuptools instead of distutils.\n  SetuptoolsDeprecationWarning\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3\ncollected 65 items\n\nr2e_tests/test_1.py ..................                                   [ 27%]\nr2e_tests/test_2.py sss.........sss.sss.sss.sss.sss.sss.sss.sss.sss      [100%]\n\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestPreprocess::test_read_data_calls_reader\nPASSED r2e_tests/test_1.py::TestRemoveConstant::test_nothing_to_remove\nPASSED r2e_tests/test_1.py::TestRemoveConstant::test_remove_columns\nPASSED r2e_tests/test_1.py::TestRemoveNaNRows::test_remove_row\nPASSED r2e_tests/test_1.py::TestRemoveNaNColumns::test_column_filtering\nPASSED r2e_tests/test_1.py::TestRemoveNaNColumns::test_column_filtering_sparse\nPASSED r2e_tests/test_1.py::TestScaling::test_scaling_mean_span\nPASSED r2e_tests/test_1.py::TestScaling::test_scaling_median_stddev\nPASSED r2e_tests/test_1.py::TestReprs::test_reprs\nPASSED r2e_tests/test_1.py::TestEnumPickling::test_continuize_pickling\nPASSED r2e_tests/test_1.py::TestEnumPickling::test_randomize_pickling\nPASSED r2e_tests/test_1.py::TestEnumPickling::test_scaling_pickling\nPASSED r2e_tests/test_1.py::TestAdaptiveNormalize::test_dense_pps\nPASSED r2e_tests/test_1.py::TestAdaptiveNormalize::test_sparse_pps\nPASSED r2e_tests/test_1.py::TestRemoveSparse::test_0_dense\nPASSED r2e_tests/test_1.py::TestRemoveSparse::test_0_sparse\nPASSED r2e_tests/test_1.py::TestRemoveSparse::test_nan_dense\nPASSED r2e_tests/test_1.py::TestRemoveSparse::test_nan_sparse\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_data_column_nans\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_image_export\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_minimum_size\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_msg_base_class\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_normalize\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_randomize\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_remove_sparse\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_select_features\nPASSED r2e_tests/test_2.py::TestDiscretizeEditor::test_editor\nPASSED r2e_tests/test_2.py::TestContinuizeEditor::test_editor\nPASSED r2e_tests/test_2.py::TestImputeEditor::test_editor\nPASSED r2e_tests/test_2.py::TestFeatureSelectEditor::test_editor\nPASSED r2e_tests/test_2.py::TestRandomFeatureSelectEditor::test_editor\nPASSED r2e_tests/test_2.py::TestRandomizeEditor::test_editor\nPASSED r2e_tests/test_2.py::TestPCAEditor::test_editor\nPASSED r2e_tests/test_2.py::TestCUREditor::test_editor\nPASSED r2e_tests/test_2.py::TestRemoveSparseEditor::test_editor\nSKIPPED [10] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:244: image exporting not tested as .widget was not set\nSKIPPED [10] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:238: minimum size not tested as .widget was not set\nSKIPPED [10] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:250: msg base class not tested as .widget was not set\n======================== 35 passed, 30 skipped in 4.13s ========================\nWidgets left: 0    Max widgets: 577 \n\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_ce493b09494c007b27c6fbc5944636136fedd6e3\ncollected 65 items\n\nr2e_tests/test_1.py .................F                                   [ 27%]\nr2e_tests/test_2.py sss.........sss.sss.sss.sss.sss.sss.sss.sss.sss      [100%]\n\n=================================== FAILURES ===================================\n_______________________ TestRemoveSparse.test_nan_sparse _______________________\n\nself = <r2e_tests.test_1.TestRemoveSparse testMethod=test_nan_sparse>\n\n    def test_nan_sparse(self):\n        self.data[1:, 1] = np.nan\n        self.data.X[:, 0] = 7\n        true_out = self.data[:, 0]\n        true_out.X = true_out.X.reshape(-1, 1)\n        self.data.X = csr_matrix(self.data.X)\n        true_out.X = csr_matrix(true_out.X)\n>       out = RemoveSparse(False, False, 0.5)(self.data)\n\nr2e_tests/test_1.py:226: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = RemoveSparse(filter_0=False, threshold=0.5)\ndata = [[a=7],\n [a=7, b=?],\n [a=7, b=?]\n]\n\n    def __call__(self, data):\n        if self.fixed_threshold:\n            tailored_threshold = self.threshold\n        else:\n            tailored_threshold = np.ceil(self.threshold/100 * data.X.shape[0])\n    \n        if self.filter_0:\n            if sp.issparse(data.X):\n                data_csc = sp.csc_matrix(data.X)\n                h, w = data_csc.shape\n                sparsness = [(h - data_csc[:, i].count_nonzero()) for i in range(w)]\n            else:\n                sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)\n        else: # filter by nans\n            if sp.issparse(data.X):\n                sparsness = np.sum(np.isnan(data.X.data), axis=0)\n            else:\n                sparsness = np.sum(np.isnan(data.X), axis=0)\n>       att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]\nE       TypeError: zip argument #2 must support iteration\n\nOrange/preprocess/preprocess.py:611: TypeError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestPreprocess::test_read_data_calls_reader\nPASSED r2e_tests/test_1.py::TestRemoveConstant::test_nothing_to_remove\nPASSED r2e_tests/test_1.py::TestRemoveConstant::test_remove_columns\nPASSED r2e_tests/test_1.py::TestRemoveNaNRows::test_remove_row\nPASSED r2e_tests/test_1.py::TestRemoveNaNColumns::test_column_filtering\nPASSED r2e_tests/test_1.py::TestRemoveNaNColumns::test_column_filtering_sparse\nPASSED r2e_tests/test_1.py::TestScaling::test_scaling_mean_span\nPASSED r2e_tests/test_1.py::TestScaling::test_scaling_median_stddev\nPASSED r2e_tests/test_1.py::TestReprs::test_reprs\nPASSED r2e_tests/test_1.py::TestEnumPickling::test_continuize_pickling\nPASSED r2e_tests/test_1.py::TestEnumPickling::test_randomize_pickling\nPASSED r2e_tests/test_1.py::TestEnumPickling::test_scaling_pickling\nPASSED r2e_tests/test_1.py::TestAdaptiveNormalize::test_dense_pps\nPASSED r2e_tests/test_1.py::TestAdaptiveNormalize::test_sparse_pps\nPASSED r2e_tests/test_1.py::TestRemoveSparse::test_0_dense\nPASSED r2e_tests/test_1.py::TestRemoveSparse::test_0_sparse\nPASSED r2e_tests/test_1.py::TestRemoveSparse::test_nan_dense\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_data_column_nans\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_image_export\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_minimum_size\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_msg_base_class\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_normalize\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_randomize\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_remove_sparse\nPASSED r2e_tests/test_2.py::TestOWPreprocess::test_select_features\nPASSED r2e_tests/test_2.py::TestDiscretizeEditor::test_editor\nPASSED r2e_tests/test_2.py::TestContinuizeEditor::test_editor\nPASSED r2e_tests/test_2.py::TestImputeEditor::test_editor\nPASSED r2e_tests/test_2.py::TestFeatureSelectEditor::test_editor\nPASSED r2e_tests/test_2.py::TestRandomFeatureSelectEditor::test_editor\nPASSED r2e_tests/test_2.py::TestRandomizeEditor::test_editor\nPASSED r2e_tests/test_2.py::TestPCAEditor::test_editor\nPASSED r2e_tests/test_2.py::TestCUREditor::test_editor\nPASSED r2e_tests/test_2.py::TestRemoveSparseEditor::test_editor\nSKIPPED [10] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:244: image exporting not tested as .widget was not set\nSKIPPED [10] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:238: minimum size not tested as .widget was not set\nSKIPPED [10] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:250: msg base class not tested as .widget was not set\nFAILED r2e_tests/test_1.py::TestRemoveSparse::test_nan_sparse - TypeError: zi...\n=================== 1 failed, 34 passed, 30 skipped in 2.55s ===================\nWidgets left: 0    Max widgets: 577 \n\n",
    "old_commit_res_stderr": ""
}
Orange/preprocess/preprocess.py Orange/tests/test_preprocess.py Orange/widgets/data/tests/test_owpreprocess.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** TypeError When Removing Sparse Attributes with NaN Values in Sparse Matrices

**Description:**
When using the `RemoveSparse` preprocessor on datasets that include NaN values within a sparse matrix, a `TypeError` is raised. The error occurs because the sparsity calculation expects an iterable, but receives a non-iterable type instead.

**Example Code:**
```python
from Orange.preprocess.preprocess import RemoveSparse
from Orange.data import Domain, ContinuousVariable, Table
from scipy.sparse import csr_matrix
import numpy as np

# Setup domain and data with NaN values
domain = Domain([ContinuousVariable('a'), ContinuousVariable('b')])
data = Table.from_numpy(domain, np.zeros((3, 2)))
data[1:, 1] = np.nan
data.X[:, 0] = 7
data.X = csr_matrix(data.X)

# Apply RemoveSparse preprocessor
preprocessor = RemoveSparse(filter_0=False, threshold=0.5)
output = preprocessor(data)
```

**Expected Behavior:**
The `RemoveSparse` preprocessor should process the data without errors, correctly handling NaN values in sparse matrices and removing attributes based on the specified sparsity threshold.

**Actual Behavior:**
A `TypeError` is raised with the message: `zip argument #2 must support iteration`. This error prevents the preprocessor from handling datasets that contain NaN values in sparse matrix formats.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### Orange/preprocess/preprocess.py
"""
Preprocess
----------

"""
import numpy as np
import bottleneck as bn
import scipy.sparse as sp
from sklearn.impute import SimpleImputer

import Orange.data
from Orange.data.filter import HasClass
from Orange.statistics import distribution
from Orange.util import Reprable, Enum, deprecated
from . import impute, discretize, transformation

__all__ = ["Continuize", "Discretize", "Impute", "RemoveNaNRows",
           "SklImpute", "Normalize", "Randomize", "Preprocess",
           "RemoveConstant", "RemoveNaNClasses", "RemoveNaNColumns",
           "ProjectPCA", "ProjectCUR", "Scale", "RemoveSparse",
           "AdaptiveNormalize"]


class Preprocess(Reprable):
    """
    A generic preprocessor base class.

    Methods
    -------
    __call__(data: Table) -> Table
        Return preprocessed data.
    """
    def __call__(self, data):
        raise NotImplementedError("Subclasses need to implement __call__")


class Continuize(Preprocess):
    MultinomialTreatment = Enum(
        "Continuize",
        ("Indicators", "FirstAsBase", "FrequentAsBase", "Remove",
         "RemoveMultinomial", "ReportError", "AsOrdinal", "AsNormalizedOrdinal",
         "Leave"),
        qualname="Continuize.MultinomialTreatment")
    (Indicators, FirstAsBase, FrequentAsBase, Remove, RemoveMultinomial,
     ReportError, AsOrdinal, AsNormalizedOrdinal, Leave) = MultinomialTreatment

    def __init__(self, zero_based=True,
                 multinomial_treatment=Indicators):
        self.zero_based = zero_based
        self.multinomial_treatment = multinomial_treatment

    def __call__(self, data):
        from . import continuize

        continuizer = continuize.DomainContinuizer(
            zero_based=self.zero_based,
            multinomial_treatment=self.multinomial_treatment)
        domain = continuizer(data)
        return data.transform(domain)


class Discretize(Preprocess):
    """
    Construct a discretizer, a preprocessor for discretization of
    continuous features.

    Parameters
    ----------
    method : discretization method (default: Orange.preprocess.discretize.Discretization)

    remove_const : bool (default=True)
        Determines whether the features with constant values are removed
        during discretization.
    """

    def __init__(self, method=None, remove_const=True,
                 discretize_classes=False, discretize_metas=False):
        self.method = method
        self.remove_const = remove_const
        self.discretize_classes = discretize_classes
        self.discretize_metas = discretize_metas

    def __call__(self, data):
        """
        Compute and apply discretization of the given data. Returns a new
        data table.

        Parameters
        ----------
        data : Orange.data.Table
            A data table to be discretized.
        """

        def transform(var):
            if var.is_continuous:
                new_var = method(data, var)
                if new_var is not None and \
                        (len(new_var.values) >= 2 or not self.remove_const):
                    return new_var
                else:
                    return None
            else:
                return var

        def discretized(vars_, do_discretize):
            if do_discretize:
                vars_ = (transform(var) for var in vars_)
                vars_ = [var for var in vars_ if var is not None]
            return vars_

        method = self.method or discretize.EqualFreq()
        domain = Orange.data.Domain(
            discretized(data.domain.attributes, True),
            discretized(data.domain.class_vars, self.discretize_classes),
            discretized(data.domain.metas, self.discretize_metas))
        return data.transform(domain)


class Impute(Preprocess):
    """
    Construct a imputer, a preprocessor for imputation of missing values in
    the data table.

    Parameters
    ----------
    method : imputation method (default: Orange.preprocess.impute.Average())
    """

    def __init__(self, method=Orange.preprocess.impute.Average()):
        self.method = method

    def __call__(self, data):
        """
        Apply an imputation method to the given dataset. Returns a new
        data table with missing values replaced by their imputations.

        Parameters
        ----------
        data : Orange.data.Table
            An input data table.
        """

        method = self.method or impute.Average()
        newattrs = [method(data, var) for var in data.domain.attributes]
        domain = Orange.data.Domain(
            newattrs, data.domain.class_vars, data.domain.metas)
        return data.transform(domain)


class SklImpute(Preprocess):
    __wraps__ = SimpleImputer

    def __init__(self, strategy='mean'):
        self.strategy = strategy

    def __call__(self, data):
        from Orange.data.sql.table import SqlTable
        if isinstance(data, SqlTable):
            return Impute()(data)
        imputer = SimpleImputer(strategy=self.strategy)
        X = imputer.fit_transform(data.X)
        # Create new variables with appropriate `compute_value`, but
        # drop the ones which do not have valid `imputer.statistics_`
        # (i.e. all NaN columns). `sklearn.preprocessing.Imputer` already
        # drops them from the transformed X.
        features = [impute.Average()(data, var, value)
                    for var, value in zip(data.domain.attributes,
                                          imputer.statistics_)
                    if not np.isnan(value)]
        assert X.shape[1] == len(features)
        domain = Orange.data.Domain(features, data.domain.class_vars,
                                    data.domain.metas)
        new_data = data.transform(domain)
        new_data.X = X
        return new_data


class RemoveConstant(Preprocess):
    """
    Construct a preprocessor that removes features with constant values
    from the dataset.
    """

    def __call__(self, data):
        """
        Remove columns with constant values from the dataset and return
        the resulting data table.

        Parameters
        ----------
        data : an input dataset
        """

        oks = np.logical_and(~bn.allnan(data.X, axis=0),
                             bn.nanmin(data.X, axis=0) != bn.nanmax(data.X, axis=0))
        atts = [data.domain.attributes[i] for i, ok in enumerate(oks) if ok]
        domain = Orange.data.Domain(atts, data.domain.class_vars,
                                    data.domain.metas)
        return data.transform(domain)


class RemoveNaNRows(Preprocess):
    _reprable_module = True

    def __call__(self, data):
        mask = np.isnan(data.X)
        mask = np.any(mask, axis=1)
        return data[~mask]


class RemoveNaNColumns(Preprocess):
    """
    Remove features from the data domain if they contain
    `threshold` or more unknown values.

    `threshold` can be an integer or a float in the range (0, 1) representing
    the fraction of the data size. When not provided, columns with only missing
    values are removed (default).
    """
    def __init__(self, threshold=None):
        self.threshold = threshold

    def __call__(self, data, threshold=None):
        # missing entries in sparse data are treated as zeros so we skip removing NaNs
        if sp.issparse(data.X):
            return data

        if threshold is None:
            threshold = data.X.shape[0] if self.threshold is None else \
                        self.threshold
        if isinstance(threshold, float):
            threshold = threshold * data.X.shape[0]
        nans = np.sum(np.isnan(data.X), axis=0)
        att = [a for a, n in zip(data.domain.attributes, nans) if n < threshold]
        domain = Orange.data.Domain(att, data.domain.class_vars,
                                    data.domain.metas)
        return data.transform(domain)


@deprecated("Orange.data.filter.HasClas")
class RemoveNaNClasses(Preprocess):
    """
    Construct preprocessor that removes examples with missing class
    from the dataset.
    """

    def __call__(self, data):
        """
        Remove rows that contain NaN in any class variable from the dataset
        and return the resulting data table.

        Parameters
        ----------
        data : an input dataset

        Returns
        -------
        data : dataset without rows with missing classes
        """
        return HasClass()(data)


class Normalize(Preprocess):
    """
    Construct a preprocessor for normalization of features.
    Given a data table, preprocessor returns a new table in
    which the continuous attributes are normalized.

    Parameters
    ----------
    zero_based : bool (default=True)
        Only used when `norm_type=NormalizeBySpan`.

        Determines the value used as the “low” value of the variable.
        It determines the interval for normalized continuous variables
        (either [-1, 1] or [0, 1]).

    norm_type : NormTypes (default: Normalize.NormalizeBySD)
        Normalization type. If Normalize.NormalizeBySD, the values are
        replaced with standardized values by subtracting the average
        value and dividing by the standard deviation.
        Attribute zero_based has no effect on this standardization.

        If Normalize.NormalizeBySpan, the values are replaced with
        normalized values by subtracting min value of the data and
        dividing by span (max - min).

    transform_class : bool (default=False)
        If True the class is normalized as well.

    center : bool (default=True)
        Only used when `norm_type=NormalizeBySD`.

        Whether or not to center the data so it has mean zero.

    normalize_datetime : bool (default=False)


    Examples
    --------
    >>> from Orange.data import Table
    >>> from Orange.preprocess import Normalize
    >>> data = Table("iris")
    >>> normalizer = Normalize(norm_type=Normalize.NormalizeBySpan)
    >>> normalized_data = normalizer(data)
    """
    Type = Enum("Normalize", ("NormalizeBySpan", "NormalizeBySD"),
                qualname="Normalize.Type")
    NormalizeBySpan, NormalizeBySD = Type

    def __init__(self,
                 zero_based=True,
                 norm_type=NormalizeBySD,
                 transform_class=False,
                 center=True,
                 normalize_datetime=False):
        self.zero_based = zero_based
        self.norm_type = norm_type
        self.transform_class = transform_class
        self.center = center
        self.normalize_datetime = normalize_datetime

    def __call__(self, data):
        """
        Compute and apply normalization of the given data. Returns a new
        data table.

        Parameters
        ----------
        data : Orange.data.Table
            A data table to be normalized.

        Returns
        -------
        data : Orange.data.Table
            Normalized data table.
        """
        from . import normalize

        if all(a.attributes.get('skip-normalization', False)
               for a in data.domain.attributes if a.is_continuous):
            # Skip normalization for datasets where all features are marked as already normalized.
            # Required for SVMs (with normalizer as their default preprocessor) on sparse data to
            # retain sparse structure. Normalizing sparse data would otherwise result in a dense
            # matrix, which requires too much memory. For example, this is used for Bag of Words
            # models where normalization is not really needed.
            return data

        normalizer = normalize.Normalizer(
            zero_based=self.zero_based,
            norm_type=self.norm_type,
            transform_class=self.transform_class,
            center=self.center,
            normalize_datetime=self.normalize_datetime
        )
        return normalizer(data)


class Randomize(Preprocess):
    """
    Construct a preprocessor for randomization of classes,
    attributes and/or metas.
    Given a data table, preprocessor returns a new table in
    which the data is shuffled.

    Parameters
    ----------

    rand_type : RandTypes (default: Randomize.RandomizeClasses)
        Randomization type. If Randomize.RandomizeClasses, classes
        are shuffled.
        If Randomize.RandomizeAttributes, attributes are shuffled.
        If Randomize.RandomizeMetas, metas are shuffled.

    rand_seed : int (optional)
        Random seed

    Examples
    --------
    >>> from Orange.data import Table
    >>> from Orange.preprocess import Randomize
    >>> data = Table("iris")
    >>> randomizer = Randomize(Randomize.RandomizeClasses)
    >>> randomized_data = randomizer(data)
    """
    Type = Enum("Randomize",
                dict(RandomizeClasses=1,
                     RandomizeAttributes=2,
                     RandomizeMetas=4),
                type=int,
                qualname="Randomize.Type")
    RandomizeClasses, RandomizeAttributes, RandomizeMetas = Type

    def __init__(self, rand_type=RandomizeClasses, rand_seed=None):
        self.rand_type = rand_type
        self.rand_seed = rand_seed

    def __call__(self, data):
        """
        Apply randomization of the given data. Returns a new
        data table.

        Parameters
        ----------
        data : Orange.data.Table
            A data table to be randomized.

        Returns
        -------
        data : Orange.data.Table
            Randomized data table.
        """
        new_data = data.copy()
        rstate = np.random.RandomState(self.rand_seed)
        # ensure the same seed is not used to shuffle X and Y at the same time
        r1, r2, r3 = rstate.randint(0, 2 ** 32 - 1, size=3, dtype=np.int64)
        if self.rand_type & Randomize.RandomizeClasses:
            new_data.Y = self.randomize(new_data.Y, r1)
        if self.rand_type & Randomize.RandomizeAttributes:
            new_data.X = self.randomize(new_data.X, r2)
        if self.rand_type & Randomize.RandomizeMetas:
            new_data.metas = self.randomize(new_data.metas, r3)
        return new_data

    @staticmethod
    def randomize(table, rand_state=None):
        rstate = np.random.RandomState(rand_state)
        if sp.issparse(table):
            table = table.tocsc()  # type: sp.spmatrix
            for i in range(table.shape[1]):
                permutation = rstate.permutation(table.shape[0])
                col_indices = \
                    table.indices[table.indptr[i]: table.indptr[i + 1]]
                col_indices[:] = permutation[col_indices]
        elif len(table.shape) > 1:
            for i in range(table.shape[1]):
                rstate.shuffle(table[:, i])
        else:
            rstate.shuffle(table)
        return table


class ProjectPCA(Preprocess):

    def __init__(self, n_components=None):
        self.n_components = n_components

    def __call__(self, data):
        pca = Orange.projection.PCA(n_components=self.n_components)(data)
        return pca(data)


class ProjectCUR(Preprocess):

    def __init__(self, rank=3, max_error=1):
        self.rank = rank
        self.max_error = max_error

    def __call__(self, data):
        rank = min(self.rank, min(data.X.shape)-1)
        cur = Orange.projection.CUR(
            rank=rank, max_error=self.max_error,
            compute_U=False,
        )(data)
        return cur(data)


class Scale(Preprocess):
    """
    Scale data preprocessor.  Scales data so that its distribution remains
    the same but its location on the axis changes.
    """
    class _MethodEnum(Enum):
        def __call__(self, *args, **kwargs):
            return getattr(Scale, '_' + self.name)(*args, **kwargs)

    CenteringType = _MethodEnum("Scale", ("NoCentering", "Mean", "Median"),
                                qualname="Scale.CenteringType")
    ScalingType = _MethodEnum("Scale", ("NoScaling", "Std", "Span"),
                              qualname="Scale.ScalingType")
    NoCentering, Mean, Median = CenteringType
    NoScaling, Std, Span = ScalingType

    @staticmethod
    def _Mean(dist):
        values, counts = np.array(dist)
        return np.average(values, weights=counts)

    @staticmethod
    def _Median(dist):
        values, counts = np.array(dist)
        cumdist = np.cumsum(counts)
        if cumdist[-1] > 0:
            cumdist /= cumdist[-1]
        return np.interp(.5, cumdist, values)

    @staticmethod
    def _Std(dist):
        values, counts = np.array(dist)
        mean = np.average(values, weights=counts)
        diff = values - mean
        return np.sqrt(np.average(diff ** 2, weights=counts))

    @staticmethod
    def _Span(dist):
        values = np.array(dist[0])
        return np.max(values) - np.min(values)

    def __init__(self, center=Mean, scale=Std):
        self.center = center
        self.scale = scale

    def __call__(self, data):
        if self.center is None and self.scale is None:
            return data

        def transform(var):
            dist = distribution.get_distribution(data, var)
            if self.center != self.NoCentering:
                c = self.center(dist)
                dist[0, :] -= c
            else:
                c = 0

            if self.scale != self.NoScaling:
                s = self.scale(dist)
                if s < 1e-15:
                    s = 1
            else:
                s = 1
            factor = 1 / s
            transformed_var = var.copy(
                compute_value=transformation.Normalizer(var, c, factor))
            return transformed_var

        newvars = []
        for var in data.domain.attributes:
            if var.is_continuous:
                newvars.append(transform(var))
            else:
                newvars.append(var)
        domain = Orange.data.Domain(newvars, data.domain.class_vars,
                                    data.domain.metas)
        return data.transform(domain)


class PreprocessorList(Preprocess):
    """
    Store a list of preprocessors and on call apply them to the dataset.

    Parameters
    ----------
    preprocessors : list
        A list of preprocessors.
    """

    def __init__(self, preprocessors=()):
        self.preprocessors = list(preprocessors)

    def __call__(self, data):
        """
        Applies a list of preprocessors to the dataset.

        Parameters
        ----------
        data : an input data table
        """

        for pp in self.preprocessors:
            data = pp(data)
        return data

class RemoveSparse(Preprocess):
    """
    Filter out the features with too many nan's or 0. Threshold is user defined.

    Parameters
    ----------
    filter_0: bool
        filter out by zeros or nan's
    fixed_threshold: bool
        threshold is either a fixed number of elements or percentage
    threshold: int
        kept as is if fixed threshold or the percent is used to calculate
        the appropriate number of elements
    """

    def __init__(self, filter_0=True, fixed_threshold=False, threshold=5):
        self.filter_0 = filter_0
        self.fixed_threshold = fixed_threshold
        self.threshold = threshold

    def __call__(self, data):
        if self.fixed_threshold:
            tailored_threshold = self.threshold
        else:
            tailored_threshold = np.ceil(self.threshold/100 * data.X.shape[0])

        if self.filter_0:
            if sp.issparse(data.X):
                data_csc = sp.csc_matrix(data.X)
                h, w = data_csc.shape
                sparsness = [(h - data_csc[:, i].count_nonzero()) for i in range(w)]
            else:
                sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)
        else: # filter by nans
            if sp.issparse(data.X):
                sparsness = np.sum(np.isnan(data.X.data), axis=0)
            else:
                sparsness = np.sum(np.isnan(data.X), axis=0)
        att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]
        domain = Orange.data.Domain(att, data.domain.class_vars,
                                    data.domain.metas)
        return data.transform(domain)


class AdaptiveNormalize(Preprocess):
    """
    Construct a preprocessors that normalizes or merely scales the data.
    If the input is sparse, data is only scaled, to avoid turning it to
    dense. Parameters are diveded to those passed to Normalize or Scale
    class. Scaling takes only scale parameter.
     If the user wants to have more options with scaling,
    they should use the preprocessing widget.
    For more details, check Scale and Normalize widget.

    Parameters
    ----------

    zero_based : bool (default=True)
        passed to Normalize

    norm_type : NormTypes (default: Normalize.NormalizeBySD)
        passed to Normalize

    transform_class : bool (default=False)
        passed to Normalize

    center : bool(default=True)
        passed to Normalize

    normalize_datetime : bool (default=False)
        passed to Normalize

    scale : ScaleTypes (default: Scale.Span)
        passed to Scale
    """

    def __init__(self,
                 zero_based=True,
                 norm_type=Normalize.NormalizeBySD,
                 transform_class=False,
                 normalize_datetime=False,
                 center=True,
                 scale=Scale.Span):
        self.normalize_pps = Normalize(zero_based,
                                       norm_type,
                                       transform_class,
                                       center,
                                       normalize_datetime)
        self.scale_pps = Scale(center=Scale.NoCentering, scale=scale)

    def __call__(self, data):
        if sp.issparse(data.X):
            return self.scale_pps(data)
        return self.normalize_pps(data)

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]

**Title:** TypeError When Removing Sparse Attributes with NaN Values in Sparse Matrices

**Description:**
When using the `RemoveSparse` preprocessor on datasets that include NaN values within a sparse matrix, a `TypeError` is raised. The error occurs because the sparsity calculation expects an iterable, but receives a non-iterable type instead.

**Example Code:**
```python
from Orange.preprocess.preprocess import RemoveSparse
from Orange.data import Domain, ContinuousVariable, Table
from scipy.sparse import csr_matrix
import numpy as np

# Setup domain and data with NaN values
domain = Domain([ContinuousVariable('a'), ContinuousVariable('b')])
data = Table.from_numpy(domain, np.zeros((3, 2)))
data[1:, 1] = np.nan
data.X[:, 0] = 7
data.X = csr_matrix(data.X)

# Apply RemoveSparse preprocessor
preprocessor = RemoveSparse(filter_0=False, threshold=0.5)
output = preprocessor(data)
```

**Expected Behavior:**
The `RemoveSparse` preprocessor should process the data without errors, correctly handling NaN values in sparse matrices and removing attributes based on the specified sparsity threshold.

**Actual Behavior:**
A `TypeError` is raised with the message: `zip argument #2 must support iteration`. This error prevents the preprocessor from handling datasets that contain NaN values in sparse matrix formats.

[/ISSUE]
{
    "TestPreprocess.test_read_data_calls_reader": "PASSED",
    "TestRemoveConstant.test_nothing_to_remove": "PASSED",
    "TestRemoveConstant.test_remove_columns": "PASSED",
    "TestRemoveNaNRows.test_remove_row": "PASSED",
    "TestRemoveNaNColumns.test_column_filtering": "PASSED",
    "TestRemoveNaNColumns.test_column_filtering_sparse": "PASSED",
    "TestScaling.test_scaling_mean_span": "PASSED",
    "TestScaling.test_scaling_median_stddev": "PASSED",
    "TestReprs.test_reprs": "PASSED",
    "TestEnumPickling.test_continuize_pickling": "PASSED",
    "TestEnumPickling.test_randomize_pickling": "PASSED",
    "TestEnumPickling.test_scaling_pickling": "PASSED",
    "TestAdaptiveNormalize.test_dense_pps": "PASSED",
    "TestAdaptiveNormalize.test_sparse_pps": "PASSED",
    "TestRemoveSparse.test_0_dense": "PASSED",
    "TestRemoveSparse.test_0_sparse": "PASSED",
    "TestRemoveSparse.test_nan_dense": "PASSED",
    "TestRemoveSparse.test_nan_sparse": "PASSED",
    "TestOWPreprocess.test_data_column_nans": "PASSED",
    "TestOWPreprocess.test_image_export": "PASSED",
    "TestOWPreprocess.test_minimum_size": "PASSED",
    "TestOWPreprocess.test_msg_base_class": "PASSED",
    "TestOWPreprocess.test_normalize": "PASSED",
    "TestOWPreprocess.test_randomize": "PASSED",
    "TestOWPreprocess.test_remove_sparse": "PASSED",
    "TestOWPreprocess.test_select_features": "PASSED",
    "TestDiscretizeEditor.test_editor": "PASSED",
    "TestContinuizeEditor.test_editor": "PASSED",
    "TestImputeEditor.test_editor": "PASSED",
    "TestFeatureSelectEditor.test_editor": "PASSED",
    "TestRandomFeatureSelectEditor.test_editor": "PASSED",
    "TestRandomizeEditor.test_editor": "PASSED",
    "TestPCAEditor.test_editor": "PASSED",
    "TestCUREditor.test_editor": "PASSED",
    "TestRemoveSparseEditor.test_editor": "PASSED"
}
diff --git a/Orange/preprocess/preprocess.py b/Orange/preprocess/preprocess.py
index ed46ba931..97c63228a 100644
--- a/Orange/preprocess/preprocess.py
+++ b/Orange/preprocess/preprocess.py
@@ -605,7 +605,8 @@ class RemoveSparse(Preprocess):
                 sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)
         else: # filter by nans
             if sp.issparse(data.X):
-                sparsness = np.sum(np.isnan(data.X.data), axis=0)
+                data_csc = sp.csc_matrix(data.X)
+                sparsness = [np.sum(np.isnan(data.X[:, i].data)) for i in range(data_csc.shape[1])]
             else:
                 sparsness = np.sum(np.isnan(data.X), axis=0)
         att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]

{"Orange/preprocess/preprocess.py": "\"\"\"\nPreprocess\n----------\n\n\"\"\"\nimport numpy as np\nimport bottleneck as bn\nimport scipy.sparse as sp\nfrom sklearn.impute import SimpleImputer\n\nimport Orange.data\nfrom Orange.data.filter import HasClass\nfrom Orange.statistics import distribution\nfrom Orange.util import Reprable, Enum, deprecated\nfrom . import impute, discretize, transformation\n\n__all__ = [\"Continuize\", \"Discretize\", \"Impute\", \"RemoveNaNRows\",\n           \"SklImpute\", \"Normalize\", \"Randomize\", \"Preprocess\",\n           \"RemoveConstant\", \"RemoveNaNClasses\", \"RemoveNaNColumns\",\n           \"ProjectPCA\", \"ProjectCUR\", \"Scale\", \"RemoveSparse\",\n           \"AdaptiveNormalize\"]\n\n\nclass Preprocess(Reprable):\n    \"\"\"\n    A generic preprocessor base class.\n\n    Methods\n    -------\n    __call__(data: Table) -> Table\n        Return preprocessed data.\n    \"\"\"\n    def __call__(self, data):\n        raise NotImplementedError(\"Subclasses need to implement __call__\")\n\n\nclass Continuize(Preprocess):\n    MultinomialTreatment = Enum(\n        \"Continuize\",\n        (\"Indicators\", \"FirstAsBase\", \"FrequentAsBase\", \"Remove\",\n         \"RemoveMultinomial\", \"ReportError\", \"AsOrdinal\", \"AsNormalizedOrdinal\",\n         \"Leave\"),\n        qualname=\"Continuize.MultinomialTreatment\")\n    (Indicators, FirstAsBase, FrequentAsBase, Remove, RemoveMultinomial,\n     ReportError, AsOrdinal, AsNormalizedOrdinal, Leave) = MultinomialTreatment\n\n    def __init__(self, zero_based=True,\n                 multinomial_treatment=Indicators):\n        self.zero_based = zero_based\n        self.multinomial_treatment = multinomial_treatment\n\n    def __call__(self, data):\n        from . import continuize\n\n        continuizer = continuize.DomainContinuizer(\n            zero_based=self.zero_based,\n            multinomial_treatment=self.multinomial_treatment)\n        domain = continuizer(data)\n        return data.transform(domain)\n\n\nclass Discretize(Preprocess):\n    \"\"\"\n    Construct a discretizer, a preprocessor for discretization of\n    continuous features.\n\n    Parameters\n    ----------\n    method : discretization method (default: Orange.preprocess.discretize.Discretization)\n\n    remove_const : bool (default=True)\n        Determines whether the features with constant values are removed\n        during discretization.\n    \"\"\"\n\n    def __init__(self, method=None, remove_const=True,\n                 discretize_classes=False, discretize_metas=False):\n        self.method = method\n        self.remove_const = remove_const\n        self.discretize_classes = discretize_classes\n        self.discretize_metas = discretize_metas\n\n    def __call__(self, data):\n        \"\"\"\n        Compute and apply discretization of the given data. Returns a new\n        data table.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            A data table to be discretized.\n        \"\"\"\n\n        def transform(var):\n            if var.is_continuous:\n                new_var = method(data, var)\n                if new_var is not None and \\\n                        (len(new_var.values) >= 2 or not self.remove_const):\n                    return new_var\n                else:\n                    return None\n            else:\n                return var\n\n        def discretized(vars_, do_discretize):\n            if do_discretize:\n                vars_ = (transform(var) for var in vars_)\n                vars_ = [var for var in vars_ if var is not None]\n            return vars_\n\n        method = self.method or discretize.EqualFreq()\n        domain = Orange.data.Domain(\n            discretized(data.domain.attributes, True),\n            discretized(data.domain.class_vars, self.discretize_classes),\n            discretized(data.domain.metas, self.discretize_metas))\n        return data.transform(domain)\n\n\nclass Impute(Preprocess):\n    \"\"\"\n    Construct a imputer, a preprocessor for imputation of missing values in\n    the data table.\n\n    Parameters\n    ----------\n    method : imputation method (default: Orange.preprocess.impute.Average())\n    \"\"\"\n\n    def __init__(self, method=Orange.preprocess.impute.Average()):\n        self.method = method\n\n    def __call__(self, data):\n        \"\"\"\n        Apply an imputation method to the given dataset. Returns a new\n        data table with missing values replaced by their imputations.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            An input data table.\n        \"\"\"\n\n        method = self.method or impute.Average()\n        newattrs = [method(data, var) for var in data.domain.attributes]\n        domain = Orange.data.Domain(\n            newattrs, data.domain.class_vars, data.domain.metas)\n        return data.transform(domain)\n\n\nclass SklImpute(Preprocess):\n    __wraps__ = SimpleImputer\n\n    def __init__(self, strategy='mean'):\n        self.strategy = strategy\n\n    def __call__(self, data):\n        from Orange.data.sql.table import SqlTable\n        if isinstance(data, SqlTable):\n            return Impute()(data)\n        imputer = SimpleImputer(strategy=self.strategy)\n        X = imputer.fit_transform(data.X)\n        # Create new variables with appropriate `compute_value`, but\n        # drop the ones which do not have valid `imputer.statistics_`\n        # (i.e. all NaN columns). `sklearn.preprocessing.Imputer` already\n        # drops them from the transformed X.\n        features = [impute.Average()(data, var, value)\n                    for var, value in zip(data.domain.attributes,\n                                          imputer.statistics_)\n                    if not np.isnan(value)]\n        assert X.shape[1] == len(features)\n        domain = Orange.data.Domain(features, data.domain.class_vars,\n                                    data.domain.metas)\n        new_data = data.transform(domain)\n        new_data.X = X\n        return new_data\n\n\nclass RemoveConstant(Preprocess):\n    \"\"\"\n    Construct a preprocessor that removes features with constant values\n    from the dataset.\n    \"\"\"\n\n    def __call__(self, data):\n        \"\"\"\n        Remove columns with constant values from the dataset and return\n        the resulting data table.\n\n        Parameters\n        ----------\n        data : an input dataset\n        \"\"\"\n\n        oks = np.logical_and(~bn.allnan(data.X, axis=0),\n                             bn.nanmin(data.X, axis=0) != bn.nanmax(data.X, axis=0))\n        atts = [data.domain.attributes[i] for i, ok in enumerate(oks) if ok]\n        domain = Orange.data.Domain(atts, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\nclass RemoveNaNRows(Preprocess):\n    _reprable_module = True\n\n    def __call__(self, data):\n        mask = np.isnan(data.X)\n        mask = np.any(mask, axis=1)\n        return data[~mask]\n\n\nclass RemoveNaNColumns(Preprocess):\n    \"\"\"\n    Remove features from the data domain if they contain\n    `threshold` or more unknown values.\n\n    `threshold` can be an integer or a float in the range (0, 1) representing\n    the fraction of the data size. When not provided, columns with only missing\n    values are removed (default).\n    \"\"\"\n    def __init__(self, threshold=None):\n        self.threshold = threshold\n\n    def __call__(self, data, threshold=None):\n        # missing entries in sparse data are treated as zeros so we skip removing NaNs\n        if sp.issparse(data.X):\n            return data\n\n        if threshold is None:\n            threshold = data.X.shape[0] if self.threshold is None else \\\n                        self.threshold\n        if isinstance(threshold, float):\n            threshold = threshold * data.X.shape[0]\n        nans = np.sum(np.isnan(data.X), axis=0)\n        att = [a for a, n in zip(data.domain.attributes, nans) if n < threshold]\n        domain = Orange.data.Domain(att, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\n@deprecated(\"Orange.data.filter.HasClas\")\nclass RemoveNaNClasses(Preprocess):\n    \"\"\"\n    Construct preprocessor that removes examples with missing class\n    from the dataset.\n    \"\"\"\n\n    def __call__(self, data):\n        \"\"\"\n        Remove rows that contain NaN in any class variable from the dataset\n        and return the resulting data table.\n\n        Parameters\n        ----------\n        data : an input dataset\n\n        Returns\n        -------\n        data : dataset without rows with missing classes\n        \"\"\"\n        return HasClass()(data)\n\n\nclass Normalize(Preprocess):\n    \"\"\"\n    Construct a preprocessor for normalization of features.\n    Given a data table, preprocessor returns a new table in\n    which the continuous attributes are normalized.\n\n    Parameters\n    ----------\n    zero_based : bool (default=True)\n        Only used when `norm_type=NormalizeBySpan`.\n\n        Determines the value used as the \u201clow\u201d value of the variable.\n        It determines the interval for normalized continuous variables\n        (either [-1, 1] or [0, 1]).\n\n    norm_type : NormTypes (default: Normalize.NormalizeBySD)\n        Normalization type. If Normalize.NormalizeBySD, the values are\n        replaced with standardized values by subtracting the average\n        value and dividing by the standard deviation.\n        Attribute zero_based has no effect on this standardization.\n\n        If Normalize.NormalizeBySpan, the values are replaced with\n        normalized values by subtracting min value of the data and\n        dividing by span (max - min).\n\n    transform_class : bool (default=False)\n        If True the class is normalized as well.\n\n    center : bool (default=True)\n        Only used when `norm_type=NormalizeBySD`.\n\n        Whether or not to center the data so it has mean zero.\n\n    normalize_datetime : bool (default=False)\n\n\n    Examples\n    --------\n    >>> from Orange.data import Table\n    >>> from Orange.preprocess import Normalize\n    >>> data = Table(\"iris\")\n    >>> normalizer = Normalize(norm_type=Normalize.NormalizeBySpan)\n    >>> normalized_data = normalizer(data)\n    \"\"\"\n    Type = Enum(\"Normalize\", (\"NormalizeBySpan\", \"NormalizeBySD\"),\n                qualname=\"Normalize.Type\")\n    NormalizeBySpan, NormalizeBySD = Type\n\n    def __init__(self,\n                 zero_based=True,\n                 norm_type=NormalizeBySD,\n                 transform_class=False,\n                 center=True,\n                 normalize_datetime=False):\n        self.zero_based = zero_based\n        self.norm_type = norm_type\n        self.transform_class = transform_class\n        self.center = center\n        self.normalize_datetime = normalize_datetime\n\n    def __call__(self, data):\n        \"\"\"\n        Compute and apply normalization of the given data. Returns a new\n        data table.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            A data table to be normalized.\n\n        Returns\n        -------\n        data : Orange.data.Table\n            Normalized data table.\n        \"\"\"\n        from . import normalize\n\n        if all(a.attributes.get('skip-normalization', False)\n               for a in data.domain.attributes if a.is_continuous):\n            # Skip normalization for datasets where all features are marked as already normalized.\n            # Required for SVMs (with normalizer as their default preprocessor) on sparse data to\n            # retain sparse structure. Normalizing sparse data would otherwise result in a dense\n            # matrix, which requires too much memory. For example, this is used for Bag of Words\n            # models where normalization is not really needed.\n            return data\n\n        normalizer = normalize.Normalizer(\n            zero_based=self.zero_based,\n            norm_type=self.norm_type,\n            transform_class=self.transform_class,\n            center=self.center,\n            normalize_datetime=self.normalize_datetime\n        )\n        return normalizer(data)\n\n\nclass Randomize(Preprocess):\n    \"\"\"\n    Construct a preprocessor for randomization of classes,\n    attributes and/or metas.\n    Given a data table, preprocessor returns a new table in\n    which the data is shuffled.\n\n    Parameters\n    ----------\n\n    rand_type : RandTypes (default: Randomize.RandomizeClasses)\n        Randomization type. If Randomize.RandomizeClasses, classes\n        are shuffled.\n        If Randomize.RandomizeAttributes, attributes are shuffled.\n        If Randomize.RandomizeMetas, metas are shuffled.\n\n    rand_seed : int (optional)\n        Random seed\n\n    Examples\n    --------\n    >>> from Orange.data import Table\n    >>> from Orange.preprocess import Randomize\n    >>> data = Table(\"iris\")\n    >>> randomizer = Randomize(Randomize.RandomizeClasses)\n    >>> randomized_data = randomizer(data)\n    \"\"\"\n    Type = Enum(\"Randomize\",\n                dict(RandomizeClasses=1,\n                     RandomizeAttributes=2,\n                     RandomizeMetas=4),\n                type=int,\n                qualname=\"Randomize.Type\")\n    RandomizeClasses, RandomizeAttributes, RandomizeMetas = Type\n\n    def __init__(self, rand_type=RandomizeClasses, rand_seed=None):\n        self.rand_type = rand_type\n        self.rand_seed = rand_seed\n\n    def __call__(self, data):\n        \"\"\"\n        Apply randomization of the given data. Returns a new\n        data table.\n\n        Parameters\n        ----------\n        data : Orange.data.Table\n            A data table to be randomized.\n\n        Returns\n        -------\n        data : Orange.data.Table\n            Randomized data table.\n        \"\"\"\n        new_data = data.copy()\n        rstate = np.random.RandomState(self.rand_seed)\n        # ensure the same seed is not used to shuffle X and Y at the same time\n        r1, r2, r3 = rstate.randint(0, 2 ** 32 - 1, size=3, dtype=np.int64)\n        if self.rand_type & Randomize.RandomizeClasses:\n            new_data.Y = self.randomize(new_data.Y, r1)\n        if self.rand_type & Randomize.RandomizeAttributes:\n            new_data.X = self.randomize(new_data.X, r2)\n        if self.rand_type & Randomize.RandomizeMetas:\n            new_data.metas = self.randomize(new_data.metas, r3)\n        return new_data\n\n    @staticmethod\n    def randomize(table, rand_state=None):\n        rstate = np.random.RandomState(rand_state)\n        if sp.issparse(table):\n            table = table.tocsc()  # type: sp.spmatrix\n            for i in range(table.shape[1]):\n                permutation = rstate.permutation(table.shape[0])\n                col_indices = \\\n                    table.indices[table.indptr[i]: table.indptr[i + 1]]\n                col_indices[:] = permutation[col_indices]\n        elif len(table.shape) > 1:\n            for i in range(table.shape[1]):\n                rstate.shuffle(table[:, i])\n        else:\n            rstate.shuffle(table)\n        return table\n\n\nclass ProjectPCA(Preprocess):\n\n    def __init__(self, n_components=None):\n        self.n_components = n_components\n\n    def __call__(self, data):\n        pca = Orange.projection.PCA(n_components=self.n_components)(data)\n        return pca(data)\n\n\nclass ProjectCUR(Preprocess):\n\n    def __init__(self, rank=3, max_error=1):\n        self.rank = rank\n        self.max_error = max_error\n\n    def __call__(self, data):\n        rank = min(self.rank, min(data.X.shape)-1)\n        cur = Orange.projection.CUR(\n            rank=rank, max_error=self.max_error,\n            compute_U=False,\n        )(data)\n        return cur(data)\n\n\nclass Scale(Preprocess):\n    \"\"\"\n    Scale data preprocessor.  Scales data so that its distribution remains\n    the same but its location on the axis changes.\n    \"\"\"\n    class _MethodEnum(Enum):\n        def __call__(self, *args, **kwargs):\n            return getattr(Scale, '_' + self.name)(*args, **kwargs)\n\n    CenteringType = _MethodEnum(\"Scale\", (\"NoCentering\", \"Mean\", \"Median\"),\n                                qualname=\"Scale.CenteringType\")\n    ScalingType = _MethodEnum(\"Scale\", (\"NoScaling\", \"Std\", \"Span\"),\n                              qualname=\"Scale.ScalingType\")\n    NoCentering, Mean, Median = CenteringType\n    NoScaling, Std, Span = ScalingType\n\n    @staticmethod\n    def _Mean(dist):\n        values, counts = np.array(dist)\n        return np.average(values, weights=counts)\n\n    @staticmethod\n    def _Median(dist):\n        values, counts = np.array(dist)\n        cumdist = np.cumsum(counts)\n        if cumdist[-1] > 0:\n            cumdist /= cumdist[-1]\n        return np.interp(.5, cumdist, values)\n\n    @staticmethod\n    def _Std(dist):\n        values, counts = np.array(dist)\n        mean = np.average(values, weights=counts)\n        diff = values - mean\n        return np.sqrt(np.average(diff ** 2, weights=counts))\n\n    @staticmethod\n    def _Span(dist):\n        values = np.array(dist[0])\n        return np.max(values) - np.min(values)\n\n    def __init__(self, center=Mean, scale=Std):\n        self.center = center\n        self.scale = scale\n\n    def __call__(self, data):\n        if self.center is None and self.scale is None:\n            return data\n\n        def transform(var):\n            dist = distribution.get_distribution(data, var)\n            if self.center != self.NoCentering:\n                c = self.center(dist)\n                dist[0, :] -= c\n            else:\n                c = 0\n\n            if self.scale != self.NoScaling:\n                s = self.scale(dist)\n                if s < 1e-15:\n                    s = 1\n            else:\n                s = 1\n            factor = 1 / s\n            transformed_var = var.copy(\n                compute_value=transformation.Normalizer(var, c, factor))\n            return transformed_var\n\n        newvars = []\n        for var in data.domain.attributes:\n            if var.is_continuous:\n                newvars.append(transform(var))\n            else:\n                newvars.append(var)\n        domain = Orange.data.Domain(newvars, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\nclass PreprocessorList(Preprocess):\n    \"\"\"\n    Store a list of preprocessors and on call apply them to the dataset.\n\n    Parameters\n    ----------\n    preprocessors : list\n        A list of preprocessors.\n    \"\"\"\n\n    def __init__(self, preprocessors=()):\n        self.preprocessors = list(preprocessors)\n\n    def __call__(self, data):\n        \"\"\"\n        Applies a list of preprocessors to the dataset.\n\n        Parameters\n        ----------\n        data : an input data table\n        \"\"\"\n\n        for pp in self.preprocessors:\n            data = pp(data)\n        return data\n\nclass RemoveSparse(Preprocess):\n    \"\"\"\n    Filter out the features with too many nan's or 0. Threshold is user defined.\n\n    Parameters\n    ----------\n    filter_0: bool\n        filter out by zeros or nan's\n    fixed_threshold: bool\n        threshold is either a fixed number of elements or percentage\n    threshold: int\n        kept as is if fixed threshold or the percent is used to calculate\n        the appropriate number of elements\n    \"\"\"\n\n    def __init__(self, filter_0=True, fixed_threshold=False, threshold=5):\n        self.filter_0 = filter_0\n        self.fixed_threshold = fixed_threshold\n        self.threshold = threshold\n\n    def __call__(self, data):\n        if self.fixed_threshold:\n            tailored_threshold = self.threshold\n        else:\n            tailored_threshold = np.ceil(self.threshold/100 * data.X.shape[0])\n\n        if self.filter_0:\n            if sp.issparse(data.X):\n                data_csc = sp.csc_matrix(data.X)\n                h, w = data_csc.shape\n                sparsness = [(h - data_csc[:, i].count_nonzero()) for i in range(w)]\n            else:\n                sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)\n        else: # filter by nans\n            if sp.issparse(data.X):\n                sparsness = np.sum(np.isnan(data.X.data), axis=0)\n            else:\n                sparsness = np.sum(np.isnan(data.X), axis=0)\n        att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]\n        domain = Orange.data.Domain(att, data.domain.class_vars,\n                                    data.domain.metas)\n        return data.transform(domain)\n\n\nclass AdaptiveNormalize(Preprocess):\n    \"\"\"\n    Construct a preprocessors that normalizes or merely scales the data.\n    If the input is sparse, data is only scaled, to avoid turning it to\n    dense. Parameters are diveded to those passed to Normalize or Scale\n    class. Scaling takes only scale parameter.\n     If the user wants to have more options with scaling,\n    they should use the preprocessing widget.\n    For more details, check Scale and Normalize widget.\n\n    Parameters\n    ----------\n\n    zero_based : bool (default=True)\n        passed to Normalize\n\n    norm_type : NormTypes (default: Normalize.NormalizeBySD)\n        passed to Normalize\n\n    transform_class : bool (default=False)\n        passed to Normalize\n\n    center : bool(default=True)\n        passed to Normalize\n\n    normalize_datetime : bool (default=False)\n        passed to Normalize\n\n    scale : ScaleTypes (default: Scale.Span)\n        passed to Scale\n    \"\"\"\n\n    def __init__(self,\n                 zero_based=True,\n                 norm_type=Normalize.NormalizeBySD,\n                 transform_class=False,\n                 normalize_datetime=False,\n                 center=True,\n                 scale=Scale.Span):\n        self.normalize_pps = Normalize(zero_based,\n                                       norm_type,\n                                       transform_class,\n                                       center,\n                                       normalize_datetime)\n        self.scale_pps = Scale(center=Scale.NoCentering, scale=scale)\n\n    def __call__(self, data):\n        if sp.issparse(data.X):\n            return self.scale_pps(data)\n        return self.normalize_pps(data)\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** TypeError When Removing Sparse Attributes with NaN Values in Sparse Matrices

**Description:**
When using the `RemoveSparse` preprocessor on datasets that include NaN values within a sparse matrix, a `TypeError` is raised. The error occurs because the sparsity calculation expects an iterable, but receives a non-iterable type instead.

**Example Code:**
```python
from Orange.preprocess.preprocess import RemoveSparse
from Orange.data import Domain, ContinuousVariable, Table
from scipy.sparse import csr_matrix
import numpy as np

# Setup domain and data with NaN values
domain = Domain([ContinuousVariable('a'), ContinuousVariable('b')])
data = Table.from_numpy(domain, np.zeros((3, 2)))
data[1:, 1] = np.nan
data.X[:, 0] = 7
data.X = csr_matrix(data.X)

# Apply RemoveSparse preprocessor
preprocessor = RemoveSparse(filter_0=False, threshold=0.5)
output = preprocessor(data)
```

**Expected Behavior:**
The `RemoveSparse` preprocessor should process the data without errors, correctly handling NaN values in sparse matrices and removing attributes based on the specified sparsity threshold.

**Actual Behavior:**
A `TypeError` is raised with the message: `zip argument #2 must support iteration`. This error prevents the preprocessor from handling datasets that contain NaN values in sparse matrix formats.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### Orange/preprocess/preprocess.py
"""
Preprocess
----------

"""
import numpy as np
import bottleneck as bn
import scipy.sparse as sp
from sklearn.impute import SimpleImputer

import Orange.data
from Orange.data.filter import HasClass
from Orange.statistics import distribution
from Orange.util import Reprable, Enum, deprecated
from . import impute, discretize, transformation

__all__ = ["Continuize", "Discretize", "Impute", "RemoveNaNRows",
           "SklImpute", "Normalize", "Randomize", "Preprocess",
           "RemoveConstant", "RemoveNaNClasses", "RemoveNaNColumns",
           "ProjectPCA", "ProjectCUR", "Scale", "RemoveSparse",
           "AdaptiveNormalize"]


class Preprocess(Reprable):
    """
    A generic preprocessor base class.

    Methods
    -------
    __call__(data: Table) -> Table
        Return preprocessed data.
    """
    def __call__(self, data):
        raise NotImplementedError("Subclasses need to implement __call__")


class Continuize(Preprocess):
    MultinomialTreatment = Enum(
        "Continuize",
        ("Indicators", "FirstAsBase", "FrequentAsBase", "Remove",
         "RemoveMultinomial", "ReportError", "AsOrdinal", "AsNormalizedOrdinal",
         "Leave"),
        qualname="Continuize.MultinomialTreatment")
    (Indicators, FirstAsBase, FrequentAsBase, Remove, RemoveMultinomial,
     ReportError, AsOrdinal, AsNormalizedOrdinal, Leave) = MultinomialTreatment

    def __init__(self, zero_based=True,
                 multinomial_treatment=Indicators):
        self.zero_based = zero_based
        self.multinomial_treatment = multinomial_treatment

    def __call__(self, data):
        from . import continuize

        continuizer = continuize.DomainContinuizer(
            zero_based=self.zero_based,
            multinomial_treatment=self.multinomial_treatment)
        domain = continuizer(data)
        return data.transform(domain)


class Discretize(Preprocess):
    """
    Construct a discretizer, a preprocessor for discretization of
    continuous features.

    Parameters
    ----------
    method : discretization method (default: Orange.preprocess.discretize.Discretization)

    remove_const : bool (default=True)
        Determines whether the features with constant values are removed
        during discretization.
    """

    def __init__(self, method=None, remove_const=True,
                 discretize_classes=False, discretize_metas=False):
        self.method = method
        self.remove_const = remove_const
        self.discretize_classes = discretize_classes
        self.discretize_metas = discretize_metas

    def __call__(self, data):
        """
        Compute and apply discretization of the given data. Returns a new
        data table.

        Parameters
        ----------
        data : Orange.data.Table
            A data table to be discretized.
        """

        def transform(var):
            if var.is_continuous:
                new_var = method(data, var)
                if new_var is not None and \
                        (len(new_var.values) >= 2 or not self.remove_const):
                    return new_var
                else:
                    return None
            else:
                return var

        def discretized(vars_, do_discretize):
            if do_discretize:
                vars_ = (transform(var) for var in vars_)
                vars_ = [var for var in vars_ if var is not None]
            return vars_

        method = self.method or discretize.EqualFreq()
        domain = Orange.data.Domain(
            discretized(data.domain.attributes, True),
            discretized(data.domain.class_vars, self.discretize_classes),
            discretized(data.domain.metas, self.discretize_metas))
        return data.transform(domain)


class Impute(Preprocess):
    """
    Construct a imputer, a preprocessor for imputation of missing values in
    the data table.

    Parameters
    ----------
    method : imputation method (default: Orange.preprocess.impute.Average())
    """

    def __init__(self, method=Orange.preprocess.impute.Average()):
        self.method = method

    def __call__(self, data):
        """
        Apply an imputation method to the given dataset. Returns a new
        data table with missing values replaced by their imputations.

        Parameters
        ----------
        data : Orange.data.Table
            An input data table.
        """

        method = self.method or impute.Average()
        newattrs = [method(data, var) for var in data.domain.attributes]
        domain = Orange.data.Domain(
            newattrs, data.domain.class_vars, data.domain.metas)
        return data.transform(domain)


class SklImpute(Preprocess):
    __wraps__ = SimpleImputer

    def __init__(self, strategy='mean'):
        self.strategy = strategy

    def __call__(self, data):
        from Orange.data.sql.table import SqlTable
        if isinstance(data, SqlTable):
            return Impute()(data)
        imputer = SimpleImputer(strategy=self.strategy)
        X = imputer.fit_transform(data.X)
        # Create new variables with appropriate `compute_value`, but
        # drop the ones which do not have valid `imputer.statistics_`
        # (i.e. all NaN columns). `sklearn.preprocessing.Imputer` already
        # drops them from the transformed X.
        features = [impute.Average()(data, var, value)
                    for var, value in zip(data.domain.attributes,
                                          imputer.statistics_)
                    if not np.isnan(value)]
        assert X.shape[1] == len(features)
        domain = Orange.data.Domain(features, data.domain.class_vars,
                                    data.domain.metas)
        new_data = data.transform(domain)
        new_data.X = X
        return new_data


class RemoveConstant(Preprocess):
    """
    Construct a preprocessor that removes features with constant values
    from the dataset.
    """

    def __call__(self, data):
        """
        Remove columns with constant values from the dataset and return
        the resulting data table.

        Parameters
        ----------
        data : an input dataset
        """

        oks = np.logical_and(~bn.allnan(data.X, axis=0),
                             bn.nanmin(data.X, axis=0) != bn.nanmax(data.X, axis=0))
        atts = [data.domain.attributes[i] for i, ok in enumerate(oks) if ok]
        domain = Orange.data.Domain(atts, data.domain.class_vars,
                                    data.domain.metas)
        return data.transform(domain)


class RemoveNaNRows(Preprocess):
    _reprable_module = True

    def __call__(self, data):
        mask = np.isnan(data.X)
        mask = np.any(mask, axis=1)
        return data[~mask]


class RemoveNaNColumns(Preprocess):
    """
    Remove features from the data domain if they contain
    `threshold` or more unknown values.

    `threshold` can be an integer or a float in the range (0, 1) representing
    the fraction of the data size. When not provided, columns with only missing
    values are removed (default).
    """
    def __init__(self, threshold=None):
        self.threshold = threshold

    def __call__(self, data, threshold=None):
        # missing entries in sparse data are treated as zeros so we skip removing NaNs
        if sp.issparse(data.X):
            return data

        if threshold is None:
            threshold = data.X.shape[0] if self.threshold is None else \
                        self.threshold
        if isinstance(threshold, float):
            threshold = threshold * data.X.shape[0]
        nans = np.sum(np.isnan(data.X), axis=0)
        att = [a for a, n in zip(data.domain.attributes, nans) if n < threshold]
        domain = Orange.data.Domain(att, data.domain.class_vars,
                                    data.domain.metas)
        return data.transform(domain)


@deprecated("Orange.data.filter.HasClas")
class RemoveNaNClasses(Preprocess):
    """
    Construct preprocessor that removes examples with missing class
    from the dataset.
    """

    def __call__(self, data):
        """
        Remove rows that contain NaN in any class variable from the dataset
        and return the resulting data table.

        Parameters
        ----------
        data : an input dataset

        Returns
        -------
        data : dataset without rows with missing classes
        """
        return HasClass()(data)


class Normalize(Preprocess):
    """
    Construct a preprocessor for normalization of features.
    Given a data table, preprocessor returns a new table in
    which the continuous attributes are normalized.

    Parameters
    ----------
    zero_based : bool (default=True)
        Only used when `norm_type=NormalizeBySpan`.

        Determines the value used as the “low” value of the variable.
        It determines the interval for normalized continuous variables
        (either [-1, 1] or [0, 1]).

    norm_type : NormTypes (default: Normalize.NormalizeBySD)
        Normalization type. If Normalize.NormalizeBySD, the values are
        replaced with standardized values by subtracting the average
        value and dividing by the standard deviation.
        Attribute zero_based has no effect on this standardization.

        If Normalize.NormalizeBySpan, the values are replaced with
        normalized values by subtracting min value of the data and
        dividing by span (max - min).

    transform_class : bool (default=False)
        If True the class is normalized as well.

    center : bool (default=True)
        Only used when `norm_type=NormalizeBySD`.

        Whether or not to center the data so it has mean zero.

    normalize_datetime : bool (default=False)


    Examples
    --------
    >>> from Orange.data import Table
    >>> from Orange.preprocess import Normalize
    >>> data = Table("iris")
    >>> normalizer = Normalize(norm_type=Normalize.NormalizeBySpan)
    >>> normalized_data = normalizer(data)
    """
    Type = Enum("Normalize", ("NormalizeBySpan", "NormalizeBySD"),
                qualname="Normalize.Type")
    NormalizeBySpan, NormalizeBySD = Type

    def __init__(self,
                 zero_based=True,
                 norm_type=NormalizeBySD,
                 transform_class=False,
                 center=True,
                 normalize_datetime=False):
        self.zero_based = zero_based
        self.norm_type = norm_type
        self.transform_class = transform_class
        self.center = center
        self.normalize_datetime = normalize_datetime

    def __call__(self, data):
        """
        Compute and apply normalization of the given data. Returns a new
        data table.

        Parameters
        ----------
        data : Orange.data.Table
            A data table to be normalized.

        Returns
        -------
        data : Orange.data.Table
            Normalized data table.
        """
        from . import normalize

        if all(a.attributes.get('skip-normalization', False)
               for a in data.domain.attributes if a.is_continuous):
            # Skip normalization for datasets where all features are marked as already normalized.
            # Required for SVMs (with normalizer as their default preprocessor) on sparse data to
            # retain sparse structure. Normalizing sparse data would otherwise result in a dense
            # matrix, which requires too much memory. For example, this is used for Bag of Words
            # models where normalization is not really needed.
            return data

        normalizer = normalize.Normalizer(
            zero_based=self.zero_based,
            norm_type=self.norm_type,
            transform_class=self.transform_class,
            center=self.center,
            normalize_datetime=self.normalize_datetime
        )
        return normalizer(data)


class Randomize(Preprocess):
    """
    Construct a preprocessor for randomization of classes,
    attributes and/or metas.
    Given a data table, preprocessor returns a new table in
    which the data is shuffled.

    Parameters
    ----------

    rand_type : RandTypes (default: Randomize.RandomizeClasses)
        Randomization type. If Randomize.RandomizeClasses, classes
        are shuffled.
        If Randomize.RandomizeAttributes, attributes are shuffled.
        If Randomize.RandomizeMetas, metas are shuffled.

    rand_seed : int (optional)
        Random seed

    Examples
    --------
    >>> from Orange.data import Table
    >>> from Orange.preprocess import Randomize
    >>> data = Table("iris")
    >>> randomizer = Randomize(Randomize.RandomizeClasses)
    >>> randomized_data = randomizer(data)
    """
    Type = Enum("Randomize",
                dict(RandomizeClasses=1,
                     RandomizeAttributes=2,
                     RandomizeMetas=4),
                type=int,
                qualname="Randomize.Type")
    RandomizeClasses, RandomizeAttributes, RandomizeMetas = Type

    def __init__(self, rand_type=RandomizeClasses, rand_seed=None):
        self.rand_type = rand_type
        self.rand_seed = rand_seed

    def __call__(self, data):
        """
        Apply randomization of the given data. Returns a new
        data table.

        Parameters
        ----------
        data : Orange.data.Table
            A data table to be randomized.

        Returns
        -------
        data : Orange.data.Table
            Randomized data table.
        """
        new_data = data.copy()
        rstate = np.random.RandomState(self.rand_seed)
        # ensure the same seed is not used to shuffle X and Y at the same time
        r1, r2, r3 = rstate.randint(0, 2 ** 32 - 1, size=3, dtype=np.int64)
        if self.rand_type & Randomize.RandomizeClasses:
            new_data.Y = self.randomize(new_data.Y, r1)
        if self.rand_type & Randomize.RandomizeAttributes:
            new_data.X = self.randomize(new_data.X, r2)
        if self.rand_type & Randomize.RandomizeMetas:
            new_data.metas = self.randomize(new_data.metas, r3)
        return new_data

    @staticmethod
    def randomize(table, rand_state=None):
        rstate = np.random.RandomState(rand_state)
        if sp.issparse(table):
            table = table.tocsc()  # type: sp.spmatrix
            for i in range(table.shape[1]):
                permutation = rstate.permutation(table.shape[0])
                col_indices = \
                    table.indices[table.indptr[i]: table.indptr[i + 1]]
                col_indices[:] = permutation[col_indices]
        elif len(table.shape) > 1:
            for i in range(table.shape[1]):
                rstate.shuffle(table[:, i])
        else:
            rstate.shuffle(table)
        return table


class ProjectPCA(Preprocess):

    def __init__(self, n_components=None):
        self.n_components = n_components

    def __call__(self, data):
        pca = Orange.projection.PCA(n_components=self.n_components)(data)
        return pca(data)


class ProjectCUR(Preprocess):

    def __init__(self, rank=3, max_error=1):
        self.rank = rank
        self.max_error = max_error

    def __call__(self, data):
        rank = min(self.rank, min(data.X.shape)-1)
        cur = Orange.projection.CUR(
            rank=rank, max_error=self.max_error,
            compute_U=False,
        )(data)
        return cur(data)


class Scale(Preprocess):
    """
    Scale data preprocessor.  Scales data so that its distribution remains
    the same but its location on the axis changes.
    """
    class _MethodEnum(Enum):
        def __call__(self, *args, **kwargs):
            return getattr(Scale, '_' + self.name)(*args, **kwargs)

    CenteringType = _MethodEnum("Scale", ("NoCentering", "Mean", "Median"),
                                qualname="Scale.CenteringType")
    ScalingType = _MethodEnum("Scale", ("NoScaling", "Std", "Span"),
                              qualname="Scale.ScalingType")
    NoCentering, Mean, Median = CenteringType
    NoScaling, Std, Span = ScalingType

    @staticmethod
    def _Mean(dist):
        values, counts = np.array(dist)
        return np.average(values, weights=counts)

    @staticmethod
    def _Median(dist):
        values, counts = np.array(dist)
        cumdist = np.cumsum(counts)
        if cumdist[-1] > 0:
            cumdist /= cumdist[-1]
        return np.interp(.5, cumdist, values)

    @staticmethod
    def _Std(dist):
        values, counts = np.array(dist)
        mean = np.average(values, weights=counts)
        diff = values - mean
        return np.sqrt(np.average(diff ** 2, weights=counts))

    @staticmethod
    def _Span(dist):
        values = np.array(dist[0])
        return np.max(values) - np.min(values)

    def __init__(self, center=Mean, scale=Std):
        self.center = center
        self.scale = scale

    def __call__(self, data):
        if self.center is None and self.scale is None:
            return data

        def transform(var):
            dist = distribution.get_distribution(data, var)
            if self.center != self.NoCentering:
                c = self.center(dist)
                dist[0, :] -= c
            else:
                c = 0

            if self.scale != self.NoScaling:
                s = self.scale(dist)
                if s < 1e-15:
                    s = 1
            else:
                s = 1
            factor = 1 / s
            transformed_var = var.copy(
                compute_value=transformation.Normalizer(var, c, factor))
            return transformed_var

        newvars = []
        for var in data.domain.attributes:
            if var.is_continuous:
                newvars.append(transform(var))
            else:
                newvars.append(var)
        domain = Orange.data.Domain(newvars, data.domain.class_vars,
                                    data.domain.metas)
        return data.transform(domain)


class PreprocessorList(Preprocess):
    """
    Store a list of preprocessors and on call apply them to the dataset.

    Parameters
    ----------
    preprocessors : list
        A list of preprocessors.
    """

    def __init__(self, preprocessors=()):
        self.preprocessors = list(preprocessors)

    def __call__(self, data):
        """
        Applies a list of preprocessors to the dataset.

        Parameters
        ----------
        data : an input data table
        """

        for pp in self.preprocessors:
            data = pp(data)
        return data

class RemoveSparse(Preprocess):
    """
    Filter out the features with too many nan's or 0. Threshold is user defined.

    Parameters
    ----------
    filter_0: bool
        filter out by zeros or nan's
    fixed_threshold: bool
        threshold is either a fixed number of elements or percentage
    threshold: int
        kept as is if fixed threshold or the percent is used to calculate
        the appropriate number of elements
    """

    def __init__(self, filter_0=True, fixed_threshold=False, threshold=5):
        self.filter_0 = filter_0
        self.fixed_threshold = fixed_threshold
        self.threshold = threshold

    def __call__(self, data):
        if self.fixed_threshold:
            tailored_threshold = self.threshold
        else:
            tailored_threshold = np.ceil(self.threshold/100 * data.X.shape[0])

        if self.filter_0:
            if sp.issparse(data.X):
                data_csc = sp.csc_matrix(data.X)
                h, w = data_csc.shape
                sparsness = [(h - data_csc[:, i].count_nonzero()) for i in range(w)]
            else:
                sparsness = data.X.shape[0] - np.count_nonzero(data.X, axis=0)
        else: # filter by nans
            if sp.issparse(data.X):
                sparsness = np.sum(np.isnan(data.X.data), axis=0)
            else:
                sparsness = np.sum(np.isnan(data.X), axis=0)
        att = [a for a, s in zip(data.domain.attributes, sparsness) if s <= tailored_threshold]
        domain = Orange.data.Domain(att, data.domain.class_vars,
                                    data.domain.metas)
        return data.transform(domain)


class AdaptiveNormalize(Preprocess):
    """
    Construct a preprocessors that normalizes or merely scales the data.
    If the input is sparse, data is only scaled, to avoid turning it to
    dense. Parameters are diveded to those passed to Normalize or Scale
    class. Scaling takes only scale parameter.
     If the user wants to have more options with scaling,
    they should use the preprocessing widget.
    For more details, check Scale and Normalize widget.

    Parameters
    ----------

    zero_based : bool (default=True)
        passed to Normalize

    norm_type : NormTypes (default: Normalize.NormalizeBySD)
        passed to Normalize

    transform_class : bool (default=False)
        passed to Normalize

    center : bool(default=True)
        passed to Normalize

    normalize_datetime : bool (default=False)
        passed to Normalize

    scale : ScaleTypes (default: Scale.Span)
        passed to Scale
    """

    def __init__(self,
                 zero_based=True,
                 norm_type=Normalize.NormalizeBySD,
                 transform_class=False,
                 normalize_datetime=False,
                 center=True,
                 scale=Scale.Span):
        self.normalize_pps = Normalize(zero_based,
                                       norm_type,
                                       transform_class,
                                       center,
                                       normalize_datetime)
        self.scale_pps = Scale(center=Scale.NoCentering, scale=scale)

    def __call__(self, data):
        if sp.issparse(data.X):
            return self.scale_pps(data)
        return self.normalize_pps(data)

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user