diff --git a/.readthedocs.yml b/.readthedocs.yml index acb46ee..91913f3 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -2,7 +2,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.12" + python: "3.13" sphinx: configuration: doc/conf.py diff --git a/doc/index.rst b/doc/index.rst index 75bd283..a65056a 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -19,7 +19,7 @@ API Reference FastCan refine - extend + minibatch ssc ols make_poly_ids diff --git a/fastcan/__init__.py b/fastcan/__init__.py index e89cf40..a1d71c1 100644 --- a/fastcan/__init__.py +++ b/fastcan/__init__.py @@ -2,8 +2,8 @@ The :mod:`fastcan` module implements algorithms, including """ -from ._extend import extend from ._fastcan import FastCan +from ._minibatch import minibatch from ._narx import ( Narx, make_narx, @@ -21,7 +21,7 @@ "ssc", "ols", "refine", - "extend", + "minibatch", "make_narx", "print_narx", "Narx", diff --git a/fastcan/_extend.py b/fastcan/_extend.py deleted file mode 100644 index ec1465f..0000000 --- a/fastcan/_extend.py +++ /dev/null @@ -1,120 +0,0 @@ -""" -Extend feature selection -""" - -import math -from copy import deepcopy -from numbers import Integral - -import numpy as np -from sklearn.utils._openmp_helpers import _openmp_effective_n_threads -from sklearn.utils._param_validation import Interval, validate_params -from sklearn.utils.validation import check_is_fitted - -from ._cancorr_fast import _forward_search # type: ignore -from ._fastcan import FastCan, _prepare_search - - -@validate_params( - { - "selector": [FastCan], - "n_features_to_select": [ - Interval(Integral, 1, None, closed="left"), - ], - "batch_size": [ - Interval(Integral, 1, None, closed="left"), - ], - }, - prefer_skip_nested_validation=False, -) -def extend(selector, n_features_to_select=1, batch_size=1): - """Extend FastCan with mini batches. - - It is suitable for selecting a very large number of features - even larger than the number of samples. - - Similar to the correlation filter which selects each feature without considering - the redundancy, the function selects features in mini-batch and the - redundancy between the two mini-batches will be ignored. - - Parameters - ---------- - selector : FastCan - FastCan selector. - - n_features_to_select : int, default=1 - The parameter is the absolute number of features to select. - - batch_size : int, default=1 - The number of features in a mini-batch. - - Returns - ------- - indices : ndarray of shape (n_features_to_select,), dtype=int - The indices of the selected features. - - Examples - -------- - >>> from fastcan import FastCan, extend - >>> X = [[1, 1, 0], [0.01, 0, 0], [-1, 0, 1], [0, 0, 0]] - >>> y = [1, 0, -1, 0] - >>> selector = FastCan(1, verbose=0).fit(X, y) - >>> print(f"Indices: {selector.indices_}") - Indices: [0] - >>> indices = extend(selector, 3, batch_size=2) - >>> print(f"Indices: {indices}") - Indices: [0 2 1] - """ - check_is_fitted(selector) - n_inclusions = selector.indices_include_.size - n_features = selector.n_features_in_ - n_to_select = n_features_to_select - selector.n_features_to_select - batch_size_to_select = batch_size - n_inclusions - - if n_features_to_select > n_features: - raise ValueError( - f"n_features_to_select {n_features_to_select} " - f"must be <= n_features {n_features}." - ) - if n_to_select <= 0: - raise ValueError( - f"The number of features to select ({n_to_select}) ", "is less than 0." - ) - if batch_size_to_select <= 0: - raise ValueError( - "The size of mini batch without included indices ", - f"({batch_size_to_select}) is less than 0.", - ) - - X_transformed_ = deepcopy(selector.X_transformed_) - - indices_include = selector.indices_include_ - indices_exclude = selector.indices_exclude_ - indices_select = selector.indices_[n_inclusions:] - - n_threads = _openmp_effective_n_threads() - - for i in range(math.ceil(n_to_select / batch_size_to_select)): - if i == 0: - batch_size_i = (n_to_select - 1) % batch_size_to_select + 1 + n_inclusions - else: - batch_size_i = batch_size - indices, scores, mask = _prepare_search( - n_features, - batch_size_i, - indices_include, - np.r_[indices_exclude, indices_select], - ) - _forward_search( - X=X_transformed_, - V=selector.y_transformed_, - t=batch_size_i, - tol=selector.tol, - num_threads=n_threads, - verbose=0, - mask=mask, - indices=indices, - scores=scores, - ) - indices_select = np.r_[indices_select, indices[n_inclusions:]] - return np.r_[indices_include, indices_select] diff --git a/fastcan/_fastcan.py b/fastcan/_fastcan.py index 5211ec0..ff5d760 100644 --- a/fastcan/_fastcan.py +++ b/fastcan/_fastcan.py @@ -287,7 +287,6 @@ def _get_support_mask(self): def _prepare_search(n_features, n_features_to_select, indices_include, indices_exclude): - """ """ # initiated with -1 indices = np.full(n_features_to_select, -1, dtype=np.intc, order="F") indices[: indices_include.size] = indices_include diff --git a/fastcan/_minibatch.py b/fastcan/_minibatch.py new file mode 100644 index 0000000..148dfab --- /dev/null +++ b/fastcan/_minibatch.py @@ -0,0 +1,134 @@ +""" +Feature selection with mini-batch +""" + +from copy import deepcopy +from numbers import Integral + +import numpy as np +from sklearn.utils._openmp_helpers import _openmp_effective_n_threads +from sklearn.utils._param_validation import Interval, validate_params +from sklearn.utils.validation import check_X_y + +from ._cancorr_fast import _forward_search # type: ignore +from ._fastcan import FastCan, _prepare_search + + +@validate_params( + { + "X": ["array-like"], + "y": ["array-like"], + "n_features_to_select": [ + Interval(Integral, 1, None, closed="left"), + ], + "batch_size": [ + Interval(Integral, 1, None, closed="left"), + ], + "verbose": ["verbose"], + }, + prefer_skip_nested_validation=False, +) +def minibatch(X, y, n_features_to_select=1, batch_size=1, verbose=1): + """FastCan selection with mini batches. + + It is suitable for selecting a very large number of features + even larger than the number of samples. + + Similar to the correlation filter which selects each feature without considering + the redundancy, the function selects features in mini-batch and the + redundancy between the two mini-batches will be ignored. + + Parameters + ---------- + X : array-like of shape (n_samples, n_features) + Feature matrix. + + y : array-like of shape (n_samples, n_outputs) + Target matrix. + + n_features_to_select : int, default=1 + The parameter is the absolute number of features to select. + + batch_size : int, default=1 + The number of features in a mini-batch. + It is recommended that batch_size be less than n_samples. + + verbose : int, default=1 + The verbosity level. + + Returns + ------- + indices : ndarray of shape (n_features_to_select,), dtype=int + The indices of the selected features. + + Examples + -------- + >>> from fastcan import minibatch + >>> X = [[1, 1, 0], [0.01, 0, 0], [-1, 0, 1], [0, 0, 0]] + >>> y = [1, 0, -1, 0] + >>> indices = minibatch(X, y, 3, batch_size=2, verbose=0) + >>> print(f"Indices: {indices}") + Indices: [0 1 2] + """ + X, y = check_X_y(X, y, ensure_2d=True, multi_output=True) + if y.ndim == 1: + y = y.reshape(-1, 1) + + n_features = X.shape[1] + n_outputs = y.shape[1] + + if n_features_to_select > n_features: + raise ValueError( + f"n_features_to_select {n_features_to_select} " + f"must be <= n_features {n_features}." + ) + + n_threads = _openmp_effective_n_threads() + + n_to_select_split = np.diff( + np.linspace( + 0, n_features_to_select, num=n_outputs + 1, endpoint=True, dtype=int + ) + ) + indices_select = np.zeros(0, dtype=int) + for i in range(n_outputs): + y_i = y[:, i] + batch_split_i = np.diff( + np.r_[ + np.arange(n_to_select_split[i], step=batch_size, dtype=int), + n_to_select_split[i], + ] + ) + for j, batch_size_j in enumerate(batch_split_i): + if j == 0: + selector_j = FastCan( + batch_size_j, indices_exclude=indices_select, verbose=0 + ).fit(X, y_i) + X_transformed_ = deepcopy(selector_j.X_transformed_) + indices = selector_j.indices_ + else: + indices, scores, mask = _prepare_search( + n_features, + batch_size_j, + selector_j.indices_include_, + np.r_[selector_j.indices_exclude_, indices_select], + ) + _forward_search( + X=X_transformed_, + V=selector_j.y_transformed_, + t=batch_size_j, + tol=selector_j.tol, + num_threads=n_threads, + verbose=0, + mask=mask, + indices=indices, + scores=scores, + ) + indices_select = np.r_[indices_select, indices] + if verbose == 1: + print( + f"Progress: {indices_select.size}/{n_features_to_select}", end="\r" + ) + if verbose == 1: + print() + return indices_select diff --git a/fastcan/_narx.py b/fastcan/_narx.py index 4f9d29a..49562a4 100644 --- a/fastcan/_narx.py +++ b/fastcan/_narx.py @@ -4,14 +4,14 @@ import math from itertools import combinations_with_replacement -from numbers import Integral, Real +from numbers import Integral import numpy as np from scipy.optimize import least_squares from scipy.stats import rankdata from sklearn.base import BaseEstimator, RegressorMixin from sklearn.linear_model import LinearRegression -from sklearn.utils import check_array, check_X_y +from sklearn.utils import check_array, check_consistent_length, column_or_1d from sklearn.utils._param_validation import Interval, StrOptions, validate_params from sklearn.utils.validation import check_is_fitted @@ -52,7 +52,7 @@ def make_time_shift_features(X, ids): [5., 3., 4.], [7., 5., 6.]]) """ - X = check_array(X, ensure_2d=True, dtype=float) + X = check_array(X, ensure_2d=True, dtype=float, force_all_finite="allow-nan") ids = check_array(ids, ensure_2d=True, dtype=int) n_samples = X.shape[0] n_outputs = ids.shape[0] @@ -177,7 +177,7 @@ def make_poly_features(X, ids): [ 1., 5., 25., 6.], [ 1., 7., 49., 8.]]) """ - X = check_array(X, ensure_2d=True, dtype=float) + X = check_array(X, ensure_2d=True, dtype=float, force_all_finite="allow-nan") ids = check_array(ids, ensure_2d=True, dtype=int) n_samples = X.shape[0] n_outputs, degree = ids.shape @@ -263,6 +263,12 @@ def make_poly_ids( return np.delete(ids, const_id, 0) # remove the constant featrue +def _mask_missing_value(*arr): + """Remove missing value for all arrays.""" + mask_nomissing = np.all(np.isfinite(np.c_[arr]), axis=1) + return tuple([x[mask_nomissing] for x in arr]) + + class Narx(BaseEstimator, RegressorMixin): """Nonlinear Autoregressive eXogenous model. For example, a (polynomial) Narx model is like @@ -392,6 +398,9 @@ def fit(self, X, y, coef_init=None, **params): When `coef_init` is an array, the model will be a Multi-Step-Ahead Narx whose coefficients and intercept are initialized by the array. + .. note:: + When coef_init is None, missing values (i.e., np.nan) are allowed. + **params : dict Keyword arguments passed to `scipy.optimize.least_squares`. @@ -401,7 +410,9 @@ def fit(self, X, y, coef_init=None, **params): self : object Fitted Estimator. """ - X, y = self._validate_data(X, y, y_numeric=True, multi_output=False) + X = self._validate_data(X, dtype=float, force_all_finite="allow-nan") + y = column_or_1d(y, dtype=float, warn=True) + check_consistent_length(X, y) if self.time_shift_ids is None: self.time_shift_ids_ = make_time_shift_ids( @@ -453,10 +464,12 @@ def fit(self, X, y, coef_init=None, **params): # fit a one-step-ahead Narx model xy_hstack = np.c_[X, y] osa_narx = LinearRegression() - time_shift_terms = make_time_shift_features(xy_hstack, self.time_shift_ids_) - poly_terms = make_poly_features(time_shift_terms, self.poly_ids_) + time_shift_vars = make_time_shift_features(xy_hstack, self.time_shift_ids_) + poly_terms = make_poly_features(time_shift_vars, self.poly_ids_) + # Remove missing values + poly_terms_masked, y_masked = _mask_missing_value(poly_terms, y) - osa_narx.fit(poly_terms, y) + osa_narx.fit(poly_terms_masked, y_masked) if coef_init is None: self.coef_ = osa_narx.coef_ self.intercept_ = osa_narx.intercept_ @@ -516,9 +529,21 @@ def _expression(self, X, y_hat, coef, intercept, k): def _predict(expression, X, y_init, coef, intercept, max_delay): n_samples = X.shape[0] y_hat = np.zeros(n_samples) - y_hat[:max_delay] = y_init - for k in range(max_delay, n_samples): - y_hat[k] = expression(X, y_hat, coef, intercept, k) + at_init = True + init_k = 0 + for k in range(n_samples): + if ~np.all(np.isfinite(X[k])): + at_init = True + init_k = k + 1 + y_hat[k] = np.nan + continue + if k - init_k == max_delay: + at_init = False + + if at_init: + y_hat[k] = y_init[k - init_k] + else: + y_hat[k] = expression(X, y_hat, coef, intercept, k) if np.any(y_hat[k] > 1e20): y_hat[k:] = np.inf return y_hat @@ -535,9 +560,11 @@ def _residual( coef = coef_intercept[:-1] intercept = coef_intercept[-1] - return ( - y - Narx._predict(expression, X, y[:max_delay], coef, intercept, max_delay) - ).flatten() + y_hat = Narx._predict(expression, X, y[:max_delay], coef, intercept, max_delay) + + y_masked, y_hat_masked = _mask_missing_value(y, y_hat) + + return (y_masked - y_hat_masked).flatten() @validate_params( { @@ -564,11 +591,11 @@ def predict(self, X, y_init=None): """ check_is_fitted(self) - X = self._validate_data(X, reset=False) + X = self._validate_data(X, reset=False, force_all_finite="allow-nan") if y_init is None: y_init = np.zeros(self.max_delay_) else: - y_init = check_array(y_init, ensure_2d=False, dtype=np.float64) + y_init = column_or_1d(y_init, dtype=float) if y_init.shape[0] != self.max_delay_: raise ValueError( "`y_init` should have the shape of " @@ -586,6 +613,9 @@ def predict(self, X, y_init=None): self.max_delay_, ) + def _more_tags(self): + return {"allow_nan": True} + @validate_params( { @@ -644,6 +674,7 @@ def print_narx( | X[k-0,9] | 68 | """ check_is_fitted(narx) + def _get_variable_str(time_shift_id): if time_shift_id[0] < narx.n_features_in_: variable_str = f"X[k-{time_shift_id[1]},{time_shift_id[0]}]" @@ -720,10 +751,10 @@ def make_narx( Parameters ---------- X : array-like of shape (n_samples, n_features) - Feature matrix. + Feature matrix. y : array-like of shape (n_samples,) - Target matrix. + Target vector. n_features_to_select : int The parameter is the absolute number of features to select. @@ -799,14 +830,15 @@ def make_narx( | X[k-1,0]*X[k-3,0] | 1.999 | | X[k-2,0]*X[k-0,1] | 1.527 | """ - X, y = check_X_y(X, y, dtype=Real, multi_output=False) + X = check_array(X, dtype=float, ensure_2d=True, force_all_finite="allow-nan") + y = column_or_1d(y, dtype=float) + check_consistent_length(X, y) xy_hstack = np.c_[X, y] n_features = X.shape[1] - n_outputs = xy_hstack.shape[1] - n_features if include_zero_delay is None: - include_zero_delay = [True] * n_features + [False] * n_outputs + include_zero_delay = [True] * n_features + [False] time_shift_ids_all = make_time_shift_ids( n_features=xy_hstack.shape[1], @@ -822,19 +854,22 @@ def make_narx( ), 0, ) - time_shift_terms = make_time_shift_features(xy_hstack, time_shift_ids_all) + time_shift_vars = make_time_shift_features(xy_hstack, time_shift_ids_all) poly_ids_all = make_poly_ids( time_shift_ids_all.shape[0], poly_degree, ) - poly_terms = make_poly_features(time_shift_terms, poly_ids_all) + poly_terms = make_poly_features(time_shift_vars, poly_ids_all) + + # Remove missing values + poly_terms_masked, y_masked = _mask_missing_value(poly_terms, y) csf = FastCan( n_features_to_select, eta=eta, verbose=0, - ).fit(poly_terms, y) + ).fit(poly_terms_masked, y_masked) if drop is not None: indices, _ = refine(csf, drop=drop, max_iter=max_iter, verbose=verbose) support = np.zeros(shape=csf.n_features_in_, dtype=bool) diff --git a/pixi.lock b/pixi.lock index 8531b61..dbad1be 100644 --- a/pixi.lock +++ b/pixi.lock @@ -57,7 +57,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pycodestyle-2.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.9.0-pyh2cfa8aa_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject_hooks-1.2.0-pyh7850678_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-6.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.7-hc5c86c4_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-build-1.2.2.post1-pyhff2d567_0.conda @@ -66,21 +66,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-5_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.8.0-py312h2156523_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.8.1-py312h2156523_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.5.2-py312h7a48858_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.14.1-py312h62794b6_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.6.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.6.0-pyhff2d567_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.5.0-pyhc1e730c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tokenize-rt-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.1.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.12.2-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.5.4-h0f3a69f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.5.5-h0f3a69f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_1.conda - pypi: https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ed/20/bc79bc575ba2e2a7f70e8a1155618bb1301eaa5132a8271373a6903f73f8/babel-2.16.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl @@ -96,7 +96,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/21/e4/c0b6746fd2eb62fe702118b3ca0cb384ce95e1261cfada58ff693aeec08a/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/27/75/de5b9cd67648051cae40039da0c8cbc497a0d99acb1a1f3d087cd66d27b7/matplotlib-3.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/40/d6/70a196b0cf62e0a5bc64ccab07816ab4f6c98db0414a55280331a481a5bf/matplotlib-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/7f/42/6e0f2c2d5c60f499aa29be14f860dd4539de322cd8fb84ee01553493fb4d/pillow-11.0.0-cp312-cp312-manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl @@ -120,8 +120,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-hfdf4475_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-compiler-1.8.0-hfc4bf79_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.8.30-h8857fd0_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-1010.6-h5b2de21_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-1010.6-h98e843e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-1010.6-h5b2de21_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-1010.6-hea4301f_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-17-17.0.6-default_hb173f14_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-17.0.6-default_he371ed4_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-17.0.6-h1af8efd_23.conda @@ -149,8 +149,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/isl-0.26-imath32_h2e86a7b_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-951.9-h0a3eb4e_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-951.9-h38c89e5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-951.9-h0a3eb4e_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-951.9-h5ffbe8e_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-25_osx64_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-25_osx64_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp17-17.0.6-default_hb173f14_7.conda @@ -190,19 +190,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pycodestyle-2.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.9.0-pyh2cfa8aa_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject_hooks-1.2.0-pyh7850678_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-6.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.0-h0608dab_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.0-h3a8ca6c_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-build-1.2.2.post1-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2024.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.13-5_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.8.0-py313h2493e73_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.8.1-py313h2493e73_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/scikit-learn-1.5.2-py313h3d59ad1_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.14.1-py313hbd2dc07_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.6.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.6.0-pyhff2d567_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1300.6.5-h390ca13_0.conda @@ -210,12 +210,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tokenize-rt-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.1.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.12.2-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/uv-0.5.4-h8de1528_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/uv-0.5.5-h8de1528_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.1-hd23fc13_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.6-h915ae27_0.conda - pypi: https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl @@ -233,7 +233,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/f5/b8a370d1aa593c17882af0a6f6755aaecd643640c0ed72dcfd2eafc388b9/kiwisolver-1.4.7-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl - - pypi: https://files.pythonhosted.org/packages/5c/7f/8932eac316b32f464b8f9069f151294dcd892c8fbde61fe8bcd7ba7f7f7e/matplotlib-3.9.2-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/60/04/949640040982822416c471d9ebe4e9e6c69ca9f9bb6ba82ed30808863c02/matplotlib-3.9.3-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/63/24/e2e15e392d00fcf4215907465d8ec2a2f23bcec1481a8ebe4ae760459995/pillow-11.0.0-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl @@ -257,8 +257,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h99b78c6_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.8.0-hf48404e_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.8.30-hf0a4a13_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1010.6-hf67d63f_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-1010.6-h4208deb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1010.6-hf67d63f_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-1010.6-h623e0ac_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-17-17.0.6-default_h146c034_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-17.0.6-default_h360f5da_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-17.0.6-he47c785_23.conda @@ -285,8 +285,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/isl-0.26-imath32_h347afa1_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-951.9-h39a299f_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-951.9-hc81425b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-951.9-h39a299f_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-951.9-h3f9b568_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-25_osxarm64_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-25_osxarm64_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp17-17.0.6-default_h146c034_7.conda @@ -326,19 +326,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pycodestyle-2.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.9.0-pyh2cfa8aa_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject_hooks-1.2.0-pyh7850678_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-6.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.0-h75c3a9f_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.0-hbbac1ca_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-build-1.2.2.post1-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2024.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.13-5_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.8.0-py313heab95af_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.8.1-py313heab95af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-learn-1.5.2-py313h14e4f8e_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.14.1-py313hb3ee861_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.6.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.6.0-pyhff2d567_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1300.6.5-h03f4b80_0.conda @@ -346,12 +346,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tokenize-rt-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.1.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.12.2-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/uv-0.5.4-h668ec48_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/uv-0.5.5-h668ec48_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.6-hb46c0d2_0.conda - pypi: https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl @@ -369,7 +369,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2a/fc/6c0374f7503522539e2d4d1b497f5ebad3f8ed07ab51aed2af988dd0fb65/kiwisolver-1.4.7-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/90/89/9db9db3dd0ff3e2c49e452236dfe29e60b5586a88f8928ca1d153d0da8b5/matplotlib-3.9.2-cp313-cp313-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/9f/90/ebd37143cd3150b6c650ee1580024df3dd649d176e68d346f826b8d24e37/matplotlib-3.9.3-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/43/72/92ad4afaa2afc233dc44184adff289c2e77e8cd916b3ddb72ac69495bda3/pillow-11.0.0-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl @@ -406,11 +406,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.9.0-25_win64_mkl.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.4-he0c23c2_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.11.1-default_h8125262_1000.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.11.2-default_ha69328c_1001.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.17-hcfcfb64_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-25_win64_mkl.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-h2466b09_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.47.0-h2466b09_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_8.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.13.5-h442d1da_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/meson-1.6.0-pyhd8ed1ab_0.conda @@ -427,38 +428,37 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-6.1.0-py313ha7868ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-h2466b09_4.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycodestyle-2.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.9.0-pyh2cfa8aa_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject_hooks-1.2.0-pyh7850678_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-6.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.0-hf5aa216_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.0-hf5aa216_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-build-1.2.2.post1-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2024.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.13-5_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.8.0-py313h331c231_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.8.1-py313h331c231_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/scikit-learn-1.5.2-py313h4f67946_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.14.1-py313h16bbbb2_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.6.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.6.0-pyhff2d567_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.13.0-hc790b64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.13.0-h62715c5_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.5.0-pyhc1e730c_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tokenize-rt-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.1.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.12.2-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/uv-0.5.4-ha08ef0e_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/uv-0.5.5-ha08ef0e_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-ha32ba9b_23.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.42.34433-he29a5d6_23.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.42.34433-hdffcdeb_23.conda - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_1.conda - pypi: https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ed/20/bc79bc575ba2e2a7f70e8a1155618bb1301eaa5132a8271373a6903f73f8/babel-2.16.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl @@ -474,7 +474,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0b/db/32e897e43a330eee8e4770bfd2737a9584b23e33587a0812b8e20aac38f7/kiwisolver-1.4.7-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/b0/6d/3572fe243c74112fef120f0bc86f5edd21f49b60e8322fc7f6a01fe945dd/matplotlib-3.9.2-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/28/dd/0a5176027c1cb94fe75f69f76cb274180c8abf740df6fc0e6a1e4cbaec3f/matplotlib-3.9.3-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/fb/01/3755ba287dac715e6afdb333cb1f6d69740a7475220b4637b5ce3d78cec2/pillow-11.0.0-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl @@ -800,48 +800,48 @@ packages: - kind: conda name: cctools version: '1010.6' - build: h5b2de21_1 - build_number: 1 + build: h5b2de21_2 + build_number: 2 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/cctools-1010.6-h5b2de21_1.conda - sha256: 3881b38dcb1e6a129617a270396e85a65b4202cf5e02a2d133caaff8643ae489 - md5: 5a08ae55869b0b1eb7fbee910aa30d19 + url: https://conda.anaconda.org/conda-forge/osx-64/cctools-1010.6-h5b2de21_2.conda + sha256: d34964e81d7f5c94279999a7af2a83677327418543848cd7e80d86f6a6e7cf14 + md5: 97f24eeeb3509883a6988894fd7c9bbf depends: - - cctools_osx-64 1010.6 h98e843e_1 - - ld64 951.9 h0a3eb4e_1 + - cctools_osx-64 1010.6 hea4301f_2 + - ld64 951.9 h0a3eb4e_2 - libllvm17 >=17.0.6,<17.1.0a0 license: APSL-2.0 license_family: Other purls: [] - size: 21528 - timestamp: 1726771688744 + size: 21119 + timestamp: 1732552446390 - kind: conda name: cctools version: '1010.6' - build: hf67d63f_1 - build_number: 1 + build: hf67d63f_2 + build_number: 2 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1010.6-hf67d63f_1.conda - sha256: b85469a1277da76dbbc71639b03014143cec96fe2e86dc11b1c3e299b9d29e2f - md5: f9138a6ffe696dadea9374101856747b + url: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1010.6-hf67d63f_2.conda + sha256: 5cd748e93968df7a3575f5cd051fb387ca0b1753537374e8c9270d44315186d2 + md5: 409225e7241a0099a81ce5fc0f3576d8 depends: - - cctools_osx-arm64 1010.6 h4208deb_1 - - ld64 951.9 h39a299f_1 + - cctools_osx-arm64 1010.6 h623e0ac_2 + - ld64 951.9 h39a299f_2 - libllvm17 >=17.0.6,<17.1.0a0 license: APSL-2.0 license_family: Other purls: [] - size: 21681 - timestamp: 1726771723258 + size: 21118 + timestamp: 1732552617055 - kind: conda name: cctools_osx-64 version: '1010.6' - build: h98e843e_1 - build_number: 1 + build: hea4301f_2 + build_number: 2 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-1010.6-h98e843e_1.conda - sha256: e28e55f55af27b66fbf4afc45f521f9a869e4495bd260c7c721dd2ac51e017a1 - md5: ed757b98aaa22a9e38c5a76191fb477c + url: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-1010.6-hea4301f_2.conda + sha256: ea6aa87dc44fbee374625e56224b2ebb350e29d68e06ff38642243eb7a5d40cd + md5: 70260b63386f080de1aa175dea5d57ac depends: - __osx >=10.13 - ld64_osx-64 >=951.9,<951.10.0a0 @@ -851,23 +851,23 @@ packages: - llvm-tools 17.0.* - sigtool constrains: - - ld64 951.9.* - - cctools 1010.6.* - clang 17.0.* + - cctools 1010.6.* + - ld64 951.9.* license: APSL-2.0 license_family: Other purls: [] - size: 1096895 - timestamp: 1726771657226 + size: 1120562 + timestamp: 1732552416131 - kind: conda name: cctools_osx-arm64 version: '1010.6' - build: h4208deb_1 - build_number: 1 + build: h623e0ac_2 + build_number: 2 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-1010.6-h4208deb_1.conda - sha256: 7122430e69ab8e38d382553bf7225b0887158341fe6879be4220e4e495b93aac - md5: bca79601bdb3a3dfa4c3917701a79f81 + url: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-1010.6-h623e0ac_2.conda + sha256: 1293ba9599964813cd5b7de3ef5b2a34f8c728f04f030add1d2daaa770563651 + md5: c667893c4bda0bd15dea9ae36e943c94 depends: - __osx >=11.0 - ld64_osx-arm64 >=951.9,<951.10.0a0 @@ -877,14 +877,14 @@ packages: - llvm-tools 17.0.* - sigtool constrains: - - clang 17.0.* - cctools 1010.6.* - ld64 951.9.* + - clang 17.0.* license: APSL-2.0 license_family: Other purls: [] - size: 1089821 - timestamp: 1726771687683 + size: 1101877 + timestamp: 1732552573870 - kind: pypi name: certifi version: 2024.8.30 @@ -1456,6 +1456,7 @@ packages: - python_abi 3.12.* *_cp312 - tomli license: Apache-2.0 + license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 364534 @@ -1474,6 +1475,7 @@ packages: - python_abi 3.13.* *_cp313 - tomli license: Apache-2.0 + license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 368990 @@ -1493,6 +1495,7 @@ packages: - python_abi 3.13.* *_cp313 - tomli license: Apache-2.0 + license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 370706 @@ -1513,6 +1516,7 @@ packages: - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: Apache-2.0 + license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 396450 @@ -2238,52 +2242,52 @@ packages: - kind: conda name: ld64 version: '951.9' - build: h0a3eb4e_1 - build_number: 1 + build: h0a3eb4e_2 + build_number: 2 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/ld64-951.9-h0a3eb4e_1.conda - sha256: d6ce3be8687f7fb607173112901e72262a4608dc351bfcb27012c068a5f25fa6 - md5: 8b8e1a4bd8384bf4b884c9e41636038f + url: https://conda.anaconda.org/conda-forge/osx-64/ld64-951.9-h0a3eb4e_2.conda + sha256: f9bc3ce2e24e3b0907436e151f5df34e407e626c7693586af5b2f39aaacd40f5 + md5: c198062cf84f2e797996ac156daffa9e depends: - - ld64_osx-64 951.9 h38c89e5_1 + - ld64_osx-64 951.9 h5ffbe8e_2 - libllvm17 >=17.0.6,<17.1.0a0 constrains: - - cctools_osx-64 1010.6.* - cctools 1010.6.* + - cctools_osx-64 1010.6.* license: APSL-2.0 license_family: Other purls: [] - size: 18841 - timestamp: 1726771674999 + size: 18434 + timestamp: 1732552435078 - kind: conda name: ld64 version: '951.9' - build: h39a299f_1 - build_number: 1 + build: h39a299f_2 + build_number: 2 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-951.9-h39a299f_1.conda - sha256: 7dc2adcb40f2bc61b7445980c882a690d1bdef5de206970da2779c2bec5fe876 - md5: b2f41d20ec157f81280e89bcb4f7164a + url: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-951.9-h39a299f_2.conda + sha256: 041d712eadca1911fac7112171db5c5c2e478c75b65ae4663005c49b77c65a45 + md5: caf11d8b84c7dd198309056dbd457b86 depends: - - ld64_osx-arm64 951.9 hc81425b_1 + - ld64_osx-arm64 951.9 h3f9b568_2 - libllvm17 >=17.0.6,<17.1.0a0 constrains: - - cctools_osx-arm64 1010.6.* - cctools 1010.6.* + - cctools_osx-arm64 1010.6.* license: APSL-2.0 license_family: Other purls: [] - size: 18942 - timestamp: 1726771707244 + size: 18503 + timestamp: 1732552594547 - kind: conda name: ld64_osx-64 version: '951.9' - build: h38c89e5_1 - build_number: 1 + build: h5ffbe8e_2 + build_number: 2 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-951.9-h38c89e5_1.conda - sha256: 8370978550dd96479d8ba635a59a97231ccf602d3a189cd2a4cb234947cf61f2 - md5: 423183fc4729ed4b8e167a980aad83ce + url: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-951.9-h5ffbe8e_2.conda + sha256: c523bf1f99b4056aa819e7c83acec58ac7d4a053924541309ece83ca2a37db3f + md5: 8cd0234328c8e9dcc2db757ff8a2ad22 depends: - __osx >=10.13 - libcxx @@ -2291,24 +2295,24 @@ packages: - sigtool - tapi >=1300.6.5,<1301.0a0 constrains: + - cctools 1010.6.* - ld 951.9.* - cctools_osx-64 1010.6.* - - cctools 1010.6.* - clang >=17.0.6,<18.0a0 license: APSL-2.0 license_family: Other purls: [] - size: 1088909 - timestamp: 1726771576050 + size: 1099649 + timestamp: 1732552367675 - kind: conda name: ld64_osx-arm64 version: '951.9' - build: hc81425b_1 - build_number: 1 + build: h3f9b568_2 + build_number: 2 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-951.9-hc81425b_1.conda - sha256: 37b083cbee78393c511f6ddb21a6ce484ebc037bc3f85c2c293fbc0f418616f1 - md5: 99473e66ff9960be2995dd1b5fe04ace + url: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-951.9-h3f9b568_2.conda + sha256: c67453a58870ce19b6acaa1d0db2c49848b7584c062d969f5d06c82ebd1454ef + md5: 68841f5b5956607ea9760cafa14271c5 depends: - __osx >=11.0 - libcxx @@ -2316,15 +2320,15 @@ packages: - sigtool - tapi >=1300.6.5,<1301.0a0 constrains: - - cctools_osx-arm64 1010.6.* - cctools 1010.6.* + - cctools_osx-arm64 1010.6.* - clang >=17.0.6,<18.0a0 - ld 951.9.* license: APSL-2.0 license_family: Other purls: [] - size: 1013046 - timestamp: 1726771628233 + size: 1017788 + timestamp: 1732552505749 - kind: conda name: ld_impl_linux-64 version: '2.43' @@ -2928,24 +2932,24 @@ packages: timestamp: 1729027639220 - kind: conda name: libhwloc - version: 2.11.1 - build: default_h8125262_1000 - build_number: 1000 + version: 2.11.2 + build: default_ha69328c_1001 + build_number: 1001 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.11.1-default_h8125262_1000.conda - sha256: 92728e292640186759d6dddae3334a1bc0b139740b736ffaeccb825fb8c07a2e - md5: 933bad6e4658157f1aec9b171374fde2 + url: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.11.2-default_ha69328c_1001.conda + sha256: 850e255997f538d5fb6ed651321141155a33bb781d43d326fc4ff62114dd2842 + md5: b87a0ac5ab6495d8225db5dc72dd21cd depends: - - libxml2 >=2.12.7,<3.0a0 - - pthreads-win32 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - libxml2 >=2.13.4,<3.0a0 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: BSD-3-Clause license_family: BSD purls: [] - size: 2379689 - timestamp: 1720461835526 + size: 2390021 + timestamp: 1731375651179 - kind: conda name: libiconv version: '1.17' @@ -3346,6 +3350,24 @@ packages: purls: [] size: 33601 timestamp: 1680112270483 +- kind: conda + name: libwinpthread + version: 12.0.0.r4.gg4f2fc60ca + build: h57928b3_8 + build_number: 8 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_8.conda + sha256: 6d5e158813ab8d553fbb0fedd0abe7bf92970b0be3a9ddf12da0f6cbad78f506 + md5: 03cccbba200ee0523bde1f3dad60b1f3 + depends: + - ucrt + constrains: + - pthreads-win32 <0.0a0 + - msys2-conda-epoch <0.0a0 + license: MIT AND BSD-3-Clause-Clear + purls: [] + size: 35433 + timestamp: 1724681489463 - kind: conda name: libxcrypt version: 4.4.36 @@ -3603,9 +3625,9 @@ packages: requires_python: '>=3.9' - kind: pypi name: matplotlib - version: 3.9.2 - url: https://files.pythonhosted.org/packages/27/75/de5b9cd67648051cae40039da0c8cbc497a0d99acb1a1f3d087cd66d27b7/matplotlib-3.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: f6ee45bc4245533111ced13f1f2cace1e7f89d1c793390392a80c139d6cf0e6c + version: 3.9.3 + url: https://files.pythonhosted.org/packages/28/dd/0a5176027c1cb94fe75f69f76cb274180c8abf740df6fc0e6a1e4cbaec3f/matplotlib-3.9.3-cp313-cp313-win_amd64.whl + sha256: 90a85a004fefed9e583597478420bf904bb1a065b0b0ee5b9d8d31b04b0f3f70 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -3619,15 +3641,15 @@ packages: - importlib-resources>=3.2.0 ; python_full_version < '3.10' - meson-python>=0.13.1 ; extra == 'dev' - numpy>=1.25 ; extra == 'dev' - - pybind11>=2.6 ; extra == 'dev' + - pybind11>=2.6,!=2.13.3 ; extra == 'dev' - setuptools-scm>=7 ; extra == 'dev' - setuptools>=64 ; extra == 'dev' requires_python: '>=3.9' - kind: pypi name: matplotlib - version: 3.9.2 - url: https://files.pythonhosted.org/packages/5c/7f/8932eac316b32f464b8f9069f151294dcd892c8fbde61fe8bcd7ba7f7f7e/matplotlib-3.9.2-cp313-cp313-macosx_10_13_x86_64.whl - sha256: 18128cc08f0d3cfff10b76baa2f296fc28c4607368a8402de61bb3f2eb33c7d9 + version: 3.9.3 + url: https://files.pythonhosted.org/packages/40/d6/70a196b0cf62e0a5bc64ccab07816ab4f6c98db0414a55280331a481a5bf/matplotlib-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b6c12514329ac0d03128cf1dcceb335f4fbf7c11da98bca68dca8dcb983153a9 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -3641,15 +3663,15 @@ packages: - importlib-resources>=3.2.0 ; python_full_version < '3.10' - meson-python>=0.13.1 ; extra == 'dev' - numpy>=1.25 ; extra == 'dev' - - pybind11>=2.6 ; extra == 'dev' + - pybind11>=2.6,!=2.13.3 ; extra == 'dev' - setuptools-scm>=7 ; extra == 'dev' - setuptools>=64 ; extra == 'dev' requires_python: '>=3.9' - kind: pypi name: matplotlib - version: 3.9.2 - url: https://files.pythonhosted.org/packages/90/89/9db9db3dd0ff3e2c49e452236dfe29e60b5586a88f8928ca1d153d0da8b5/matplotlib-3.9.2-cp313-cp313-macosx_11_0_arm64.whl - sha256: 4876d7d40219e8ae8bb70f9263bcbe5714415acfdf781086601211335e24f8aa + version: 3.9.3 + url: https://files.pythonhosted.org/packages/60/04/949640040982822416c471d9ebe4e9e6c69ca9f9bb6ba82ed30808863c02/matplotlib-3.9.3-cp313-cp313-macosx_10_13_x86_64.whl + sha256: 203d18df84f5288973b2d56de63d4678cc748250026ca9e1ad8f8a0fd8a75d83 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -3663,15 +3685,15 @@ packages: - importlib-resources>=3.2.0 ; python_full_version < '3.10' - meson-python>=0.13.1 ; extra == 'dev' - numpy>=1.25 ; extra == 'dev' - - pybind11>=2.6 ; extra == 'dev' + - pybind11>=2.6,!=2.13.3 ; extra == 'dev' - setuptools-scm>=7 ; extra == 'dev' - setuptools>=64 ; extra == 'dev' requires_python: '>=3.9' - kind: pypi name: matplotlib - version: 3.9.2 - url: https://files.pythonhosted.org/packages/b0/6d/3572fe243c74112fef120f0bc86f5edd21f49b60e8322fc7f6a01fe945dd/matplotlib-3.9.2-cp313-cp313-win_amd64.whl - sha256: f32c7410c7f246838a77d6d1eff0c0f87f3cb0e7c4247aebea71a6d5a68cab49 + version: 3.9.3 + url: https://files.pythonhosted.org/packages/9f/90/ebd37143cd3150b6c650ee1580024df3dd649d176e68d346f826b8d24e37/matplotlib-3.9.3-cp313-cp313-macosx_11_0_arm64.whl + sha256: b651b0d3642991259109dc0351fc33ad44c624801367bb8307be9bfc35e427ad requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -3685,7 +3707,7 @@ packages: - importlib-resources>=3.2.0 ; python_full_version < '3.10' - meson-python>=0.13.1 ; extra == 'dev' - numpy>=1.25 ; extra == 'dev' - - pybind11>=2.6 ; extra == 'dev' + - pybind11>=2.6,!=2.13.3 ; extra == 'dev' - setuptools-scm>=7 ; extra == 'dev' - setuptools>=64 ; extra == 'dev' requires_python: '>=3.9' @@ -4555,23 +4577,6 @@ packages: - pkg:pypi/psutil?source=hash-mapping size: 501944 timestamp: 1729847219864 -- kind: conda - name: pthreads-win32 - version: 2.9.1 - build: h2466b09_4 - build_number: 4 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-h2466b09_4.conda - sha256: b989bdcf0a22ba05a238adac1ad3452c11871681f565e509f629e225a26b7d45 - md5: cf98a67a1ec8040b42455002a24f0b0b - depends: - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: LGPL-2.1-or-later - purls: [] - size: 265827 - timestamp: 1728400965968 - kind: conda name: pycodestyle version: 2.12.1 @@ -4644,13 +4649,13 @@ packages: timestamp: 1727644193632 - kind: conda name: pytest - version: 8.3.3 + version: 8.3.4 build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.3-pyhd8ed1ab_0.conda - sha256: e99376d0068455712109d233f5790458ff861aeceb458bfda74e353338e4d815 - md5: c03d61f31f38fdb9facf70c29958bf7a + url: https://conda.anaconda.org/conda-forge/noarch/pytest-8.3.4-pyhd8ed1ab_0.conda + sha256: 254256beab3dcf29907fbdccee6fbbb3371e9ac3782d2b1b5864596a0317818e + md5: ff8f2ef7f2636906b3781d0cf92388d0 depends: - colorama - exceptiongroup >=1.0.0rc8 @@ -4662,11 +4667,10 @@ packages: constrains: - pytest-faulthandler >=2 license: MIT - license_family: MIT purls: - pkg:pypi/pytest?source=hash-mapping - size: 258293 - timestamp: 1725977334143 + size: 259634 + timestamp: 1733087755165 - kind: conda name: pytest-cov version: 6.0.0 @@ -4722,22 +4726,22 @@ packages: - kind: conda name: python version: 3.13.0 - build: h0608dab_100_cp313 - build_number: 100 + build: h3a8ca6c_101_cp313 + build_number: 101 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.0-h0608dab_100_cp313.conda - sha256: f4c8ca4c34cb2a508956cfc8c2130dc30f168a75ae8254da8c43b5dce10ed2ea - md5: 9603103619775a3f99fe4b58d278775e + url: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.0-h3a8ca6c_101_cp313.conda + sha256: c8b23bbdcd0e4f24fed2028cba20bd81325a4220439c1b8e6b06694f16642a2c + md5: 0acea4c3eee2454fd642d1a4eafa2943 depends: - __osx >=10.13 - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.6.3,<3.0a0 + - libexpat >=2.6.4,<3.0a0 - libffi >=3.4,<4.0a0 - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.46.1,<4.0a0 + - libsqlite >=3.47.0,<4.0a0 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - - openssl >=3.3.2,<4.0a0 + - openssl >=3.4.0,<4.0a0 - python_abi 3.13.* *_cp313 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 @@ -4745,27 +4749,27 @@ packages: - xz >=5.2.6,<6.0a0 license: Python-2.0 purls: [] - size: 13933848 - timestamp: 1729169951268 + size: 13941305 + timestamp: 1732736712289 - kind: conda name: python version: 3.13.0 - build: h75c3a9f_100_cp313 - build_number: 100 + build: hbbac1ca_101_cp313 + build_number: 101 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.0-h75c3a9f_100_cp313.conda - sha256: be9464399b76ae1fef77853eed70267ef657a98a5f69f7df012b7c6a34792151 - md5: 94ae22ea862d056ad1bc095443d02d73 + url: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.0-hbbac1ca_101_cp313.conda + sha256: 742544a4cf9a10cf2c16d35d96fb696c27d58b9df0cc29fbef5629283aeca941 + md5: e972e146a1e0cfb1f26da42cb6f6648c depends: - __osx >=11.0 - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.6.3,<3.0a0 + - libexpat >=2.6.4,<3.0a0 - libffi >=3.4,<4.0a0 - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.46.1,<4.0a0 + - libsqlite >=3.47.0,<4.0a0 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - - openssl >=3.3.2,<4.0a0 + - openssl >=3.4.0,<4.0a0 - python_abi 3.13.* *_cp313 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 @@ -4773,25 +4777,25 @@ packages: - xz >=5.2.6,<6.0a0 license: Python-2.0 purls: [] - size: 12804842 - timestamp: 1729168680448 + size: 12806496 + timestamp: 1732735488999 - kind: conda name: python version: 3.13.0 - build: hf5aa216_100_cp313 - build_number: 100 + build: hf5aa216_101_cp313 + build_number: 101 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/python-3.13.0-hf5aa216_100_cp313.conda - sha256: 18f3f0bd514c9101d38d57835b2d027958f3ae4b3b65c22d187a857aa26b3a08 - md5: 3c2f7ad3f598480fe2a09e4e33cb1a2a + url: https://conda.anaconda.org/conda-forge/win-64/python-3.13.0-hf5aa216_101_cp313.conda + sha256: b8eba57bd86c7890b27e67b477b52b5bd547946c354f29b9dbbc70ad83f2863b + md5: 158d6077a635cf0c0c23bec3955a4833 depends: - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.6.3,<3.0a0 + - libexpat >=2.6.4,<3.0a0 - libffi >=3.4,<4.0a0 - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.46.1,<4.0a0 + - libsqlite >=3.47.0,<4.0a0 - libzlib >=1.3.1,<2.0a0 - - openssl >=3.3.2,<4.0a0 + - openssl >=3.4.0,<4.0a0 - python_abi 3.13.* *_cp313 - tk >=8.6.13,<8.7.0a0 - tzdata @@ -4801,8 +4805,8 @@ packages: - xz >=5.2.6,<6.0a0 license: Python-2.0 purls: [] - size: 16641177 - timestamp: 1728417810202 + size: 16697406 + timestamp: 1732734725404 - kind: conda name: python-build version: 1.2.2.post1 @@ -5007,12 +5011,12 @@ packages: requires_python: '>=3.8' - kind: conda name: ruff - version: 0.8.0 + version: 0.8.1 build: py312h2156523_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.8.0-py312h2156523_0.conda - sha256: 4612ed5e995f4735ac8193c1319690b62440598fad9ebf24198b7ba49396cb2c - md5: 8c1d1a4d606a6d822643a44f124af736 + url: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.8.1-py312h2156523_0.conda + sha256: 8491e2095d5c0d92d63458fccc222a94e3892c463dd8503dc35e5096917c080a + md5: 2722627efb013e97b624001c391fc5cc depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 @@ -5025,16 +5029,16 @@ packages: license_family: MIT purls: - pkg:pypi/ruff?source=hash-mapping - size: 7886786 - timestamp: 1732285636885 + size: 7862629 + timestamp: 1732870126500 - kind: conda name: ruff - version: 0.8.0 + version: 0.8.1 build: py313h2493e73_0 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.8.0-py313h2493e73_0.conda - sha256: cf612c148a46d4d56143f25a081662ff0b0e254110a56be7f51c492de94d9a61 - md5: c4f55071260737af0613c25c7e0e8297 + url: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.8.1-py313h2493e73_0.conda + sha256: 23e2da831b6beb0a3a5bc8041d8072369a8576feb39b2405d12b4b22bb44a837 + md5: a47431da09c591ff3c3dbcc26b73f3e5 depends: - __osx >=10.13 - libcxx >=18 @@ -5046,16 +5050,16 @@ packages: license_family: MIT purls: - pkg:pypi/ruff?source=hash-mapping - size: 7284256 - timestamp: 1732286157815 + size: 7295758 + timestamp: 1732871014446 - kind: conda name: ruff - version: 0.8.0 + version: 0.8.1 build: py313h331c231_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.8.0-py313h331c231_0.conda - sha256: c3b6938349a1c97a54a1f921ea324284ad2eafe774ab33902028c39f8eb5fc92 - md5: 4c755a91f686eb21da6fbb8f7cb158bd + url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.8.1-py313h331c231_0.conda + sha256: 385d9fc0abbdd66dd68c0a71e8a9a3d57a4b1a069bcb452c991d51bde3781e21 + md5: 6faa6c22f03f4d1f769f42fed9602d1e depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 @@ -5066,16 +5070,16 @@ packages: license_family: MIT purls: - pkg:pypi/ruff?source=hash-mapping - size: 6873151 - timestamp: 1732286500899 + size: 6892876 + timestamp: 1732870841177 - kind: conda name: ruff - version: 0.8.0 + version: 0.8.1 build: py313heab95af_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.8.0-py313heab95af_0.conda - sha256: 8fa95df70654b8f7124924b023c7b5bd3548385b0c539fe7fd00c2850be4a811 - md5: 51a01bd7e637556f33e14695983fcd02 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.8.1-py313heab95af_0.conda + sha256: 0f4b82f2cb83af93c2b4a7964749b82799e51a126db4fd81a72574f8b661c6cb + md5: 2ac10bad59722af27f61b12c26106e01 depends: - __osx >=11.0 - libcxx >=18 @@ -5088,8 +5092,8 @@ packages: license_family: MIT purls: - pkg:pypi/ruff?source=hash-mapping - size: 6960999 - timestamp: 1732286297576 + size: 6949768 + timestamp: 1732870522684 - kind: conda name: scikit-learn version: 1.5.2 @@ -5308,20 +5312,21 @@ packages: - kind: conda name: setuptools version: 75.6.0 - build: pyhff2d567_0 + build: pyhff2d567_1 + build_number: 1 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.6.0-pyhff2d567_0.conda - sha256: eeec4645f70ce0ed03348397dced9d218a650a42df98592419af61d2689163ed - md5: 68d7d406366926b09a6a023e3d0f71d7 + url: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.6.0-pyhff2d567_1.conda + sha256: abb12e1dd515b13660aacb5d0fd43835bc2186cab472df25b7716cd65e095111 + md5: fc80f7995e396cbaeabd23cf46c413dc depends: - python >=3.9 license: MIT license_family: MIT purls: - pkg:pypi/setuptools?source=hash-mapping - size: 774304 - timestamp: 1732216189406 + size: 774252 + timestamp: 1732632769210 - kind: conda name: sigtool version: 0.1.3 @@ -5602,21 +5607,21 @@ packages: - kind: conda name: tbb version: 2021.13.0 - build: hc790b64_0 + build: h62715c5_1 + build_number: 1 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.13.0-hc790b64_0.conda - sha256: 990dbe4fb42f14700c22bd434d8312607bf8d0bd9f922b054e51fda14c41994c - md5: 28496a1e6af43c63927da4f80260348d + url: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.13.0-h62715c5_1.conda + sha256: 03cc5442046485b03dd1120d0f49d35a7e522930a2ab82f275e938e17b07b302 + md5: 9190dd0a23d925f7602f9628b3aed511 depends: - - libhwloc >=2.11.1,<2.11.2.0a0 + - libhwloc >=2.11.2,<2.11.3.0a0 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: Apache-2.0 - license_family: APACHE purls: [] - size: 151494 - timestamp: 1725532984828 + size: 151460 + timestamp: 1732982860332 - kind: conda name: threadpoolctl version: 3.5.0 @@ -5737,21 +5742,20 @@ packages: timestamp: 1604308660817 - kind: conda name: tomli - version: 2.1.0 - build: pyhff2d567_0 + version: 2.2.1 + build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/tomli-2.1.0-pyhff2d567_0.conda - sha256: 354b8a64d4f3311179d85aefc529ca201a36afc1af090d0010c46be7b79f9a47 - md5: 3fa1089b4722df3a900135925f4519d9 + url: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_0.conda + sha256: 706f35327a1b433fb57bb99e9fef878e90317fd6ea8cbcd454fb4af1a2e3f035 + md5: ee8ab0fe4c8dfc5a6319f7f8246022fc depends: - python >=3.9 license: MIT - license_family: MIT purls: - pkg:pypi/tomli?source=hash-mapping - size: 18741 - timestamp: 1731426862834 + size: 19129 + timestamp: 1732988289555 - kind: conda name: typing_extensions version: 4.12.2 @@ -5811,12 +5815,12 @@ packages: requires_python: '>=3.8' - kind: conda name: uv - version: 0.5.4 + version: 0.5.5 build: h0f3a69f_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/uv-0.5.4-h0f3a69f_0.conda - sha256: 826c427524d1930d66bdbbe9f2a380d46abc02e06b4b9870e4c5eb661a292156 - md5: ecce7c2d83da66eaabf8ba4961a4c828 + url: https://conda.anaconda.org/conda-forge/linux-64/uv-0.5.5-h0f3a69f_0.conda + sha256: d5e7c70e8fd6c328e9a61b6f003f32eb67f9fb4548e266310a1cca8afd9afc4a + md5: 8991c763ef7e46ea36acd42c8af4ebef depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 @@ -5825,16 +5829,16 @@ packages: - __glibc >=2.17 license: Apache-2.0 OR MIT purls: [] - size: 10061197 - timestamp: 1732159190433 + size: 10298311 + timestamp: 1732748322896 - kind: conda name: uv - version: 0.5.4 + version: 0.5.5 build: h668ec48_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/uv-0.5.4-h668ec48_0.conda - sha256: 85b61a53c0f39339c67a4f11b708fa1f59ad5f0a85d907f3c5ff001c88914b31 - md5: baad04fb088c4c66acf74a870bdb4536 + url: https://conda.anaconda.org/conda-forge/osx-arm64/uv-0.5.5-h668ec48_0.conda + sha256: 2e5e109a631845b307a054d6f04c7dc834eb5a0c0477fbecfec9f5850a6e36e1 + md5: 022b347422968f5d454b397193fe28ee depends: - __osx >=11.0 - libcxx >=18 @@ -5842,16 +5846,16 @@ packages: - __osx >=11.0 license: Apache-2.0 OR MIT purls: [] - size: 8942315 - timestamp: 1732160450871 + size: 8997490 + timestamp: 1732748956120 - kind: conda name: uv - version: 0.5.4 + version: 0.5.5 build: h8de1528_0 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/uv-0.5.4-h8de1528_0.conda - sha256: 7ee578a9944f39c7d249c18fcde7f8a6d3131c3788c9dc6b8b3c36c0784b3340 - md5: 0cf1dbd494c85fd0730a27b9c335b2ea + url: https://conda.anaconda.org/conda-forge/osx-64/uv-0.5.5-h8de1528_0.conda + sha256: 1fd02edd93c39676024211b32a04880e9579bd5534e694ae6bc6cef6453dc865 + md5: 863a10750b4ee2d02ae8dafdafdc4fdb depends: - __osx >=10.13 - libcxx >=18 @@ -5859,24 +5863,24 @@ packages: - __osx >=10.13 license: Apache-2.0 OR MIT purls: [] - size: 9694051 - timestamp: 1732159860536 + size: 9798812 + timestamp: 1732748791519 - kind: conda name: uv - version: 0.5.4 + version: 0.5.5 build: ha08ef0e_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/uv-0.5.4-ha08ef0e_0.conda - sha256: 493bece8c71254c2f9002fe5f53dd71265ce38d9dee2842286120e86acc2e523 - md5: 9fc38b02b5c4fa1be9a42c1b951d98e1 + url: https://conda.anaconda.org/conda-forge/win-64/uv-0.5.5-ha08ef0e_0.conda + sha256: 4daaf55e417b790b1bb5cf4cded0ed241dbd0b513933601b2be6fc8d55d13f53 + md5: 7efee2c95bdad3ec4df7b9d66471106e depends: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: Apache-2.0 OR MIT purls: [] - size: 10797785 - timestamp: 1732160258909 + size: 11162866 + timestamp: 1732749609026 - kind: conda name: vc version: '14.3' @@ -5985,20 +5989,21 @@ packages: - kind: conda name: zipp version: 3.21.0 - build: pyhd8ed1ab_0 + build: pyhd8ed1ab_1 + build_number: 1 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_0.conda - sha256: 232a30e4b0045c9de5e168dda0328dc0e28df9439cdecdfb97dd79c1c82c4cec - md5: fee389bf8a4843bd7a2248ce11b7f188 + url: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_1.conda + sha256: 567c04f124525c97a096b65769834b7acb047db24b15a56888a322bf3966c3e1 + md5: 0c3cc595284c5e8f0f9900a9b228a332 depends: - - python >=3.8 + - python >=3.9 license: MIT license_family: MIT purls: - pkg:pypi/zipp?source=hash-mapping - size: 21702 - timestamp: 1731262194278 + size: 21809 + timestamp: 1732827613585 - kind: conda name: zlib version: 1.3.1 diff --git a/tests/test_extend.py b/tests/test_extend.py deleted file mode 100644 index b37e990..0000000 --- a/tests/test_extend.py +++ /dev/null @@ -1,84 +0,0 @@ -"""Test feature selection extend""" -import numpy as np -import pytest -from numpy.testing import assert_array_equal -from sklearn.datasets import make_classification - -from fastcan import FastCan, extend - - -def test_select_extend_cls(): - # Test whether refine work correctly with random samples. - n_samples = 200 - n_features = 30 - n_informative = 20 - n_classes = 8 - n_repeated = 5 - n_to_select = 18 - - X, y = make_classification( - n_samples=n_samples, - n_features=n_features, - n_informative=n_informative, - n_repeated=n_repeated, - n_classes=n_classes, - n_clusters_per_class=1, - flip_y=0.0, - class_sep=10, - shuffle=False, - random_state=0, - ) - - n_features_to_select = 2 - selector = FastCan(n_features_to_select).fit(X, y) - indices = extend(selector, n_to_select, batch_size=3) - selector_inc = FastCan(n_features_to_select, indices_include=[10]).fit(X, y) - indices_inc = extend(selector_inc, n_to_select, batch_size=3) - selector_exc = FastCan( - n_features_to_select, indices_include=[10], indices_exclude=[0] - ).fit(X, y) - indices_exc = extend(selector_exc, n_to_select, batch_size=3) - - - assert np.unique(indices).size == n_to_select - assert_array_equal(indices[:n_features_to_select], selector.indices_) - assert np.unique(indices_inc).size == n_to_select - assert_array_equal(indices_inc[:n_features_to_select], selector_inc.indices_) - assert np.unique(indices_exc).size == n_to_select - assert_array_equal(indices_exc[:n_features_to_select], selector_exc.indices_) - assert ~np.isin(0, indices_exc) - - -def test_extend_error(): - # Test refine raise error. - n_samples = 200 - n_features = 20 - n_informative = 10 - n_classes = 8 - n_repeated = 5 - - X, y = make_classification( - n_samples=n_samples, - n_features=n_features, - n_informative=n_informative, - n_repeated=n_repeated, - n_classes=n_classes, - n_clusters_per_class=1, - flip_y=0.0, - class_sep=10, - shuffle=False, - random_state=0, - ) - - n_features_to_select = 2 - - selector = FastCan(n_features_to_select, indices_include=[0]).fit(X, y) - - with pytest.raises(ValueError, match=r"n_features_to_select .*"): - _ = extend(selector, n_features+1, batch_size=3) - - with pytest.raises(ValueError, match=r"The number of features to select .*"): - _ = extend(selector, n_features_to_select, batch_size=3) - - with pytest.raises(ValueError, match=r"The size of mini batch without .*"): - _ = extend(selector, n_features, batch_size=1) diff --git a/tests/test_minibatch.py b/tests/test_minibatch.py new file mode 100644 index 0000000..9018a09 --- /dev/null +++ b/tests/test_minibatch.py @@ -0,0 +1,64 @@ +"""Test feature selection with mini-batch""" +import numpy as np +import pytest +from sklearn.datasets import make_classification +from sklearn.preprocessing import OneHotEncoder + +from fastcan import minibatch + + +def test_select_minibatch_cls(): + # Test whether refine work correctly with random samples. + n_samples = 200 + n_features = 30 + n_informative = 20 + n_classes = 8 + n_repeated = 5 + n_to_select = 18 + + X, y = make_classification( + n_samples=n_samples, + n_features=n_features, + n_informative=n_informative, + n_repeated=n_repeated, + n_classes=n_classes, + n_clusters_per_class=1, + flip_y=0.0, + class_sep=10, + shuffle=False, + random_state=0, + ) + + indices = minibatch(X, y, n_to_select, batch_size=3) + assert np.unique(indices).size == n_to_select + assert indices.size == n_to_select + + Y = OneHotEncoder(sparse_output=False).fit_transform(y.reshape(-1, 1)) + + indices = minibatch(X, Y, n_to_select, batch_size=2) + assert np.unique(indices).size == n_to_select + assert indices.size == n_to_select + +def test_minibatch_error(): + # Test refine raise error. + n_samples = 200 + n_features = 20 + n_informative = 10 + n_classes = 8 + n_repeated = 5 + + X, y = make_classification( + n_samples=n_samples, + n_features=n_features, + n_informative=n_informative, + n_repeated=n_repeated, + n_classes=n_classes, + n_clusters_per_class=1, + flip_y=0.0, + class_sep=10, + shuffle=False, + random_state=0, + ) + + with pytest.raises(ValueError, match=r"n_features_to_select .*"): + _ = minibatch(X, y, n_features+1, batch_size=3) diff --git a/tests/test_narx.py b/tests/test_narx.py index bb4544a..ef5f9ed 100644 --- a/tests/test_narx.py +++ b/tests/test_narx.py @@ -19,7 +19,8 @@ def test_time_ids(): with pytest.raises(ValueError, match=r"The length of `include_zero_delay`.*"): make_time_shift_ids(3, 2, [False, True, False, True]) -def test_narx(): +@pytest.mark.parametrize("nan", [False, True]) +def test_narx(nan): rng = np.random.default_rng(12345) n_samples = 1000 max_delay = 3 @@ -32,8 +33,14 @@ def test_narx(): y = y[max_delay:]+e X = np.c_[u0[max_delay:], u1] + if nan: + X_nan_ids = rng.choice(n_samples, 20, replace=False) + y_nan_ids = rng.choice(n_samples, 10, replace=False) + X[X_nan_ids] = np.nan + y[y_nan_ids] = np.nan + params = { - "n_features_to_select": rng.integers(low=1, high=4), + "n_features_to_select": rng.integers(low=2, high=4), "max_delay": rng.integers(low=0, high=10), "poly_degree": rng.integers(low=2, high=5), } @@ -46,14 +53,19 @@ def test_narx(): params["include_zero_delay"] = [False, True, False] narx_0_delay = make_narx(X=X, y=y, **params) time_shift_ids = narx_0_delay.time_shift_ids - assert ~np.isin(0, time_shift_ids[time_shift_ids[:, 0] == 0][:, 1]) - assert np.isin(0, time_shift_ids[time_shift_ids[:, 0] == 1][:, 1]) - assert ~np.isin(0, time_shift_ids[time_shift_ids[:, 0] == 2][:, 1]) + time_ids_u0 = time_shift_ids[time_shift_ids[:, 0] == 0] + time_ids_u1 = time_shift_ids[time_shift_ids[:, 0] == 1] + time_ids_y = time_shift_ids[time_shift_ids[:, 0] == 2] + assert ~np.isin(0, time_ids_u0[:, 1]) or (time_ids_u0.size == 0) + assert np.isin(0, time_ids_u1[:, 1]) or (time_ids_u1.size == 0) + assert ~np.isin(0, time_ids_y[:, 1]) or (time_ids_y.size == 0) params["static_indices"] = [1] narx_static = make_narx(X=X, y=y, **params) time_shift_ids = narx_static.time_shift_ids - assert time_shift_ids[time_shift_ids[:, 0] == 1][0, 1] == 0 + time_ids_u1 = time_shift_ids[time_shift_ids[:, 0] == 1] + if time_ids_u1.size != 0: + assert time_ids_u1[0, 1] == 0 params["drop"] = 1 params["max_iter"] = 10 @@ -112,3 +124,5 @@ def test_narx(): poly_ids = make_poly_ids(time_shift_ids.shape[0]+1, 2) with pytest.raises(ValueError, match=r"The element x of poly_ids should .*"): narx_osa = Narx(time_shift_ids=time_shift_ids, poly_ids=poly_ids).fit(X, y) + +test_narx(True)