pax_global_header00006660000000000000000000000064151447415710014523gustar00rootroot0000000000000052 comment=3ee0934e33dca7a88ac15c0bdfde1b8e4bdae582 sparse-0.18.0/000077500000000000000000000000001514474157100131065ustar00rootroot00000000000000sparse-0.18.0/.codecov.yml000066400000000000000000000004741514474157100153360ustar00rootroot00000000000000comment: false coverage: status: project: default: # Total project must be 95% target: '100%' threshold: '5%' patch: default: # Patch coverage must be 92% target: '100%' threshold: '8%' precision: 2 round: down range: 80...98 sparse-0.18.0/.coveragerc000066400000000000000000000002561514474157100152320ustar00rootroot00000000000000[run] source= sparse/ omit= sparse/_version.py **/tests/* [report] exclude_lines = pragma: no cover return NotImplemented raise NotImplementedError sparse-0.18.0/.gitattributes000066400000000000000000000001661514474157100160040ustar00rootroot00000000000000sparse/_version.py export-subst # GitHub syntax highlighting pixi.lock linguist-language=YAML linguist-generated=true sparse-0.18.0/.github/000077500000000000000000000000001514474157100144465ustar00rootroot00000000000000sparse-0.18.0/.github/CODE_OF_CONDUCT.md000066400000000000000000000001031514474157100172370ustar00rootroot00000000000000# Code of Conduct Please see [`docs/conduct.md`](docs/conduct.md) sparse-0.18.0/.github/FUNDING.yml000066400000000000000000000012251514474157100162630ustar00rootroot00000000000000# These are supported funding model platforms github: [Quansight, Quansight-Labs] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] sparse-0.18.0/.github/ISSUE_TEMPLATE/000077500000000000000000000000001514474157100166315ustar00rootroot00000000000000sparse-0.18.0/.github/ISSUE_TEMPLATE/bug_report.yml000066400000000000000000000037231514474157100215310ustar00rootroot00000000000000name: Bug report description: Report to help us reproduce the bug title: "Bug: " labels: ["bug", "needs triage"] body: - type: markdown attributes: value: > ## Thanks for taking the time to fill out this report - type: checkboxes id: checks attributes: label: sparse version checks options: - label: > I checked that this issue has not been reported before [list of issues](https://github.com/pydata/sparse/issues). required: true - label: > I have confirmed this bug exists on the latest version of sparse. required: true - label: > I have confirmed this bug exists on the main branch of sparse. - type: textarea attributes: label: Describe the bug description: > A clear and concise description of what the bug is. validations: required: true - type: textarea attributes: label: Steps or code to reproduce the bug description: | Please add a minimal code example to reproduce the bug. validations: required: true - type: textarea attributes: label: Expected results description: > Please paste or describe the expected results. placeholder: > Example: No error is thrown. validations: required: true - type: textarea attributes: label: Actual results description: | Please paste or describe the results you observe instead of the expected results. validations: required: true - type: textarea attributes: label: Please describe your system. value: | 1. OS and version: [e.g. Windows 10] 2. sparse version (sparse.__version__) 3. NumPy version (np.__version__) 4. Numba version (numba.__version__) validations: required: true - type: textarea attributes: label: Relevant log output description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. render: shell sparse-0.18.0/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000001361514474157100206210ustar00rootroot00000000000000blank_issues_enabled: true name: Blank issue url: https://github.com/pydata/sparse/issues/new sparse-0.18.0/.github/ISSUE_TEMPLATE/doc_issue.yml000066400000000000000000000016511514474157100213340ustar00rootroot00000000000000name: Documentation improvement description: Report to improve the docs. You could also directly open a PR with your suggestions. title: "Doc: " labels: ["docs", "needs triage"] body: - type: markdown attributes: value: > ## Thanks for taking the time to fill out this form - type: dropdown id: TYPE attributes: label: What type of report is this? options: - 'Correction' - 'Improvement' validations: required: true - type: textarea attributes: label: Please describe the issue. description: > Tell us if something is unclear or incorrect, and where. validations: required: true - type: textarea attributes: label: If you have a suggestion on how it should be, add it below. description: > How can we improve it - type: markdown attributes: value: > ### If you are interested in opening a pull request to fix this, please let us know. sparse-0.18.0/.github/ISSUE_TEMPLATE/feature_request.yml000066400000000000000000000024261514474157100225630ustar00rootroot00000000000000name: Feature request description: Form to request a new feature title: "Enh: " labels: ["enhancement", "needs triage"] body: - type: markdown attributes: value: > ## Thanks for helping us improve sparse! - type: markdown attributes: value: > ### Before submitting a request, please check if it has already been discused in the [list of issues](https://github.com/pydata/sparse/issues). - type: textarea attributes: label: Please describe the purpose of the new feature or describe the problem to solve. description: > A clear description of the objective. validations: required: true - type: textarea attributes: label: Suggest a solution if possible. description: > Please suggest a solution if you can. validations: required: false - type: textarea attributes: label: If you have tried alternatives, please describe them below. description: > What you have tried if applicable. - type: textarea attributes: label: Additional information that may help us understand your needs. description: > Context, screenshots, or any useful information. - type: markdown attributes: value: > ### If you are interested in opening a pull request to fix this, please let us know. sparse-0.18.0/.github/ISSUE_TEMPLATE/question-support.yml000066400000000000000000000010341514474157100227330ustar00rootroot00000000000000name: Question/Support description: A question about how to use this library. title: "Usage: " labels: "usage" body: - type: markdown attributes: value: > ## Thank you for your interest in sparse - type: textarea attributes: label: Please provide a description of what you'd like to do. validations: required: true - type: textarea attributes: label: Example Code description: > Syntactically valid Python code that shows what you want to do, possibly with placeholder functions or methods. sparse-0.18.0/.github/dependabot.yml000066400000000000000000000007151514474157100173010ustar00rootroot00000000000000# Set update schedule for GitHub Actions # This opens a PR when actions in workflows need an update version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: # Check for updates to GitHub Actions every week interval: "weekly" commit-message: prefix: "skip changelog" # So this PR will not be added to release-drafter include: "scope" # List of the updated dependencies in the commit will be added sparse-0.18.0/.github/pull_request_template.md000066400000000000000000000013651514474157100214140ustar00rootroot00000000000000 ## What type of PR is this? (check all applicable) - [ ] ๐Ÿ’พ Refactor - [ ] ๐Ÿช„ Feature - [ ] ๐Ÿž Bug Fix - [ ] ๐Ÿ”ง Optimization - [ ] ๐Ÿ“š Documentation - [ ] ๐Ÿงช Test - [ ] ๐Ÿ› ๏ธ Other ## Related issues - Related issue # - Closes # ## Checklist - [ ] Code follows style guide - [ ] Tests added - [ ] Documented the changes *** ## Please explain your changes below. sparse-0.18.0/.github/release-drafter.yml000066400000000000000000000027331514474157100202430ustar00rootroot00000000000000exclude-labels: # When PR will not be classified if it has these labels - skip changelog - release name-template: 'Sparse v$RESOLVED_VERSION' change-template: '- $TITLE (#$NUMBER)' autolabeler: - label: breaking title: # Example: feat!: ... - '/^(build|chore|ci|depr|docs|feat|fix|perf|refactor|release|test)(\(.*\))?\!\: /' - label: build title: - '/^(build)/' - label: internal title: - '/^(chore|ci|refactor|test)/' - label: deprecation title: - '/^depr/' - label: documentation title: - '/^(docs|docstring)/' - label: enhancement title: - '/^feat/' - label: fix title: - '/^fix/' - label: performance title: - '/^perf/' - label: release title: - '/^release/' - label: 'skip changelog' title: - '/^\[pre-commit.ci\]/' categories: - title: ๐Ÿ“ฃ Highlights labels: highlight - title: ๐Ÿงจ Breaking changes labels: - breaking - breaking python - title: ๐Ÿšง Deprecations labels: deprecation - title: ๐Ÿช„ Performance improvements labels: performance - title: ๐ŸŽŠ Enhancements labels: enhancement - title: ๐Ÿž Bug fixes labels: fix - title: ๐Ÿ“š Documentation labels: documentation - title: ๐Ÿงฐ Build system labels: build - title: ๐Ÿ”ง Other improvements labels: internal template: | ## Changes $CHANGES Thank you to all our contributors for making this release possible! $CONTRIBUTORS sparse-0.18.0/.github/workflows/000077500000000000000000000000001514474157100165035ustar00rootroot00000000000000sparse-0.18.0/.github/workflows/ci.yml000066400000000000000000000054721514474157100176310ustar00rootroot00000000000000defaults: run: shell: bash -leo pipefail {0} concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true name: "CI" jobs: test: name: Test ${{ matrix.os }} (${{ join(matrix.tasks, ' ') }}) strategy: matrix: os: [macos-latest, windows-latest] tasks: [[test-numba, test-finch, test-mlir]] environments: [[test, finch, mlir]] include: - os: ubuntu-latest tasks: [test-numba, test-finch, test-mlir, test-numba-mindeps, test-finch-mindeps, test-mlir-mindeps] environments: [mindeps, test, finch, mlir] fail-fast: false runs-on: ${{ matrix.os }} steps: - name: Checkout Repo uses: actions/checkout@v4 - uses: prefix-dev/setup-pixi@v0.9.4 with: pixi-version: v0.63.2 cache: true environments: ${{ join(matrix.environments, ' ') }} - name: hack for setuptools-scm run: pixi build - name: Run tests run: | for task in ${{ join(matrix.tasks, ' ') }}; do pixi run "$task" done - uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./**/coverage*.xml examples: runs-on: ubuntu-latest steps: - name: Checkout Repo uses: actions/checkout@v4 - uses: prefix-dev/setup-pixi@v0.9.4 with: pixi-version: v0.63.2 cache: true environments: examples - name: Run examples run: pixi run test-examples-ci notebooks: runs-on: ubuntu-latest steps: - name: Checkout Repo uses: actions/checkout@v4 - uses: prefix-dev/setup-pixi@v0.9.4 with: pixi-version: v0.63.2 cache: true environments: notebooks - name: Run notebooks run: pixi run test-notebooks-ci array_api_tests: name: ${{ matrix.task }} strategy: matrix: include: - task: xp-tests-numba environments: [xp-tests] - task: xp-tests-finch environments: [finch, xp-tests] fail-fast: false runs-on: ubuntu-latest steps: - name: Checkout Repo uses: actions/checkout@v4 - uses: prefix-dev/setup-pixi@v0.9.4 with: pixi-version: v0.63.2 cache: true environments: ${{ join(matrix.environments, ' ') }} - name: Run the test suite run: pixi run ${{ matrix.task }} on: # Trigger the workflow on push or pull request, # but only for the main branch push: branches: - main - vnext pull_request: branches: - main - vnext # Also trigger on page_build, as well as release created events page_build: release: types: # This configuration does not affect the page_build event above - created sparse-0.18.0/.github/workflows/codspeed.yml000066400000000000000000000011441514474157100210140ustar00rootroot00000000000000name: codspeed-benchmarks on: push: branches: - "main" # or "master" pull_request: # `workflow_dispatch` allows CodSpeed to trigger backtest # performance analysis in order to generate initial data. workflow_dispatch: jobs: benchmarks: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Install dependencies run: pip install ".[all]" - name: Run benchmarks uses: CodSpeedHQ/action@v3 with: run: pytest benchmarks/ --codspeed sparse-0.18.0/.github/workflows/release-drafter.yml000066400000000000000000000025361514474157100223010ustar00rootroot00000000000000name: Release Drafter on: push: # branches to consider in the event; optional, defaults to all branches: - main # pull_request event is required only for autolabeler pull_request: # Only following types are handled by the action, but one can default to all as well types: [opened, reopened, synchronize, edited] # pull_request_target event is required for autolabeler to support PRs from forks pull_request_target: types: [opened, reopened, synchronize, edited] permissions: contents: read jobs: update_release_draft: permissions: # write permission is required to create a github release contents: write # write permission is required for autolabeler # otherwise, read permission is required at least pull-requests: write runs-on: ubuntu-latest steps: # (Optional) GitHub Enterprise requires GHE_HOST variable set #- name: Set GHE_HOST # run: | # echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV # Drafts your next Release notes as Pull Requests are merged into "main" - uses: release-drafter/release-drafter@v6 # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml # with: # config-name: my-config.yml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} sparse-0.18.0/.gitignore000066400000000000000000000017761514474157100151110ustar00rootroot00000000000000#####=== Python ===##### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *,cover .pytest_cache/ test_results/ junit/ .hypothesis/ coverage_*.xml # Translations *.mo *.pot # Django stuff: *.log # mkdocs documentation site/ # PyBuilder target/ # IDE .idea/ .vscode/ default.profraw # Sandbox sandbox.py # macOS **/.DS_Store # Version file sparse/_version.py # Benchmark Results results/ # Notebooks converted to scripts. docs/examples_ipynb/ # Envs .pixi/ .venv/ sparse-0.18.0/.pre-commit-config.yaml000066400000000000000000000013741514474157100173740ustar00rootroot00000000000000repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - id: fix-byte-order-marker - id: destroyed-symlinks - id: mixed-line-ending - id: name-tests-test args: ["--pytest-test-first"] - id: no-commit-to-branch - id: pretty-format-json args: ["--autofix", "--no-ensure-ascii"] exclude: ".ipynb" - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.15.1 hooks: - id: ruff-check args: ["--fix"] types_or: [ python, pyi, jupyter ] - id: ruff-format types_or: [ python, pyi, jupyter ] - repo: https://github.com/kynan/nbstripout rev: 0.9.0 hooks: - id: nbstripout sparse-0.18.0/.readthedocs.yml000066400000000000000000000007501514474157100161760ustar00rootroot00000000000000# Read the Docs configuration file for MkDocs projects # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Set the version of Python and other tools you might need build: os: ubuntu-22.04 tools: python: "3.12" mkdocs: configuration: mkdocs.yml fail_on_warning: false # Optionally declare the Python requirements required to build your docs python: install: - method: pip path: . extra_requirements: - docs sparse-0.18.0/LICENSE000066400000000000000000000027551514474157100141240ustar00rootroot00000000000000BSD 3-Clause License Copyright (c) 2018, Sparse developers All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. sparse-0.18.0/README.md000066400000000000000000000016041514474157100143660ustar00rootroot00000000000000![Sparse](docs/assets/images/logo_with_text.svg) # Sparse Multidimensional Arrays [![Build Status](https://github.com/pydata/sparse/actions/workflows/ci.yml/badge.svg)]( https://github.com/pydata/sparse/actions/workflows/ci.yml) [![Docs Status](https://readthedocs.org/projects/sparse-nd/badge/?version=latest)]( http://sparse.pydata.org/en/latest/?badge=latest) [![Coverage](https://codecov.io/gh/pydata/sparse/branch/main/graph/badge.svg)]( https://codecov.io/gh/pydata/sparse) ## This library provides multi-dimensional sparse arrays. - ๐Ÿ“š [Documentation](http://sparse.pydata.org) - ๐Ÿ™Œ [Contributing](https://github.com/pydata/sparse/blob/main/docs/contributing.md) - ๐Ÿชฒ [Bug Reports/Feature Requests](https://github.com/pydata/sparse/issues) - ๐Ÿ’ฌ [Discord Server](https://discord.gg/vur45CbwMz) [Channel](https://discord.com/channels/786703927705862175/1301155724646289420) sparse-0.18.0/benchmarks/000077500000000000000000000000001514474157100152235ustar00rootroot00000000000000sparse-0.18.0/benchmarks/__init__.py000066400000000000000000000000001514474157100173220ustar00rootroot00000000000000sparse-0.18.0/benchmarks/conftest.py000066400000000000000000000002751514474157100174260ustar00rootroot00000000000000import pytest import numpy as np @pytest.fixture(scope="function") def rng(): return np.random.default_rng(seed=42) @pytest.fixture def max_size(scope="session"): return 2**26 sparse-0.18.0/benchmarks/test_benchmark_coo.py000066400000000000000000000103251514474157100214270ustar00rootroot00000000000000import itertools import operator import sparse import pytest DENSITY = 0.01 def format_id(format): return f"{format=}" @pytest.fixture(params=["coo", "gcxs"], ids=format_id) def format_param(request): return request.param @pytest.fixture def matmul_args(sides, format_param, rng, max_size): m, n, p = sides if m * n >= max_size or n * p >= max_size: pytest.skip() x = sparse.random((m, n), density=DENSITY, format=format_param, random_state=rng) y = sparse.random((n, p), density=DENSITY, format=format_param, random_state=rng) return x, y def test_matmul(benchmark, matmul_args): x, y = matmul_args x @ y # Numba compilation @benchmark def bench(): x @ y def get_test_id(params): side, rank, format = params return f"{side=}-{rank=}-{format=}" @pytest.fixture(params=itertools.product([100, 500, 1000], [1, 2, 3, 4], ["coo", "gcxs"]), ids=get_test_id) def elemwise_args(request, rng, max_size): side, rank, format = request.param if side**rank >= max_size: pytest.skip() shape = (side,) * rank x = sparse.random(shape, density=DENSITY, format=format, random_state=rng) y = sparse.random(shape, density=DENSITY, format=format, random_state=rng) return x, y @pytest.mark.parametrize("f", [operator.add, operator.mul]) def test_elemwise(benchmark, f, elemwise_args): x, y = elemwise_args f(x, y) @benchmark def bench(): f(x, y) def get_elemwise_ids(params): side, format = params return f"{side=}-{format=}" @pytest.fixture(params=itertools.product([100, 500, 1000], ["coo", "gcxs"]), ids=get_elemwise_ids) def elemwise_broadcast_args(request, rng, max_size): side, format = request.param if side**2 >= max_size: pytest.skip() x = sparse.random((side, 1, side), density=DENSITY, format=format, random_state=rng) y = sparse.random((side, side), density=DENSITY, format=format, random_state=rng) return x, y @pytest.mark.parametrize("f", [operator.add, operator.mul]) def test_elemwise_broadcast(benchmark, f, elemwise_broadcast_args): x, y = elemwise_broadcast_args f(x, y) @benchmark def bench(): f(x, y) @pytest.fixture(params=itertools.product([100, 500, 1000], [1, 2, 3], ["coo", "gcxs"]), ids=get_test_id) def indexing_args(request, rng, max_size): side, rank, format = request.param if side**rank >= max_size: pytest.skip() shape = (side,) * rank return sparse.random(shape, density=DENSITY, format=format, random_state=rng) def test_index_scalar(benchmark, indexing_args): x = indexing_args side = x.shape[0] rank = x.ndim x[(side // 2,) * rank] # Numba compilation @benchmark def bench(): x[(side // 2,) * rank] def test_index_slice(benchmark, indexing_args): x = indexing_args side = x.shape[0] rank = x.ndim x[(slice(side // 2),) * rank] # Numba compilation @benchmark def bench(): x[(slice(side // 2),) * rank] def test_index_fancy(benchmark, indexing_args, rng): x = indexing_args side = x.shape[0] index = rng.integers(0, side, size=(side // 2,)) x[index] # Numba compilation @benchmark def bench(): x[index] def get_sides_ids(param): m, n, p = param return f"{m=}-{n=}-{p=}" @pytest.fixture(params=itertools.product([200, 500, 1000], [200, 500, 1000], [200, 500, 1000]), ids=get_sides_ids) def sides(request): m, n, p = request.param return m, n, p @pytest.fixture(params=([(0, "coo"), (0, "gcxs"), (1, "gcxs")]), ids=["coo", "gcxs-0-axis", "gcxs-1-axis"]) def densemul_args(request, sides, rng, max_size): compressed_axis, format = request.param m, n, p = sides if m * n >= max_size or n * p >= max_size: pytest.skip() if format == "coo": x = sparse.random((m, n), density=DENSITY / 10, format=format, random_state=rng) else: x = sparse.random((m, n), density=DENSITY / 10, format=format, random_state=rng).change_compressed_axes( (compressed_axis,) ) t = rng.random((n, p)) return x, t def test_gcxs_dot_ndarray(benchmark, densemul_args): x, t = densemul_args # Numba compilation x @ t @benchmark def bench(): x @ t sparse-0.18.0/benchmarks/test_elemwise.py000066400000000000000000000033471514474157100204550ustar00rootroot00000000000000import importlib import operator import os import sparse import pytest import scipy.sparse as sps DENSITY = 0.001 def get_test_id(side): return f"{side=}" @pytest.fixture(params=[100, 500, 1000], ids=get_test_id) def elemwise_args(request, rng, max_size): side = request.param if side**2 >= max_size: pytest.skip() s1_sps = sps.random(side, side, format="csr", density=DENSITY, random_state=rng) * 10 s1_sps.sum_duplicates() s2_sps = sps.random(side, side, format="csr", density=DENSITY, random_state=rng) * 10 s2_sps.sum_duplicates() return s1_sps, s2_sps @pytest.fixture(params=[operator.add, operator.mul, operator.gt]) def elemwise_function(request): return request.param @pytest.fixture(params=["SciPy", "Numba", "Finch"]) def backend_name(request): return request.param @pytest.fixture def backend_setup(backend_name): os.environ[sparse._ENV_VAR_NAME] = backend_name importlib.reload(sparse) yield sparse, backend_name del os.environ[sparse._ENV_VAR_NAME] importlib.reload(sparse) @pytest.fixture def sparse_arrays(elemwise_args, backend_setup): s1_sps, s2_sps = elemwise_args sparse, backend_name = backend_setup if backend_name == "SciPy": s1 = s1_sps s2 = s2_sps elif backend_name == "Numba": s1 = sparse.asarray(s1_sps) s2 = sparse.asarray(s2_sps) elif backend_name == "Finch": s1 = sparse.asarray(s1_sps.asformat("csc"), format="csc") s2 = sparse.asarray(s2_sps.asformat("csc"), format="csc") return s1, s2 def test_elemwise(benchmark, elemwise_function, sparse_arrays): s1, s2 = sparse_arrays elemwise_function(s1, s2) @benchmark def bench(): elemwise_function(s1, s2) sparse-0.18.0/benchmarks/test_tensordot.py000066400000000000000000000040561514474157100206620ustar00rootroot00000000000000import itertools import sparse import pytest import numpy as np DENSITY = 0.01 def get_sides_ids(param): m, n, p, q = param return f"{m=}-{n=}-{p=}-{q=}" @pytest.fixture( params=itertools.product([10, 50], [10, 20], [20, 50], [10, 50]), ids=get_sides_ids, scope="function", ) def sides(request): m, n, p, q = request.param return m, n, p, q def get_tensor_ids(param): left_index, right_index, left_format, right_format = param return f"{left_index=}-{right_index=}-{left_format=}-{right_format=}" @pytest.fixture( params=([(1, 2, "dense", "coo"), (1, 2, "coo", "coo"), (1, 1, "coo", "dense")]), ids=get_tensor_ids, scope="function", ) def tensordot_args(request, sides, rng, max_size): m, n, p, q = sides if m * n * p * q >= max_size: pytest.skip() left_index, right_index, left_format, right_format = request.param t = rng.random((m, n)) if left_format == "dense" and right_format == "coo": left_tensor = t right_tensor = sparse.random((m, p, n, q), density=DENSITY, format=right_format, random_state=rng) if left_format == "coo" and right_format == "coo": left_tensor = sparse.random((m, p), density=DENSITY, format=left_format, random_state=rng) right_tensor = sparse.random((m, n, p, q), density=DENSITY, format=right_format, random_state=rng) if left_format == "coo" and right_format == "dense": left_tensor = sparse.random((m, n, p, q), density=DENSITY, format=left_format, random_state=rng) right_tensor = t return left_index, right_index, left_tensor, right_tensor @pytest.mark.parametrize("return_type", [np.ndarray, sparse.COO]) def test_tensordot(benchmark, return_type, tensordot_args): left_index, right_index, left_tensor, right_tensor = tensordot_args sparse.tensordot(left_tensor, right_tensor, axes=([0, left_index], [0, right_index]), return_type=return_type) @benchmark def bench(): sparse.tensordot(left_tensor, right_tensor, axes=([0, left_index], [0, right_index]), return_type=return_type) sparse-0.18.0/benchmarks/utils.py000066400000000000000000000001021514474157100167260ustar00rootroot00000000000000import os CI_MODE = bool(int(os.getenv("CI_MODE", default="0"))) sparse-0.18.0/benchmarks_original/000077500000000000000000000000001514474157100171075ustar00rootroot00000000000000sparse-0.18.0/benchmarks_original/__init__.py000066400000000000000000000000001514474157100212060ustar00rootroot00000000000000sparse-0.18.0/benchmarks_original/elemwise_example.py000066400000000000000000000040051514474157100230050ustar00rootroot00000000000000import importlib import operator import os import sparse from utils import benchmark import numpy as np import scipy.sparse as sps LEN = 10000 DENSITY = 0.001 ITERS = 3 rng = np.random.default_rng(0) if __name__ == "__main__": print("Elementwise Example:\n") for func_name in ["multiply", "add", "greater_equal"]: print(f"{func_name} benchmark:\n") s1_sps = sps.random(LEN, LEN, format="csr", density=DENSITY, random_state=rng) * 10 s1_sps.sum_duplicates() s2_sps = sps.random(LEN, LEN, format="csr", density=DENSITY, random_state=rng) * 10 s2_sps.sum_duplicates() # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) s1 = sparse.asarray(s1_sps.asformat("csc"), format="csc") s2 = sparse.asarray(s2_sps.asformat("csc"), format="csc") func = getattr(sparse, func_name) # Compile & Benchmark result_finch = benchmark(func, args=[s1, s2], info="Finch", iters=ITERS) # ======= Numba ======= os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) s1 = sparse.asarray(s1_sps) s2 = sparse.asarray(s2_sps) func = getattr(sparse, func_name) # Compile & Benchmark result_numba = benchmark(func, args=[s1, s2], info="Numba", iters=ITERS) # ======= SciPy ======= s1 = s1_sps s2 = s2_sps if func_name == "multiply": func, args = s1.multiply, [s2] elif func_name == "add": func, args = operator.add, [s1, s2] elif func_name == "greater_equal": func, args = operator.ge, [s1, s2] # Compile & Benchmark result_scipy = benchmark(func, args=args, info="SciPy", iters=ITERS) np.testing.assert_allclose(result_numba.todense(), result_scipy.toarray()) np.testing.assert_allclose(result_finch.todense(), result_numba.todense()) np.testing.assert_allclose(result_finch.todense(), result_scipy.toarray()) sparse-0.18.0/benchmarks_original/matmul_example.py000066400000000000000000000031241514474157100224730ustar00rootroot00000000000000import importlib import os import sparse from utils import benchmark import numpy as np import scipy.sparse as sps LEN = 100000 DENSITY = 0.00001 ITERS = 3 rng = np.random.default_rng(0) if __name__ == "__main__": print("Matmul Example:\n") a_sps = sps.random(LEN, LEN - 10, format="csr", density=DENSITY, random_state=rng) * 10 a_sps.sum_duplicates() b_sps = sps.random(LEN - 10, LEN, format="csr", density=DENSITY, random_state=rng) * 10 b_sps.sum_duplicates() # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) a = sparse.asarray(a_sps) b = sparse.asarray(b_sps) @sparse.compiled() def sddmm_finch(a, b): return a @ b # Compile & Benchmark result_finch = benchmark(sddmm_finch, args=[a, b], info="Finch", iters=ITERS) # ======= Numba ======= os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) a = sparse.asarray(a_sps) b = sparse.asarray(b_sps) def sddmm_numba(a, b): return a @ b # Compile & Benchmark result_numba = benchmark(sddmm_numba, args=[a, b], info="Numba", iters=ITERS) # ======= SciPy ======= def sddmm_scipy(a, b): return a @ b a = a_sps b = b_sps # Compile & Benchmark result_scipy = benchmark(sddmm_scipy, args=[a, b], info="SciPy", iters=ITERS) # np.testing.assert_allclose(result_numba.todense(), result_scipy.toarray()) # np.testing.assert_allclose(result_finch.todense(), result_numba.todense()) # np.testing.assert_allclose(result_finch.todense(), result_scipy.toarray()) sparse-0.18.0/benchmarks_original/mttkrp_example.py000066400000000000000000000026401514474157100225170ustar00rootroot00000000000000import importlib import os import sparse from utils import benchmark import numpy as np I_ = 1000 J_ = 25 K_ = 1000 L_ = 100 DENSITY = 0.0001 ITERS = 3 rng = np.random.default_rng(0) if __name__ == "__main__": print("MTTKRP Example:\n") B_sps = sparse.random((I_, K_, L_), density=DENSITY, random_state=rng) * 10 D_sps = rng.random((L_, J_)) * 10 C_sps = rng.random((K_, J_)) * 10 # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) B = sparse.asarray(B_sps.todense(), format="csf") D = sparse.asarray(np.array(D_sps, order="F")) C = sparse.asarray(np.array(C_sps, order="F")) @sparse.compiled() def mttkrp_finch(B, D, C): return sparse.sum(B[:, :, :, None] * D[None, None, :, :] * C[None, :, None, :], axis=(1, 2)) # Compile & Benchmark result_finch = benchmark(mttkrp_finch, args=[B, D, C], info="Finch", iters=ITERS) # ======= Numba ======= os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) B = sparse.asarray(B_sps, format="gcxs") D = D_sps C = C_sps def mttkrp_numba(B, D, C): return sparse.sum(B[:, :, :, None] * D[None, None, :, :] * C[None, :, None, :], axis=(1, 2)) # Compile & Benchmark result_numba = benchmark(mttkrp_numba, args=[B, D, C], info="Numba", iters=ITERS) np.testing.assert_allclose(result_finch.todense(), result_numba.todense()) sparse-0.18.0/benchmarks_original/sddmm_example.py000066400000000000000000000034611514474157100223040ustar00rootroot00000000000000import importlib import os import sparse from utils import benchmark import numpy as np import scipy.sparse as sps LEN = 10000 DENSITY = 0.00001 ITERS = 3 rng = np.random.default_rng(0) if __name__ == "__main__": print("SDDMM Example:\n") a_sps = rng.random((LEN, LEN - 10)) * 10 b_sps = rng.random((LEN - 10, LEN)) * 10 s_sps = sps.random(LEN, LEN, format="coo", density=DENSITY, random_state=rng) * 10 s_sps.sum_duplicates() # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) s = sparse.asarray(s_sps) a = sparse.asarray(np.array(a_sps, order="F")) b = sparse.asarray(np.array(b_sps, order="C")) @sparse.compiled() def sddmm_finch(s, a, b): return sparse.sum( s[:, :, None] * (a[:, None, :] * sparse.permute_dims(b, (1, 0))[None, :, :]), axis=-1, ) # Compile & Benchmark result_finch = benchmark(sddmm_finch, args=[s, a, b], info="Finch", iters=ITERS) # ======= Numba ======= os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) s = sparse.asarray(s_sps) a = a_sps b = b_sps def sddmm_numba(s, a, b): return s * (a @ b) # Compile & Benchmark result_numba = benchmark(sddmm_numba, args=[s, a, b], info="Numba", iters=ITERS) # ======= SciPy ======= def sddmm_scipy(s, a, b): return s.multiply(a @ b) s = s_sps.asformat("csr") a = a_sps b = b_sps # Compile & Benchmark result_scipy = benchmark(sddmm_scipy, args=[s, a, b], info="SciPy", iters=ITERS) np.testing.assert_allclose(result_numba.todense(), result_scipy.toarray()) np.testing.assert_allclose(result_finch.todense(), result_numba.todense()) np.testing.assert_allclose(result_finch.todense(), result_scipy.toarray()) sparse-0.18.0/benchmarks_original/spmv_add_example.py000066400000000000000000000032541514474157100227750ustar00rootroot00000000000000import importlib import os import sparse from utils import benchmark import numpy as np import scipy.sparse as sps LEN = 100000 DENSITY = 0.000001 ITERS = 3 rng = np.random.default_rng(0) if __name__ == "__main__": print("SpMv_add Example:\n") A_sps = sps.random(LEN - 10, LEN, format="csc", density=DENSITY, random_state=rng) * 10 x_sps = rng.random((LEN, 1)) * 10 y_sps = rng.random((LEN - 10, 1)) * 10 # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) A = sparse.asarray(A_sps) x = sparse.asarray(np.array(x_sps, order="C")) y = sparse.asarray(np.array(y_sps, order="C")) @sparse.compiled() def spmv_finch(A, x, y): return sparse.sum(A[:, None, :] * sparse.permute_dims(x, (1, 0))[None, :, :], axis=-1) + y # Compile & Benchmark result_finch = benchmark(spmv_finch, args=[A, x, y], info="Finch", iters=ITERS) # ======= Numba ======= os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) A = sparse.asarray(A_sps, format="csc") x = x_sps y = y_sps def spmv_numba(A, x, y): return A @ x + y # Compile & Benchmark result_numba = benchmark(spmv_numba, args=[A, x, y], info="Numba", iters=ITERS) # ======= SciPy ======= def spmv_scipy(A, x, y): return A @ x + y A = A_sps x = x_sps y = y_sps # Compile & Benchmark result_scipy = benchmark(spmv_scipy, args=[A, x, y], info="SciPy", iters=ITERS) np.testing.assert_allclose(result_numba, result_scipy) np.testing.assert_allclose(result_finch.todense(), result_numba) np.testing.assert_allclose(result_finch.todense(), result_scipy) sparse-0.18.0/benchmarks_original/utils.py000066400000000000000000000011011514474157100206120ustar00rootroot00000000000000import os import time from collections.abc import Callable, Iterable from typing import Any CI_MODE = bool(int(os.getenv("CI_MODE", default="0"))) def benchmark( func: Callable, args: Iterable[Any], info: str, iters: int, ) -> object: # Compile result = func(*args) if CI_MODE: print("CI mode - skipping benchmark") return result # Benchmark print(info) start = time.time() for _ in range(iters): func(*args) elapsed = time.time() - start print(f"Took {elapsed / iters} s.\n") return result sparse-0.18.0/conftest.py000066400000000000000000000013241514474157100153050ustar00rootroot00000000000000import pathlib import sparse import pytest @pytest.fixture(scope="session", autouse=True) def add_doctest_modules(doctest_namespace): import sparse import numpy as np doctest_namespace["np"] = np doctest_namespace["sparse"] = sparse def pytest_ignore_collect(collection_path: pathlib.Path, config: pytest.Config) -> bool | None: if "numba_backend" in collection_path.parts and sparse._BackendType.Numba != sparse._BACKEND: return True if "mlir_backend" in collection_path.parts and sparse._BackendType.MLIR != sparse._BACKEND: return True if "finch_backend" in collection_path.parts and sparse._BackendType.Finch != sparse._BACKEND: return True return None sparse-0.18.0/docs/000077500000000000000000000000001514474157100140365ustar00rootroot00000000000000sparse-0.18.0/docs/api.md000066400000000000000000000000001514474157100151170ustar00rootroot00000000000000sparse-0.18.0/docs/assets/000077500000000000000000000000001514474157100153405ustar00rootroot00000000000000sparse-0.18.0/docs/assets/images/000077500000000000000000000000001514474157100166055ustar00rootroot00000000000000sparse-0.18.0/docs/assets/images/check-list-icon.png000066400000000000000000000074521514474157100222770ustar00rootroot00000000000000‰PNG  IHDR๊z„฿qขPLTE %:5tRNSฑ %+37น#5ฉIMjR“คฉAjคฉAjR“šิค&5H Rƒิ 5H Rƒิค&5ฉIMjR“คฉAjคฉIMjR“šิค&5H Rƒิ 5H Rƒิค&5ฉIMjคฉAjคฉIMjR“šิŒิ 5H Rƒิ 5HMjR“šิค&5ฉAjคฉAjค&5ฉIMjRƒิ 5H Rƒิ 5HMjR“šิคฉAjzฅv8tช9๒ูN]๊“ว งป™3ศSะj๊p ฏŒim5๕ตพ๑าะd๊ฆฎiาะb๊๊Jื,b"ฺK}ถะ ฮ‰h.u<ัM๚Dด–:7ะฆฒฐฺน{œ/~ฆ๙dะ.q๊Žn–ศ๎โ๖\บษEtคฉ™n–สฮ~ฯี“สQฆ.ง๊0“…ื๊‰U๋Sๆ_๖[„}๕G็่RGCujษnฎี'อcK}ซNiAv๒[ฝ’–Ž+uKบฒ“xก~ๅŽ)u}ฅNฑ์ไR}๓๛ˆR—๊””d'แB}34•บt9๏ปตP6ศ?ชSV—ิิ;ูฉิ•ก>™7ืc‡๗๊ึ–uี?็VR‡W™3,์ง'ปzP\I๋้+ำyๅ\F‘์jช Œค๎่ใW*ฉ:อOdg ๕ฯะF๊rถ๕‹๒้–4iYv7W๊Ÿ+ฉ›[ฯu^ช[ส>ฺ๊Ÿบ‰ิทบIV•๛•ํ{>ิญคIcฉ?}‹H)QงeQ๖4V฿๔ฤD๊{๗YƒยLV5ูWC=“•lค๎้fY5|๘ž๋๕น‘๚ๅVlคnซร์VnไЉ๚d–7’บค{F๒ฟ3๕GR#ฉeค;›ไs.V”ฎ‰™ิuUR’ฯช/ีำ’ุI-}M๖[>๏คŸ้ฯท๊ฦb)uaก;น”/Qบ]๊ฯ6๏žZ{f๋—๎ขŸ“/Vš›Ÿ้ๆ๊ข”3๘x^O?nฬs๓>งฮฯ๕ฃง๓9ติ3˜U…^~ง–[˜ ry•z%šZง–Zฆ๏ป็ eRหพkส{MคŽg๚ŽคH+ ฉ฿_ยณ:ฉLค~ oSสL๊ํKxPvRK5SงQD(CฉๅZ]ๆ't2•:ž:ฮ"“ญิRษt“Œ:lฅv?5E${ฉฃG]p>ิ`jฉฌ๔ญ 7#˜L-}cyF"KฉฏzMซ2šZย}aฮื,ฉ๊}ฒบแบฅ้ิ’ซŒๆหiะ*P‡MAjค&5ฉIMjRƒิ 5H Rƒิ 5HMjR“šิคฉAjคฉAjšิค&5ฉIMjRƒิ 5H Rƒิ 5HMjR“šิคฉAjค~–ห‘๎Rวอ`že‹‡6ปYNถ—๚duอ๛f ง. ๕…i‰‚VS็'๚ส’]Qฆކ๚ฦ”ฝ=lฆพั5]ZLิu)oˆ7˜บถา ZD4—๚lษ9ปใHOtฃ9ฅ,%ขฑิW๊ัV๊FฆD4•บœชKŸˆ–RŸฬีฉ!๛สล๙Ÿ)>ิัH‘์ฃะ์OW๚Sญ&ท๘(S๗ิญ){(ฎ๔งKบ…ใKVทปœ์,ผLีหs“ฉรH\๊™:M๓ฒณ๘N}qK7๏ชษจS” Љ:%EูYฎี?MฉบI ษ๕ฟKศPsc"uo‘ศฅบก์eฆน3‘๚^7JNEไwฆN“X๖ณP Mคtณ๛œ”uZžษžๆ๊Ÿ{ฉoิกY˜ฉำช*๛ซz&R7ี!}ฯ!i_si"๕ivเ#าฆ๚งf"ต tgก์๏,S฿,#ฉ‹+ัฌ Ÿ๑ พนฉฅฃปIJ๒)5๕ฬ๊ฬJ๊hฌปศ~ษ' ิ/Wb%ต”V‡==YจOฦ‘ิrฉืฯษงUR๕วฬิฝe#จq,_ –๘Sบ(–RK)ีYœส—(=ชNฤVji๋‡ค๙"Q'ัŸoั ล@๊}–๐s๙:๙๖8ำŸl๕pY|fซ˜๊๛บ๒ต๒ต‹V๛gjWbซObถ๔]wกภ@๊pจ๏xไอฑžงv/แผKิ@๊=–๐URfR็๔ o4žZฮuบฅ“ฅิาT—aD'KฉK๘œwK-ง‰n’ฒiƒฉิ๎'lณ‘Lฅv2YL}บิท์f2๕๚sZcva1šZZฏ[Oู ฯlji$๚ฯ_ณ ง–ำTxl๐ฺDjท|ฃ;z—eโฐฉ1H Rƒิค&5ฉIMjคฉAjคฉIMjR“šิ 5H Rƒิ 5H R“šิค&5ฉIMjคฉAjคฉIMjR“šิ 5H RƒิฯN+•"ปู้O]น]จช&ƒ_ผƒิt๊“>ฑญ‡แิๅ…พฒฑ‡ูิฅฅพ’"กอิ…™พ‘œัะb๊hจk4ด˜๚Fืelwl0uS•ธŽ"umฅ› ‰h-๕ูR7ZัX๊xข›ฅDด•: ิaID[ฉฏิeLDSฉฯ3uน!ขฅิๅTjD4”๚dฎNฎdJิ)ใCm)uOบ$๔+uฎXญ•"ูฌญn๗vไU๊Joฉชบzhl Wฯิišง Gฉ }}๖X•ทJ‰:%E๙„จXฅ<ฉJs}aี”ื๒Suส๊ฒท๒๕$ำ๏ฑ่7"Rฏ+.฿ไป—ยukหพj#V‹vD๊7ขฑพ‘–ไ…kuป•=ล=veRฟึา5“Hž]จ(’œN๔V RฟฮทVR]ฉำD๖s2ำƒศค~กฆฌส๒วูBา๒งdU!๕?Uu.แ๑๘;>2Wz0ณ˜ิฯ๚[ฮvๆ๊ึ‘=Wz8R?ปืฒŠˆtิmสžzz@Ižิบูc$L&ฑ์)Ÿ๊!5I๎ืๆn)Uงๅ™์๋\๊ิ5ิ![จำช*{ปีƒJCR?‰ำฏŠ#=ฌ"ฉ+๘๛nไfzX5RUX๊ŽB๙„ฅVิฯบ›YA>cฮง๚ฉบ‹ค$"ฏ๖3uaก|๑๛0zzPซˆิ{.แ—๒IzPCพWฟาื๊็ไ“ +=คฉ๗[ยG‘|Z_(-๚ต_๚!‹S๙ผRฆ‡ำๅสึ^KiEพยฬ"O๊ท๒s}฿น|‰๘Q$ซqสบ๚รณ…F“{ห๖บโtสW)ฮ๔ฒ&wŒ๎ต„?ๆๅ๋๎๕-j๎Pฯt‹eQพTcช฿*ํๆyบcฏ%|U“/ึ{‹o๋ะ*๐ฬึ๑์ะ'N*๕__ฏVŒx๓ตLn–RปOn #2YJํ^ย็*YK-ีLืฅlลb*ต๛ฆยŒXLฆŽงผุxj๗;nผkะhjฉฝn}วมทูิR๋ณU‡ะN-แลS์ไ–ฝvŒคv;บlVYปู้คฉAjR“šิค&5H Rƒิ 5H Rƒิค&5ฉIMjคฉAjคฉIMjR“šิค&5H Rƒิ 5H Rƒิค&5ฉIMjคฉAjคฉIMjR“šิ 5H Rƒิ 5H R“šิค&5ฉIMjคฉAjคฉIMjR“šิ 5H Rƒิ 5H R“šิค&5ฉAjคฉAj|]๊n1b|>้ƒ ฏ[ค1๓๓Gœ๊เFท้2@tu››เRทษZLะญLทน ฮuปQ๋W?ฏึHท;สŠฃPโS8ซ81c8c ไš1ƒk คฮŽA]‰ๆ`_I าc๖๕D‘*ƒฐฏ๚_j™0 ๋&๒'๕9ฃฐ๎)u8eถMรงิา`ถ5ไoj2 ห†๒/u1evฅลฉฅล@์jษหิน€‰Xไ^ฅ–ฮbฝสะ$ษzฏลZ-ƒคซซช{ไซEMk$ฌEึHุ0ŠึHุ$ŠผS €@ €@ €@ €ะ.#aณ(๊Z#acgs๗E k$ฌซzๆHืธซฮ\ŠOืmฌwodตcณๆิ&™jEนบท`ž†ฑฅ๚Cงืส๏๛ุKปงึyP}Qjฆ]kบ(uEฟ๐ฺตบ@ €@ €@ €@ €@ €@ €@ €@€@ €@ €@ €@€่เ่dูq%ครฺษฒฺ!ปัy{4[|ฒw/สฉ*i†Pใ“๕8ุํ+>'€F๛Šรใฐฦh_แ!€@ €@ €@ €@ €@ €@ €@ €@ €@ €@w `…ัพโ8|`ดฏุ๐๏Jๆ' ใQโPวั* Šฌ‚ฃU@-ŠsดชRtKฎย9’€!Žืc—ฐ|ม+‹DLqภ fIBสธV[,A“ฤผเ˜ŠMขฦ8h๒A„˜ฃS ฏgนB๐mŠง<ลj0‚yb+ฟ-ฐศ3oeื(!ฃZO฿œอฎžพšI้ม>แd6 @ €@ €@@-ฯปเแ๐ึ3๛๕นfj๔—fิฌ—แtyF€๋ š:]๓ิ›๎@ฑุ,ยิ–`ผ๛iฯ๗ๅNAี๑ ‡O–'พงีซNQตๆ‡้b0๓ภโ™„ิฆ>(NK‹„Ug(FปลR_ €เู:ล๕r@y`๙D ๏ศs—7Jจ}D๙ `ื ฤฬ9ศkŽA2 ว›$i@ธผ4O{ทNIT^#€|เ6Hชาโ๑ะ* ซีnYr8ึI2๓ะญมt} ๘_ŸลคWฯQnH~ภำpแ๑5‡YฯศGงฅ@_<@ๆšC๘๓Žฆ~‹RalŠภำิใ[ ลบ”’๒>—ˆ฿w๊J0คิิOล @ท=Žj฿V8€JQ;(j-‹˜ชฐ)Qtfฝัจ—5Šฮ.hƒ ‹ู7ิ เ\ฃH4k่l/9j้อผˆhSๆu• เ•"ะฺณs™๗Jy(^๚œc๚ 0ฃŒแพ๊<ฉาmญ€น‹๑( รRฒฯ+!qั˜qL~GตฺtK๏ศก.ฃ o‹ภc;ืี `F7T>๙ฆ3`E ภ๒9พญฎRง2…๋œ8‚`คQธ๗ ๏8‰‰J๔)ˆ#ZšสhRaŒ8ฟกN-พjูีิ™0ืI€มษ๔(Kใš“ตไ฿mZ฿; y‰“yก ฬYž1ลRšส1)ฎห5#:'ำUเษ`!งละุ๓-๎3ลฃy,ื–hœLGมืสOถ}ๆลRgษกฦ9™ถz›%ไoœ์๘/ค๖ยฒYžƒ€3หด!Qึ…ฃ ^(†ห&ขก$ฐสRy$จ|ไจผบŒ5nฆˆTีฟะbนฬื k„ญYถE†ป-ว”บหU#!ํดฏŒบ,>รˆCฉ๋ณ\๕4฿MrิIษ|ฯeภHgm,ื‰hฅ}NดXพF†' f๎NๅTงh+๑Ÿ'฿k†O:”ถKh$@๗XLP‰ฟ ฬ~[˜ถใฤZ =$_เs๊ทว–ožๅEจ5ฅฬ`ฉ)_†~'1;–๏้EV‹Rv`™ฦ$b–r`T 8eŠฤ๐Y‚ ฅฬนใอ EฺO [œ†v–ำซตb[‚รfสo(u…น๗›ฺ๙x๕ึKดL๛กฝ3 ๙๘O{wข,ฒธX5A\——EQ”ญษ๎ํฬฤŒ‚]Eœๆ{๛†ฎญ‘‚ว๚ว@ฬGqจ€3 …XๅLด[T’5จ35!ั@mฮb4ˆ™ ล ™h‰‚‚q@๏œ‰ศP[ข(๒๎๙=อ1“$"ํ=Jร]3ฉj‚ŠGœyD™มwภฮT 7C!2›พั'š A‘•œ?Lำฝ™ข+(jM™"—ฏิb Vอมฏ€-RI4ถ h๚0ƒ Cมf:IVR‰P€ฮรŒRp$ขRฅศ€ฮš๋+๐ฌ>สฅPƒขิŒ4.ๆ#ฌมดฑ~<ฬ8๕7ž!ีc‚RชWณTYl$[ไN)๐“ หApLš)0“6้า"$ี‡๋ i๔(ทวTšมๅ{ฦHkอbซภๅ9ใžebคคแ†ณแ:=ฎจ9”ป‹rง@aาๆฬ>RsษWC๘Xs๛Œ4ๅดAr6๙}\๏ภ้“yPผC™้"=ฎS‚ป*‰ด2ฺ๕5ๅค>ุฤ฿ขsเๅ๒&ฌ<ย ‡\ฺำhา^6–“ต Œ]lD๑‘…Mzœท5k๋วyธ”Q๖ศn,#ณxPKธF;"“6a<๘Q๎ึpกœ>Yt๔นxt๑เ“†œ zJ4…จ#›.YVj๒(w์n ,่ะA>[ช- Pก 3ฮ|ี˜ๆีุสQŸh B%,,*ีก,=ยโา&\แ"'—&ืพS {ฮ๋Bg%RF†œ๖4'TฤกœงŸฐจคY`=‡Iฎ} HžU๎0งจ‘|๑bd‘…พ๓Beชxคฺy-ขด“๑dท;nฏ๛Nง}มฏˆฺ฿ณํ–ี4ฒ[ @UNผwlฐ๏ฆคS…!ถ1TๅIDmแ0ๅ.฿•โau#™c ช2bพีB ชบ โํสีSช์Z๕%กษ๖ฤugc ”๗o#ม<JSLo›ผ&sKฦ’nOญ~f ฃ@ic‚ย!๓ฃvีU\N "๊หqTŽ“™ฬ€ฯ๙ ภ?0nฅั๏:้<๎ %xปณ•xŽฑด3”ค่ƒฮีv Ÿv๙i>!z%w’๏•ูgi^4เอO]แ}ƒ4+ผเžŠฃƒ8ส‹HL`งญ๐^แ+แGฺไ.}iƒ8ƒ_n๙(ภฺ‚šY_ฦq#O๚R X)“…H&Q?Bา|ฏส๛VF ฯ Š`Pฌ‚P๏x]ซสใีpั†> Mu(ฆอ>+ง3Fž=–ฐjwกpัฬ„"๚์;ภšq@้c)ฎฤC็Œ4’ๅณเc@ป‚๊๗ค ๗ณXR8:Oฃๅ)eซžะXเŒใ /๊ภิiŠๅy= ะ†ศ`7ึลu‰Ds๐fษ๎กŽxŸ`jPึฤ=!›xiรUญ„ตRQล7๓žfG ๘Y „ฺ_‘๖ฺ6`œฝ2๚<ลbย!”aฝy s๖#[…ปไพ๗๙$Nพg๘Œƒ๓ี๑ ‹๖ก˜ๆไ+๕—c[Rด๑+t˜Ypูำo•๖เ>ฺ[ˆๅ๘C n๔|๕V/‹Sž บ>6ษŸ—ห(๐•+0๗พ26„VS๓)พRปA๙ _ผย๒เdจา ง7 ŠภพŽ๐™‘๕aวˆUPยR”ภŸ๙I9% (u8%]‚งแqj ๛E9e4R<ŒลฃF์๐i<’„์ฉาKM@S’sDฤšO|คiภ" งC3*ํณ้ˆwhฆgv jซOฒรL@L๓ๆe"@ˆ D€"@ˆ D€"@ฐp0ะศ๕ๆ ่ขV&›&ภ+P/ษ† Q3O&`530}ิL%6Kภ‘๋ฏ@5SnZDอd&>™}๘ €ห;|‹ฅ"@ˆ Dภ๛๖\ะH€xๅบ๊บวu˜ธ. Š€ฅ๋0q]ภฤu˜ธ. t]Fฎ ป.`๊บŒ]0v]ภฤu5๑šฤํ`ยC@€k“ต0โ! วตฉ xb! @ dญLทg•ุS+ี๖ฌšด€}B๑ึD@ูN@ฦAภjเฑ€>j i'`ฬAค:V†ต๐ศB€wƒk๒3," •€' D€"@ˆ D€"@ˆ D€"@ˆ Dภv1B/€–*๔๗ ฉ7X@ˆฟS4E/ ฐOีZd` ภงูชƒฟจจจR“7H/ งปqฒd! ฅฝs”^ภ.ล^%|&c! ฤg"ขI/ภ'Xก›ช"@,@eมสพ๓’ƒ๕฿3Š็้จฒฒ3เกๅ๛็Sตœž…Hํ๎ู์โ c6:๘Bmลภ!พs .จฯภ8'jOฝ€๙=b็{`‹'c$ภวY๊ฟแ=>ฃF*`$๚ซl๘๊ NFฌ๘+l๛๕ ฝ@- ๙,๕ช้O๔๏,Oษx9ฮา$:˜3,ข6ๆOา €nณ€ะ่ญC9pฺ( GฬUYไ NPQผyk~ผ้๓๙ŒC%๐!†ท„ฤ'฿U4rํPํ ๆูก ุ*s%โŸฝ5i์ว้จt7}ทJMม 9sกแSฎ|ไ'`๒(qfุแ% x๛]{ฆฯทIy ภ7|4๛๖-,>šๆ‘‡€ฮ‚&เh›จ/-jผย ช ˆa†g dจจh;pdจ๖w ๋€ฝEf?0a$`B)CDEL5๐pOS %ว฿ิA`ษGภˆ"p ดจb‘"0a# ! €ˆY.hƒ u<7UไD €…?†็h…h๑T@ใซ&€$~00! ŒU @‰'๎Jชศ€œžj์ภ(Q‘ƒ ๐W@–˜ข๊˜2D+dŽภ=ธ‚p l9ฝ[\BuMฺผ‘่ ถŸx๔GO฿eอSสธAืuอƒ๓N€+คฎ h๐/…ธ‚_ะNำำs]€—ำNOH €Jธ.Rื๘ฤkƒ้้`>10ท่เ] ม1Bฆ๖/ƒ๋s‚R๘8ษ๑™๊ Œใ๓pใoฆฑๅ‰,ฮRฌbปฅpิ|ถพPกหJ@ฺpๆฉ)rF>S,ึ ๙6๖‰fตJสE@฿ฅŽ์M T@H }๋าลลล1,งฯB€—๋]ต์)๐™ogซฯ‘ื<nLฺ|}TFะL€P๋ย๕รbถ–&ซF4ใ_œaํ—Eูz8นโ-•ผ„U}vR›˜O?พ๔uธ\€3QvืG๋–ำiMKMณgฒ๋%_๕๐๖2๏W มธ้จ-szธWkf“มเข6\B7L ิxซJะE qฟWดุ กิ•‰ะฤd l๊‹ฺg“ๆเ.๘Nะ์บา@ใ‘:๛ผหค!;˜kิSG8)4ผน8ะธ™ห+ฺ-ิ>ซdš@[์ุ\เว(ต์(ช5 าk ˆดศ้คซู–๖๘:ฯต8jŸKฺ—ี‡ศฤ ฐ{—ใ๊ฤฺ้Ul%ฑ–t2ึ๗|ชศ;›7a ›ยUีๆJต•ธา๎ถ\Q•Š+•ฒอฉjน๒ฝฟวP:yxืRภzlฯŒํ™ื ฐ $บใลั!^hM่MLUiยYhปเ}DŠxytˆิš๓•ภ%RV“.zเ‚ {ืcZ!!\q&Cี= Z)ญเ•!e์•(ดps๕ัTๆ/ E" Zx“Cฉƒาก๓sRŠ!๔ˆKX•3๛@ปYฅค`๛ง>ถจฮ]ฦชๅ=”ง‚ฏVLP้ฉsฒU#&5aƒ๔ฉXฐ{0V4ทฉ0?`~00`dƒ๔Y vศ—j8HOt๛มณฦเqฑ˜=฿“/จฌ๓RŽธ่ด่jCฯH…Jฮหเ u1จ X๘€Nู]%"ฮภhธแo c?ธH๕,ำมSA+’ใ<เ2U เ+€H„พุqไทC“€k5(Žp…(๔ภัccณh=หt ‘วฤดšeI"ๅ G๔ดšd็๏‰ศโ6=๓ภศ„ิ=7G€@๗lPจ=ะซค €†๎Y#ฐ8 €ส03%Fอญำ๑ฝR€ิS‹ำ˜œง&€Wƒจj*ฅqธgภไ|kิะ@S52; @ว‰สI{ัkฌภ›€z ๏ศˆฐ‡Cฬ๘ซผB๒Pw ๅใU^F๏…ฉ‘ซจ…ภTฮูY_๘ฌฎฃภp#ทAro„ง‰R#Gฒƒ™“ฒzxข๒,Rplฮ‰•j”“ฉฃภHeีh„’หlภ@ๅ[vh~@'ะQทƒม โk bf๎้๔5พp,วัžอฒP8กJ<^s)j;sˆˆlmFภค:่ธB๔…0ชค”สC|หั^ ฆ+นd$pDโJ.+t ฤˆKแญเD“ืVrKDzj=Q}ล‰™็Y%ฉXฎD่a'hIVžๆ`ง๎V„oo?€วU็+ƒฐต—[‡๋้ตฎญ‹Sซ`4˜ปเPmไศ๒V hฏฐ7คƒล‹ุ˜ ฐl<ญิ9๓Fะ-`ะ“มฦดVํ๎;๙ ผC๕mฯ๊€K7ถเนPพ๒>ˆฉbŽ+Rเ h๛~ร>–oฮแฝ๛๗KxN)ํ๎ow_์พใ่ŸSฬA/ชgš๕มzพูf>}&๔ 8 K-x<ฝฌ๗๘ฯห้้}s5B0ฺ|๗๘ทผซij[‡ขJึํ+/[Cก†ยKถn ๕6L ูาะŽท$๚๛) b๋Jบ=UšA+Y>บ๗œs- ):x[ธม_ุ#/ q35ƒ’]b|BoJ ŽG7ฎeป`*Sg|Tnศ(uถ#|ั p๘จ< ๘ุธนw1‘@๐V hWŒšpม‰ฆ"†๕‰j.ะฆุtอเ่kY"'เ a๛0๐pC'เ —OE•1ฦ แ@Dภ๑œ๔T๕้โ`†Yใ9เsฟ|๙eห–<—ถwN๊—มฤ์าŽ5Q€:“าถ™‰—m๐6(ศ œ`๘[ๆy.qŠt„t›ฝQ๛ร•Pพึ‘-)๘ ITฏๅษ์Žด‘”ำข€ฐ NˆIงฺ็Œฺ*๎O~๚o]oIqซไoเ€๊„ šฝEฌ*สๆqก’์”ฝ@ค๋t'๊ฆ”Kฦํ˜ทิมูๅออ๕ล)ปimกNƒZ฿ต4ษJv"tาU฿Wขฉฯl–ฟYา*น๕Ž:้5ฟใญjซ? ฬ^๛นลฺ7c’ฤ#ํฆเœC`ะ๛ี?/žรฉขZnN ่ฏwzAEย ž๊vฺธฯ[j\oฯ?฿\ž%LฅฐˆmาŸZ%^43ๆZi;\๕อjiนค>•]4บzs+ใCฬgI25๙ๆฃt‹Xt‡ี'ฒ3i0UŒt๘&ฆ.๛ฉxศ๐3OM|‚ีŸŽณ~ุ?ดŠ“ศ.Jก>4๙ {Xhๅ_iไ ฮพฎCณ.ฬะ'kิ๘g๓Y0ฑูฅ•}yณ2\๋อ๚~ึŒE[จฺta่ƒฅ –พ|๚;่ษใ†HŽZ>ฃ) ‰Œืใยru^w=Zf„5ฑ P7ดRtฤ๙วว็ki}l/ํฦ{i> ‰‚ฎfข๊+ูœๆ๚โใัฃ๗็_%G?†ฦ#Ÿ1พŽึ}ฃรŽ™E Eอ›[l๛\+๊จ4งฒภ25[XใG<ทา(จUoฏฯvc6z}||#ฌ‚žโกc Œœ@ ึจE6ถœ\พ ฝ๔…†M7ด˜–ก3@žd๚‚}|ห$ฬภœUฉ‚๏aบ%ฬŽQ j1u็€(xWยฺk4iอ™Œยถ-ม |(…,.f7”—Žœ@D‚ฦ'ฏƒ42—˜o๏Wˆ้up %ึAปงเ}๎€m#0F๋VF ไHบลุ@เ'ฆศ‰‰\Pvฒ7ฃฐง’91Cิ[ูKf`* œpU€ฮ์่+฿ชว#‘ฃ"ว•ถ.Zไํ=ผ~Œ*ฅฏสžอึh/Žš*ฆฏ+ู๋ภ ๘ŒqUะ–๕”อa!“้ะฺ 'mt{ ำ€‘š-j่€[กฆฮ Enธว(8ผ*ฝม>€ฏ†J€ฉZ๗ีPๅ €5|5T+นฉ‡ 5ลUi#ทD5โH๗ €[t5ิˆ้Dhb# —Fฏ€ ผ๐๒ฝ „{aoนWะสภ+ oi๐Šฝ ๕ะVะk๗ :+๖Zศะ๎%W„lษ6OIENDฎB`‚sparse-0.18.0/docs/assets/images/install-software-download-icon.png000066400000000000000000000104361514474157100253500ustar00rootroot00000000000000‰PNG  IHDRภ dK฿จPLTE,฿H†7tRNS %*.37;@DHLQV\bflotx}†‹—œกงญณบฟฤศอาืแใ็๋๏๓๘๛ฯu๎IDATxฺ์้r8…แฃ}ณ"๏vlล–ckณdวZฯ_ืT%๓g–๊QOษ€๑<7ะ๐ I‘œ–๎ภป$bo๔ฎฅฟe *@T€จQขDˆ  *@T€จQขDˆ  *@T€จQขDˆ  *@T€จQขDˆ  *@T€จQขDˆ  *@T€จQขDˆ  *@T€จQขDˆ  *@T€จQขDˆ  *@T€จQขDˆ  *@T€จQขDจ T€ P*@จ T€ P*@จ T€ P*@จ T€ P*@จ T€ P*@จ T€ P*@จ T€ P*@จ T€ P*@จ T€ P*@จ T€ P*@จ T€ P*@จ T€ P*@จ ๔ทฌDˆ ็๚,้ำฃ}คฃตส๊ลีฆ,‘i ล=ฏฒx‡+f62•6giฬ๋0x |ฝz`fOฐh,X‹:,Fฬไ๊wWC˜4?X M˜<3“g8๒ษฬaำ๚d |ถ`๓ฤLๆpฃม์พรจ๓ล“๗ี†ัfฒซย‰ fwซ๎š'n…ีู๔แฤูภ์lร“ถ9ƒู#ณy€fw ป–'l๘๋l 'Vฬ๎ œ๏xฒv็pเžู|ม…sธ€ —{žจ%\ธcFm8pลpโzข\ร‰We<1‡>ธๅIบƒ7ฬhฆฬกGพ๓=ภ‘kfด€ๆะ+CžœpๅŠํ๋0๋06œyๆ‰y†3—!oฬn˜G๎ผ๐คผภ f๕ณ๓จรส+Oศ[๎œ3ซ ฬๆฬฃ‡ชcžŒI}cVkXUwฬ‡47v0fึxoc;ธU›k&์๏œ1ณ[1 ซ/x ธีcf?a๔“yฌเZsฉ™ฐC]fถ„ั‚y|ยนึg™gย์i๖ ˜ิ๖๙j‡{ํ_LฺWฮตรฝฎฦ\๐ ณ*๑L˜ /hแCoS™0๛๐๎&ฏฬe†Cฅž~ƒ๕< V`๑ม\ฆ๐cฐKv&ฬ‹Zฐ7๖ ๆ3†'I&ฐฟ‚ี`c)็ฬ็ ‡ส;7ถฟ/{f๗jžK7วส;7vovกาŒ™ฯ นgbเฯ6ิะฦ๓มฃวrฮ„ูG๗ฎPX‹9=มง'&dŸVฦำ.™ำ^ฝ0?แีs˜[)็๔ฟ^ห4fคƒ}๙”9}‡_•q gย์O๊๚(jอœ๎เYuยฬj๐lๆf‡yภทฺŒั{ฏรทE˜uืฬ๋ี฿นeฝ3ฏpซvฎเ_c™L˜œA–rอ˜ืŒาไฏ6˜97Wถฬk›๔็ฦV„0 ๒xชห๚0InlCๆฒ๖6ฎ‡0z๋ค?e7f.๛Zจgฐคษนผน˜a=0O๊™'8๋{ๆถA`?LT๘น%r0ฟB1 ฏ•ุำ฿ืƒœa?OF`\E`ร/ํ˜฿‚ซผ๑่ฆU„๖`x“๙-^u’โLX๘ฯ.O‘S“ฬqตY[†!l_D~มf8†๚<ต™0ป;๏m‡,`‚ฃh,๛L”ญuฌ0ฦq4?าš ณปanฏศgลp$ญฯคfย์ฎฝPk^,—ๆVฅ›ŽไŠ๙5 e๕‚ฃ้ฎš ณปd~—6๘แxฮ6้ฬ„ู]xy5ณพ ๏6™ญํพŸึT6,bˆc:฿ลฝu`ภ-&์‹ศปพฟœ“ุ-Žฉฯ๚†Ÿ›†Uสัฯ%๙G=๓šˆBล๏าถ๏,จH4qฯ„ูํ้sŒ๏5‹ๆGิ[ฺํXฤฺฐTภ๙€๔็ฦึ]Dc๋๓:`QUฤฃ๑ึvkŸฯํฯYะ1้ฎโ:ะnๅ๓y๖m•&ฺญํ~ฑ%ฒณ 5โา฿&๘™(๛ฝš}๙ ๚BdปHทด๛๐๘๊ฆลข>›ห=ธCd–G[ฎXิ ขช๔ฑYฐ˜ฉื=ˆฯm[†bยพˆ|สขๆˆะwšŸ9ฝฝฐจb4คัODhๆ๏Žฆรย&ˆาณy๋ภMYะซปฅ‡ฦˆำ‹q๋ภMฎXุโTy5}&*Jcz{;w{มL|nl^GœHOีญ1๚ด็ฦ– D๊ี{,๎ัชอผฮ„ฅ๔-ี™ว'(OˆW}a˜ ;ฉปmี฿}๓k, Ÿ‰:ฅxfxlxzžุบ‹ˆ|-|ฏํใg%Vฅ›3ฤ์ูื๖> ๎ทฮส0™'๖ห฿{”Dฎท1lx:o;Z†Ÿ™†ลษIอํฏนG_ว้ƒ—ˆ`g˜ ‹ษƒงท๕= ฮฟ‹]๊ทด๖ห๕ปaฉ€aejBscˆ฿=‹ี Wรฃ†dๆฦž€;OTวด่HŸฯ(แŽํ๎~ัขƒ4<fhbqC๚ๅiาคD<fย"qMƒŸKš4‘ŠรLXฎœญะคŽdผfยขpI/Oo'4ฉ"•1y่=†ฯ|uM‹=Rfย"0 ลฏM“-RR›™gยbbยพˆš&k$ฅ~ฐu`B๚49๗ฒธๆ ii,fยาั๓ฒ?ยŒ&Ÿ08๖'็ึ=$ฅK“)NeK็ทฉฬm๛HK‡&›Š‡ฌธภกDๆฦvƒไโฅMืววๆHOw}0–†m๎|lอ0E‚ฮ6ไษi๚๘(ย;m&Hั`ห[คงA›ชํh3F’.๎‘ :š8pFฃWH05]โภ=~๊ธ„Sกัผา่Eว% =mf8ฐคัณK@;ฺlซึฅ‡žtXฺt;ู= ีP‡% 5๎๏ู ระŠFo๘oดบืa ฟล„รEไŸดบำa ่“V-E“f7:,}ะ๊qAณk–€–t๋}HณK–€ดzว_Lhvฎร~‹ w‹ศW4๛ฆระ๑kำ๎L‡% ฉณ“ช€์่ฐคฅ็บ€฿๚; ่ฬฮ– ตuX;;bUจ่PยsZ€:t๊* „4[@* ผ็g?T@ย็€ŽNe, ๑Ÿ;ม๊™ (๏9   [Uๅฝจ๊Fฐดิ*  ๙Ÿซ๔Z ”ดU@ญซs@9 ๘๗U SQๅ>ด ซ@r~ป<4T@ษฏM่*œ?:จG๗u ฎJชึ๘Pบ ”๔€ฆฎษ๚ํฒ€šฮe=4TQU%ฟ ิกส}จฉ€vX@บLฯ h๊*P๖s@U”ป€JCฟส]ูฝ6%r„Q>s/€!* บ"—๙$V™T,SตัŠป๊ HชืUWdF้่>ฯg๒๖ฉทoรŒ˜01ky’(‹™-P๑I[€ “-U_ภ˜0X}ู์์L{ ฑ 9หะเฎXc &@s€&ห ฑ4ฯ4gs%จ9‡=€=€ ะšล0L€ึlฎ™๖๖า˜รhฮฐ™อYL@Zใ,ภฐzณ€/ษu–g4ท tY•MพCo 9“ `ˆ=€4f0์L@œH[pภs1ตุธ`˜าภฝภ@์ฅ๋ฯgง'ฟ~~9@ถธ'ŽPฏšใ‡da฿—ซสaˆLซ`ใ%wซ'5พ@tŽ๓&^฿๎๛าt2‡"ี&๑พ, ไฯDฟ!TำWL/‡7ุ;าP๔gโBฅT›<ผญไหั๒L€|ํ$ฆู๐ฅ86˜้:)LW๔eh๋L€lี๙9ฉ9ไ™`ฮ.ฤ้ˆwo๒cกา}๙ŒN๎™Oวๆ๚œ Pั็+๕็€ Pฯ๘  bิsyเฮ๏!ุˆ{ูFƒ 6dlx2/‚ ˜ษฎFใŸ1ฤ1’]!”แ{€bพ"œ๑๋€1# ำอœ%เฮ›€LฃยนƒPฃ! ื! !ิ70r‡ก๎˜อ aƒ‡‚2ูษbP‹m BฒHfฦoJ Bฐศๆ†{กพฑศๆ] ”Dบ0ฒฅJ< ‘n“ ห‹!ŒU0Š12# กฎม• t„\†P_ูไKฅ\Bo˜€ไ˜›Pื#ภ๎8(Ry9U6DOL@J1“]ƒXทณL€U* u8[‚HT ิใะว๙Jูสภ:๐E๓๊h60•น็ ็๘‰๔s˜ยฺ๕…kใมGDพไิ}๑๊x็xD`ฯมd^ำ— ‚‡# ญ &ฐ~้๙2d๑ภ๊q8"ฑท„W˜๋M_Žพซs0"RหXx.Vh๚’4๑จฤกˆฬ๑Nฮ5๐?หฌ๕}iถ.ๆC๗ฐถ[ญ7๛พTY<2ฺ๔lฐอz่ง†'VYไ๐„qฤ‚h= ๐S3ชโทฯ’hfฯีXฝ4๐Bš5ั …CE'm /ญณ*:ูฤOŒหขc?หฐ.๚(เ>.จ›ฆ…ื,๑L@<ม๛!ิ0รKb-t]L’eutPฤdU–G}๛&sZ,๊: ผe™๛ีe๑ถKคถ รฅ€ฎ๊&ฆฑ๖Y&u5Lใ‘ฒฺ.‚HpC จฮ‚qy6จค๎2‚J2 ๊,#8—r:ยˆ๓ฑAลด’วๆใใJ๙GX&Fคช…wX็{ั/โ}O,ž šหช๐ชp๑m๘{‚ืZรว˜EฎXฏlแรโ[œ UีลL$ซฬภ"ชy˜™ไ_;บ`๚ปf*^ๆmั้T\ฬœ™ฎฒ,„~-kA ;[ํฐภ๓ญป—s ’แm๎ณฮ๓ฉS+ญ˜!‘ฉ79'ฬ~๛ Zฮธ$ณฉฅๅŠิฒ—r ฟๆะๅ ‰.็‚IENDฎB`‚sparse-0.18.0/docs/assets/images/logo.png000066400000000000000000006724451514474157100202750ustar00rootroot00000000000000‰PNG  IHDRคค]#าะ pHYs  า~tEXtSoftwareCelsys Studio Toolมงแ| IDATxฺ์y|wa๗๑ฯof๖”dห๗}฿ฑใ8N์ุ‰ฯฤนI8 ”ถด ”ปจZ่Cฎ–(NG ”คO -<Bศ}XพวN๑}HŽ๏SฒคฝๆzXIถ›\๖Xใ|฿Jซ™อj~๛yอึ„aˆˆˆˆˆˆˆˆˆHTŒ‚”ˆˆˆˆˆˆˆˆDIAJDDDDDDDD"ฅ %""""""""‘R‘H)H‰ˆˆˆˆˆˆˆHคคDDDDDDDD$R R""""""""))‰”‚”ˆˆˆˆˆˆˆˆDJAJDDDDDDDD"ฅ %""""""""‘R‘H)H‰ˆˆˆˆˆˆˆHคคDDDDDDDD$R R""""""""))‰”‚”ˆˆˆHDŽ๗๊ฦะx -ฌ…ี5uzFDDDไํJAJDDD$"ว๏บบ<๑ h0ฦซญฎYrฏžy;R‰HGjง0%"""oS R""""yUjะ`Œ[S]ณ๔ทz–DDDไํ@AJDDD$"g RํSชญฎYVงgKDDD.d R""""yอ ีNaJDDD.p R""""yAช]ภbc‚š๊šบตz๖DDDไBข %"""‘7คฺ}ฦ˜ฺ๊šบz=‹"""r!P‰ศ›RํฆDDDไก %"""‘ทคฺ•รTMuM]ฃžU‰#)‘ˆœต ะoก…ตPaJDDDโFAJDDD$"g5HตS˜‘R‰ศ9 RํšŒ๑jซk–,ิ3-"""]‚”ˆˆˆHDฮijะะฆ๎ี3."""]•‚”ˆˆˆHD" RํฆDDDค S‰HคAช]@ƒ1ฅชk–ีiDDDคซP‰ศy RํSชU˜‘ฎ@AJDDD$"็5HตS˜‘.@AJDDD$"]"Hต XlLp[uM]ฝFFDDDขฆ %"""‘.คฺ}ฦ˜Z…)‰’‚”ˆˆˆHDบdjง0%"""R‰H—Rํฎถ0ีจ‘sEAJDDD$"ฑRMก๑ZX ฆDDDไ\P‰Hl‚T;…)9GคDDDD"ป ี. ษฏฆบfษฝE9คDDDD" `ูT\๓น†ไ๘ตX๖ฝMy+คDDDD"็ eœูŸ#9fXvƒปkEmbฤ•๗jTEDDไMอ-คDDDDข๋ •ฬ’]๐y’ฃgƒฑpท/%ท่{/†ญ๛jชk–ีitEDDไ อ-คDDDDข๋ •ฎขโฺฟ#1b&‹า–งษ/๙A๎,6ฆTซ0%"""ฏ{nก %"""8)+ƒ์ตObุๅๅ ต๑Qrห0ส—๏)L‰ˆˆศ๋ค %"""‘Xฉส>dฏ;Cฆ‚1ื?H~ลO '^}ใภภSS]SWฏQ‘ำQ‰HฌƒTทT\๛yœA—€โฺ!ฬ}„ล–3Qเ฿gŒฉU˜‘WR‰Hœƒ”c0ู‡3`"Rx—VOXสฝ๖+L‰ˆˆศ+(H‰ˆˆˆD$ึAชืฒ >‡ำo<„…็๎งฐๆ—„nu฿GzwZX ซk๊u4ˆˆˆผฝ)H‰ˆˆˆD$ึAช๏*ฎ๙vŸั๘ไŸ๙ลตC่฿ุ4…ฦ[จ0%""๒๖ฆ %"""‘8)gภEdฏ์^# ๙?กด๗o พ๛ึ๎8 มฏถบfษฝ:BDDD>คDDDD"็ •6ฬOcW"t๓ไ฿Ciห“เ{g็ฆDDDVคDDDD"๋ 5๒*ฒs>…ีญ?aฑ…\]”ถ-ภ;ปค0%""๒ถ  %"""‘8ฉไุ๙df} ซฒ/aก‰ึงฟ‹ปsนyภ€ลฦ”jซk–ี้ศน๐(H‰ˆˆˆD$ึA๊ขศฬ0VE/‚1rO}ท~„มน}`…)‘ ’‚”ˆˆˆHDโคR“฿I๚Š?วสTดก๕‰ƒท็ˆj.ฉ0%""rAQ‰HœƒTz๊๛H_ง˜T%A๓!Zgผ}๋ฃ฿ภฟฯS[]SWฏ#JDD$พคDDDD"฿ eHO3าS฿‡Id๑›๖‘{์xทœฟMR˜‰5)‘ˆฤ6H‹ฬŒH]๒nL"|7ญ~ศฮ๓ฟmๅ0US]Sืจ#LDD$Fำ )‘hฤ6HY™ซ>B๊โ[0vh=ญ|๘ห]c๛šBใ-ดฐ*L‰ˆˆฤƒ‚”ˆˆˆHDbค์ููŸ$9๑FŒeใA๋รwœ8ะตถSaJDD$6คDDDD"ื eœ™นท“špƒw`s9Hตํšฆzึ,ฉีQ'""าE็ R""""ัˆmJdศ^]Crฬ|ผhyจ–ฐpขkox@ƒ1^muอ’{u๔‰ˆˆtฑ๙…‚”ˆˆˆH4bค’Yฒ >OrิU†ธ{_ค๕กZยR.; 0%""า๕ๆ R""""ัˆmJUQq฿“1ƒ0๐๐vฏก๕ก; Rผv$ มทฆบf้ou4Šˆˆœ็๙…‚”ˆˆˆH4bค2ฉธ‹$†]N่ปxปžฅๅกZ ฆ๓ศ€ลNŸ!ตUผฏNGฅˆˆศyš_(H‰ˆˆˆD#ฎAสส๖ โฦ3x ก_ยฑŒึGพ๋ฑp๚ฃโ_[lU๖ช๊ttŠˆˆDKAJDDD$"ฑ Rฝจธ้qN"๔Šธำ๚๘?วy Œ3h•7‰ษVด]\|—5™ูŸ\ซฃTDD$ขณฑ‚”ˆˆˆH4bค*๛Pq๓8วบJ[ž"๗ิwb<6$†Lฅโฦ/cาU-‡)ฌล~}Ÿ1ฆถบฆฎ^Gซˆˆศ9>+H‰ˆˆˆDใ๘]ื„q\wษ๊ึŸสw|ปฯ่rฺ๘(นบปc<6$†ฯ โ๚/bRอ)ฌบŸโ†‡สฟ|…)‘s}:V‰ฦษ+ค q SV๗T๒5์^ร <ล๕ฟ'ฟ๔‡1ž[$F]Eลu_ภ$2M๛ษ?s/ฅอOtพ]เ฿ีฆu๔Šˆˆœๅำฑ‚”ˆˆˆH4š๛ฏCศNBฏุ>#aส๎1˜Š[พc0a)Gqไ—8พaู$วฬ#ปเs'…|…•Ni[ซoะoก…ตPaJDDไ์Q‰ˆtW่n_Bi๛Rฃป cึตร”s•ท~ซ๛ยb+ลตฟ&ฬฝ๑ห!9~WlX๙ๅ?ฦนโฬฃ0%""rV)H‰ˆˆˆD'$๐๐์คดๅ)J;W4๎ๅdŒ๊šaส๎=ฒคช๚[(NŸQ`':~[๐๖ญงด้ =/ๆ›บฬv;/ฆ๒ึฏaRU„นF๒ซƒโ‹ฟ๏8‘&5๕df€ทoนล๗เฺ๚ๆ๏4 ม˜าmี5ห๊tค‹ˆˆผŽ๓ฑ‚”ˆˆˆH4Ž฿uuเ๔ฟgุ4’ฃฎย๎5,ปใ6aก๗ๅ5”^z๏ภFยbหy฿ngศT*oพ“ช ศฃฐ๒g7<฿ p2K๚ฒžAผ=kษีดญ฿yภbcJต S"""ฏq>V‰ฦ๑ปฎ O]สt ‰‘W’>ปzpง0ไŽแีฏขธ๑1C[ y๎ฤ๐+จธ๑c’Y‚ึฃไ—„าฆวโ;NUž็คงพw๗r‹๎"hs๖DaJDDไŸคDDDDขั~…ิ+-OŒ˜Ab๘ C/รช๊ถำ๑ป ๙๎Že7?Apดžะ+Fพ‰QณจธแK'Eะ|ˆ๒Sฺ๒T|'ภ้*23n#uษปpw=Cฎ๎n‚ฮƒฦ˜š๊šบzฝDDDN9+H‰ˆˆˆDใd๊˜Šัฆ,›ไจู$†Oว<ซฒฯษ+ฆย iฅmu”6?‰฿ด|7ฒํNŽฝš์ตŸo Rษ/ฅm‹ใ;ฮT“น๒รค&ฝwวฒrj9r๎4๐๏3ฦิ*L‰ˆˆดคDDDDข๑๊ ี1%ฃ=L™d–ฤจY$Fฬฤ0ซขSพYเใ7๎กด๙ J[4‚ภ?็œp=ื-ุAำ>rK„ปcYlวมส๖$3๋ฃ$'\@ib๒uwไŽŸ๛W˜)ฯyคDDDDขqๆ ušIZฆ;ษ1sI ฟป฿8ฌlสแ Bฟ„dฅMใn_B;็pN—št3ู๙w€ๅ4๎!ทไธปž‰ํ8X•}ศฬ8ษฑWPฺ$นล๗NDถ a่ia-ฌฎฉkิ+CDDŽคDDDD"๒F‚T;ซขษqืเ ›†ำ{&ำ Œ@Xlล?ผโฆวqw,o๛Fพณ?ทK]๒.ฒsocแk ฟ๘๛ธปWวvฌnศฮ๙$‰Qณ(m|”’๏[ฃ€ฆะx ฆDDไํHAJDDD$"o&Hตณบ$5แZœ!Sฑ{วค*สa* ‹อxทP๐{]+ม๗ฮ๊vงงพฬฌO€1๘Gv’[|žตฑซzูนท“~ล ‘_๒ƒ๓๗M† S""๒6ค %"""‘7ค:#Ÿg4ษqW“|)V๕`L2[^c*๐ '๐๖ญงธ๎ผ—_8kž๖งdฎ+ภเFฎ๎ผ}๋c;vฯadๆNb่e_-๙ฅ?"๔K็wรšŒ๑jชk–ซW‹ˆˆ\่คDDDD"๒Vฎze˜r]Lr‚๒ย็๚—ร€๏ไŽแ๎~žโ๚฿แ๒g‹†๔๔ฟ 3ใ/๐n!_w7Mฑป๗Hฒ๓>ƒ3h2…็E~๙!๐บฦ4ใี*L‰ˆศ…LAJDDD$"o-HuL฿85L%†^Nrยต8'`*zaœ4ฝม‰xปืP\ ฑ†7๗p–Mfฦmคงไ๊๎ฦ?ด5ถใ`๗Cv8. ๐ฯษฏ้9]MQ˜‘ ˜‚”ˆˆˆHDฮN๊˜ฦัฆŒ!9z‰1๓p๚รd{`์Dy})ท@ะดท~ล 4|๕฿!ถCๆสž๚~ผฝ๋สA๊ศฮุŽƒำูyŸม๎7)<๛ไŸนฏ๋npภ‹ฦ”jชk–ี้U$"" )‘ˆœ ี1ฃ=,;Ib์|’c็c๗…•้– _Fพฦ=ธ;WP๐{ยB๓ซด๗๎คศ\๕RS๏ๅ็ษี}๏อ_qี8'‘v๏Q†ไW”ยs?๏๚ฐุ˜Rญย”ˆˆ\คDDDD"rn‚TวดŽŽ0•ช 9แ’cๆ`๗†IU–ฟ‘/๐๒M๘G๋qท-ฆธ้ัSพ‘๏๔aส$2df}œิไ[p๋W‘_r๑=ฑg๐”r๊9 ย€ฒฃ๐/ใณ S""rP‰ศน Rำ;ฺร’Uู›ไฤ›IŽบซภถoไ| w๏เfํK)m}๚”๕“:‡)“ช 3๋ค& €ปs9น%? hฺqH ฝŒฬผฯ`๗Onษ๗)พ๘๘ํHเ฿—ž๒žฺฬ;๊๕๊‘ธQ‰H4A๊ี์žรHNผ‰ฤ๐้ๅoไs’B่—[ใํ฿Hi๛RหO&!&UEv๎งHNธ€าถลไ— ๙Plว!1bูนทcuพGฎ๎.ŠŠๅพค/}/™ซ>zvขจืซLDDโBAJDDD$"็+Hตณ๛Ž!u๑-$†\†Uูlh[๘ผ๙พ ”ถ>๗๒ ''‹™jฒsšไธk(m~’ฒ%h=qHŒšEvฮงฐบ๕'๔KไžฅอOฤr_า— ™ม?ถ๛พงถ๒๏ฉืซMDDบ:)‘ˆœ๏ ี~ี“3`"ฉK3d Vฆบผพ–rM{๑๖ฌฃดu'E๖บ/3€โK_๑cย\clว!9f.™9Ÿยช์C่ษ=MJ๊bน/้้NๆŠ?หม?ZO๎๑o5นื/ดฐVืิ5๊U'""]•‚”ˆˆˆHDฮ๊˜‚e“v9ฉ‹oม0 “ฎ,ส฿ศwผwวrC[INzวษ ตA๒+~JX8qHŽ_@fึวฑ*zบyZฦ+>ฎ™™&}๙สA๊๐vZŸ6กญะOaJDDบ,)‘ˆt ี>ด0NŠฤจซHMผ ปฯLชขํ—!aฎ ๘ห˜l์ƒ(<+ ซƒฐุqH^t™ซ>Š•ํAXสั๚P-๎๎ีฑ—ฬฌ‘พ๔}`ู๘‡ถ–ƒิแํ'o 0%""]”‚”ˆˆˆHDบ\jgู˜TษัณIŽฟปฯhL"]]เ—ฟฯv(ฎr‹๏‰๕8ค&ฝƒฬ•…ษt',4ำ๒๛/ใํ}1–๛’™๓)าSฦย;ฐ‘“฿ม?บ๋ี7 h0ฦซญฎYrฏ^‰""า(H‰ˆˆˆDคหฉv–ƒUั‹ไ˜9ๅ0ีk8XNง›๘วwS\๗;J›Ÿ ,4วrR—ผ‹ฬŒaาU„๙ฦrฺท!–๛’๗R“o-ฉ}๋ษ=๕/๘วฮ S""าE(H‰ˆˆˆDคหฉvvป[cๆ’šx#Vท~ดลณwืJ]ฯ–rฑ‡๔ฅ๏%}ล_`R•ญGi—๑lŠแL"{u ฉ‰7•ƒิžตไžใ{^๛oŒqkชk–VฏL9/ง1)‘hฤ&H"5๑&าWVU฿ฮฟ‚ๆCธปืเ6ฌยน/๛”พ์คง“ฬ4ขๅ๗_./7ถCลีŸ%9แz0w๗jrO/$hฺ๗๚๏#`ฑ1ฅฺ๊šeuz…ŠˆH”คDDDD"ว ๅ œDvงฑ๛Œ฿%๔]L"ฆ|>ม‰ธ๕ฯโึฏยmxฎห๏Sz๚I_๖r:ฑŸ–ฟŒdG&๒NŠ์5Ÿ%9nA9HํZIฎ๎{'ผ๑;S˜‘จฯc R""""ัˆcJ ฝŒฬ์O`๗E่)ฝ๔&U3d*VEฏ“7 ใ/ใ๎X†[ฟ o฿๚.ปO™™&u้{1‰4๑=ด>๔ง_ผซOไ“Yฒื-ษ1๓สAjว2r‹๏!h>๔ๆ๏4`ฑ1AMuMZฝbEDไœžวคDDDDขห 5b™ซ>V^เ๗ศ-๚.~ใ^ฌส$Fฯ!1ไRLช๊ไ„‘”ถ-มฝ๏เ–.ทO™Y'uษป0N ่.Zบ๘๎๘MไSUT,๘‰QณภJ[‘_๒‚ึฃoฮ>cLmuM]ฝ^น""rNฮc R""""ัˆe5‹ฬUล๎1|—ึงพƒxVe/0Ve#fโ ผ“ช8๙‡พ‹wxฅอOแํ]ืฅ>—{;ษI7—ƒิแmดx๖ฉโบฟ'1v~9Hํ]G๋c฿xk๋.'VU฿r:0ื=@~ๅฯ 'ฮอ4…ฦ[ha-T˜‘ทJAJDDD$"q RฉI7“žAฌช~„ลVZ๛:๋ิ)%aชะ –ƒ3pษฑ๓ฐ{;ัqหฐ”รmxŽาๆ'๐n9;๋ฝฑ้/7|‰ไู่`'pwฏ!๗ฤ7 ZŽฤ๎xฒบ bม็q_ ฯŠยช๛ ‹อ็๖ฆDDไlœ‘คDDDDขห uษปI_ฌส>„…fZZ[Œ:ฎœฆŠญ'…3d*‰‘WbW้ธeX8ปke๙Šฉ#;su กโ๚/‘yุ๎ฎgศ=๙ํณป๎RD์Cศ^๓9œA“ „ยšขฐ๚็„ลึh6 -L๕ฌYRซWทˆˆผQ R""""‰cJO}?ฉฉ๏รช่E˜kค๕ัฏท…ฅ?ด+ง„)ท€IfH ›Ž3๔2์๎ม:ฆ‚–รธปžกดๅI#๕็๊“ศPqร?6ญคถ/ฅ๕้๏ž›u—ฮ1ปื๐r0ยยชKแ๙_–rัnH@ƒ1^muอ’{๕*‘ื}NV‰F,ƒิด?#5ๅ=XูญGi}์Ÿ0ง\้๔SM:ย”๏a’Yรง“zVUฟN๛ š๖Sฺฑ w"ฃ „nL~ำUT๐%Cฆ‚ฑ)m]Dฎ๎๎sท๎า9d๗C๖šฯโ๔ O~ๅฯ(พ๘Bทp~6HaJDDศ9YAJDDD$q R™ท‘š|+&SMะ|ˆึ'พ‰9eMจื9ๅค#LVถ‰ก—แ นซข7SพYโ7๎ฅด๙ ห ๗zลณบ?Vถ'7| gะล`,J›'ทไ„ล–ุON dฏ์>ฃภ๗ศ/1ล๕ž๕็์ h0ฆt[uอฒ:ฝ๊EDไŒณ)‘hฤ2H]๕QR“nฦคซš{๊)ƒSONจŸฉ่Mrฤ ์ae{ด<ฃ๕ๅ0ตk%‰ƒเปgeฌชพT\ฅ๒ว€โ†‡ศ/q๔s; œA“ษฮฟปืpBฏD~้(ฝ๔ก_๊ฐุ˜Rญย”ˆˆœvV  %"""Xฉ9Ÿ"uั๕˜d%~ใrOใ$ฯส}‡^‰ะอใ๔KbไUุ}ว`eบw|”/๔Š๘‡ทSฺ๘(nร๊๒7๒[zLซz0ืง๏ุ๒บK๋ ฐ๒฿ฯ฿ว‚ฤะหศฬ๛4v๕Bฏ@~๑๗)n~โฌลปณFaJDDNCAJDDD$"q Rู๙ww &Yฌพค’ูณ๚aก,ง#f`๗Iw๋๘(_XสแุD้ฅ‡๑๖ฎ#ศ7Bเฟฉวฒ{ งโบ/`๗Ex_๘V?ๆ๖&$Fฬ$;็SX–rไ๊๎ฆดm๘^ืเ€ลฦทUืิี๋ฟˆˆ(H‰ˆˆˆD$–Ajม็HŽ™‡Iค๑์ ท่.Lช๒œcจธ๎๏;>ๆVXs kป๋]U๔:$วฬ%3๋cXU ‹-ไž.ฅห๒Ud็\เ฿gŒฉU˜y{S‰HƒTล๕‹ฤจY;‰wh+๙บป1™๎็๔1รB3&S3๘ƒง`U>yUVดร๓ล ใVFพื9งuL$ปเsุ=†บ ฯGแล฿tซŠ€ไ๘dฎVeย|ญO ๎ฎ•o๚๊ฑศ)L‰ˆผญ)H‰ˆˆˆD$–A๊ฆ/“>c;x๛7’[๚ร๒:O อX๚ใ ž‚3๐bฌชพ˜d0เ{อpw?Oqร๏ ŽฟL่•8uั๔ำqOกโšฟล๊>€ฐุJ~ลO(พ๔p|"ฮ)Ro"=๓CXูžนcไžnร๊7|ีุy๘w%Nฌญใ4๊ฟ„ˆศ‡‚”ˆˆˆHDโค*o๙*ฮะห1ฦยปŽสŸbฅปEบ aกปืœA“ฑ๛_„Uูใคภ@่Nภญ–โ‹ผๆย็‰แWฝบฆ|UQแนฅ?ขด๙‰ื}…UW’บไ]คง+SMะz”ึวฟ‰ท็…X๎Kๆส6%'^ฟะุ‰…&Uฅ0%"๒6  %"""‘Xฉw}g๐%xปŸงฐ๊bาU็e[Bฏ„ำ{ฮ )ุฦbฒ=0vยฐ”รo‹ป} ล—!ฬ7qบซฅฃg“{;VE/‚|#๙บ๏Qฺถ„ืบฒช+JO}?้ห?€IUดข๕ฑฦท!–๛RyหืH ›˜&w๗๊…ญ~ia๕gžR˜น€)H‰ˆˆˆD$vAสXTฝ็8&†-Vd IDAT~๙*ค5ฟฤค+ฯ๛ฆ9}วbšŒkVบ;ุaฑh=ฅ-OSฺ๒$ก[8u‡ส๋.อVฆ;Aหr‹๎*ฏปC้้$}้๛0ษ,ม‰ด>๖ ผ›cน/U๏๙6ฮภ‹pwฏกๅท_j2ฦญฉฎYrฏsˆˆ\˜คDDDD"ท e์$•๔œ~ใ}w็ Š๋~{r๑๓อNb๗Cb๐ฅุีƒห฿ศgูxนใ๘ทPฺฑ”าๆ'vศšx™+?‚IWœ8H๎้มฝ&†ณxCfฦmค.yO๙๗ะ๚ศW๑์Œ฿พX6U๏๙N‹สแsื3ด>|g๙w ฦxต S"")‘ˆฤ.H%ณTฝ็;ุ}Fzล๒วแ6>‚Idบฬ6†^ ‚€ฤศ™$†\Šี}@๖BฟDุzoFJ—เ๎\Aj๒;ษ\๙aLฒฟqนงพ…ทw}&ห&sๅGHMพc'๐ํฆ๕แฏเ฿ฟ7$‰4•๏v[๘tqw,ฅ๕ฑ๊|#…)‘ Ž‚”ˆˆˆHDbคฒีTฝ๛ุฝ†บJ[žขดuฦIvนm อ˜T%‰QณpMฦช๊W^๘< w’„nŽะ+•ืœ2ศNZ๛ฑ†๘Mโ™นMrยucแB๋ร_!h9ป}ฑ*z•ณ^ร KyJ[ž$ท่ฎ?G‹)ี*L‰ˆฤ—‚”ˆˆˆHDbคชS๕ฮยชHXhก๘าCxปื”ืi๊โยRป็pฃga๗•๊ถ aฦ@AหarOทู๖ฉ1q๙†:“H“๗’ใเุHหรต„น๘}1ีญ?•๏๚g์๊!ๅ๐น๑qrKพ๚XaJD$ถคDDDD"ฏ eฐ{ ง๒ึฏcu๋G˜?Aqƒx๛6”ปML„พ‹ำo‰aำฑ{j๛†ภถ๐]ผ›)m[„ปsA๓กŽ}๏๊aส$ณdฏ,ษ1s o฿:Zช%,ถฤํํv!ๅใฌz aก™โ†‡ศ/๑ป›ภภSS]SWฏ4""19(H‰ˆˆˆD#vAช๏*o๙*Veo‚\#ลƒhk Ÿy‹0๐pN"=ๅ˜TUวoส Ÿร?ผwื3”ถ/%,6w<]5L™T%ูŸ#9j>๎ห/ะ๚p-ก[ˆ์#ฉผ๕kXU} ๓MืŽ3๗พนป ๛Œ1ต S""18(H‰ˆˆˆD#nAส8‘Š›๏ฤส๖ h=Jqํเู็?,ถ’บ๔ฝ$วฬm๛Aว๗h S-G๐๖oฤ๕ ๎Že„~ฉใน่jaสคซจธ๎ $†ฯ \ผ†ีดโฒVงใlภ$*nGฌlฯr๘|Wžๅู๓ะปำยZX]Sืจ@""]์  %"""ฦ๏฿†^ฑ}ึตใฑH ›Fล _ยค* šQX๓฿M{ใ;v’ิE7’9|w๗ ซAjโ8รฆae{žผbสอ4๎ลณw็ ผ=kO}rฮ๛ุYูžT๘8ƒงzEหi}๔k1|7bH ™Jล ะ>SX Š/๖์=F@Shผ… S""]์  %"""ยณ–v,ว?Vพ>ฃK†)c‘y%ื}“ฬœุOน_ถŠ๏ฤ7ไ๘kI ›พKiว2Z:&™ล๎;–ิไ[I šŒษTwMXlลoƒท{5๎ฮๅx6Ÿz็m์ฌŠ^T๔8'•ƒิถ:Zf ล"1|:ืฑ-|คฐ๊?)n๘ู,…)‘ฎu P‰ˆ๏…๑Jใ๎\|7๘ํktฑ0eู$Gฯ!ปเ๓˜Dš q/…ี?'h=฿‰o"Cj๒;หW๙%m‹i}์Ÿ:žซข'v ค&Œ3h2&‘้๘ฐุŠd'nรณธปž}ลZZัUี—Š›jq๚'๔Š”6?I๎ฉ๏ฤoP,ป>ฏ๛r๘lฺOู๛(mz=f@ƒ1^muอ’{๕OIDไ<ž—คDDDD"Sžx๙ฑ]”ถ<ปsA๓!N~”ฏซ„‡ไธซษ^๓YŒฤ?พ›ยs?'ฬว๘ยc“ž๖ง8&๚ฅrฤy๒ฏธมช์‹3h2ฉI7แ๔Ÿถsr‹-๘‡ถRฺนฏa๑=็gxบ๕ง๒wb๗C่(m|”\๑ห!9ฆ-|:)‚ฦ=ไWŒาึE็ฑฆDDฮ๏iYAJDDD$a)šd๖ไ|่ฎ๒S;–4๎:aสvHMธž์ผ;ภv๐ึSx๎~ยbK|Ÿภ#{ๅGฑ๛+_Uด๑Qr‹๎:ร,ูย๊>€ฤเ)$'ฝงฯจŽ…ฯย\#มMธ;–ใ๎^Cะ|0า}ฑชQ๙Žฏ`๗QR"ทไ๛๑!9๖ฒืMG๘ฬ/ ๎Žeัmƒย”ˆศyก %"""‘โ{ยไ่9ุ}วt๚8XG˜ฺZGiว2ยๆC„~้<‡‚ฉI7“{; ศ ซ๎'t๓ฑ}C฿#;็SุฝGzEŠ๋$ฟไฏ1[ถฐ{ '1lษ๑ืb๗–~ญว๐๖mภพoฯฺ๒7๗E1<=†Pqหืฐ{ !,ๅ(ฎ{€๒วoPN>๓หทู่ท%`ฑ1ฅฺ๊šeu๚o%"r๎)H‰ˆˆˆDไ๘]W‡vŸ18ƒ'“5ป฿8Œ“:yƒถ0U๎Žๅๅ๕š:?x’h'IMพ•ฬœOะV๒ซ๎‡๓สŠภ'3๗v์žรล๓๚#Žภ้=’ฤศ+IŽU=ธ๓]ทลฝšาถ%x๛6›ฯ้ฎุ=‡Qyหืฐช•ƒิฺ_“_๙ณ๘ฝฑ“$'ิ)|ๆ—w๗š๓xœ(L‰ˆDrP‰ฦ๑ปฎ๎˜xู}F“6ฤˆุ}ฦ`้“7๔]ผร)mzwืJย\cไWL'Ejส{ศ\๕Qผ›(ฌ๚Oฝ๘@วษˆ๓ยฏศ?s฿{^i์>cHŒšErฬ\ฌชพข๙๎ฎgpw,ล;ฐ‰ฐ”kKฮๆย็v๏‘T๚uฌช~„ลV ฯ7…U๗ว๏อˆ“*‡ฯูŸ =|ๆ–|o๏๚.pผ(L‰ˆœำs€‚”ˆˆˆH4สAชs˜p๚ร6ฤ๐+ฐ{ ็ิ5ฆBฏˆxฅ-Oโ๎XFoŠ์Š)“ศš๚>23nภทยsI—๚&ภ7( B*-VU_ยRŽย๊_ดํำ›x~’YœHŒžCbฤLฌสง๓‹๏ม;ฐฉ๋ldเ฿gŒฉญฎฉซื1‘ณxP‰ฦฉWHฝ*L๕ฟgุ4รงa๗ŠIUv.t๓'ริ๖ฅลf๐ฯํ•J&™%}ูHO`9์YKa๕ฯมXฑ}ร0คโฺฟรช่UŽ8ซ๎ง๐/฿ฺ๓”ฎย8‰ไ˜y8C/วส๖8๙หภวoƒปcฅmK๐ํ:eZ˜ฒ๛+ฉlOยbsพ*~oFN>su฿ร?ผญ๋mฌย”ˆศู=(H‰ˆˆˆDฃs๊˜Žั)L ธˆฤ๐+p†^ŽsX็+ฆ<แํ”6>Jiว๒๒วม‚sฆLช’๔ด?#}ูเ๎^Ca๕/0ถ฿กโบ/`ฒี„…f๒ฯGqํœ•ปถฒ=q]Lbฬ<C/๋ |c ”ถ>ป}๑—O๓7ฆœQy๋ื1™๎g}_"}3rš๐™ซปh}ืh…)‘ณsP‰ฦ้ƒTวดŒW^1•= gะ์žC;‡ฉRะVŠล๕ aฑยเ์NำUdfF๊’wเึ?Kaอ/1N"ฦ3_Cลu_ฤคซ๓MไW;ล๕žี‡ฐ*๛เ ™Jrฬ\œม—t6ลภร;ดาฆวp๋Ÿ%8qเŒใZœSyหืฺ๖ฅ‘3๗R\๗ป๘ Iช‚๔ดv Ÿ๙บป๐๏ฺ้ะoก…ตฐบฆฎQDDฤ9@AJDDD$8HuLฯ่ฆ^Lr๔œAcu„IUด&$,ดเฺzr๑๓b+gk'“ฉ&3๓Cค.พฅ v.งธ๖7ใ+คŒ• {0ฉ ย\#๙?ก๘ารg๋;=๗V๗$†_Ar๔์~ใ;-Z๚%›(n| ฏแน๒ท)žแ~ฮฤr)•7ๅไพฌ)ล ลoLาUdฎ๘KRSS>ฮ๊Ÿ%ท่n‚๛ใฑ S""o  %"""ืค:ฆit Sƒง5ซฆบ ,_1e „!aพฉฆ6?Žปc๙) hฟyVถ™ซ>J๒ข(m[Liƒ๑RNš์ต‡If Z’_cJ›?าi์^รI ›Nb๔์#;‡ฉRo†rP€์œฟ&1๒JŠ/=oโ;w4ฝจ˜7`;M๛ษ-นง|%Y4ฮซ‚โศซp†^†}@ง0ดลน‚าฦว๐์8ํG0“ใฏํืwวฒุษซย็ๆ'สAชุ|aผ่Œ)V]ณฌNED^qfT‰ฦู Rำ8:Ž3IŽปง฿xLEOŒS^ซ(๔Š-G๐lคด๙ k^ืฝ=“™s;‰แำ(ฎท™7uตUWau๋Ov๎ํ`9๘ว๗_|nรชจง฿'วอ#ฏ"1b‰ม—bU๖9นFWœ8@i๛J›Ÿภ?พ“มLMผ‰์š“qm๑=ธปVฦpL๛)#ฏ*g/=B~ษ๗เีaq†Z[JDไ4gD)‘hœ ี1ใd˜2$F]ีฆฦaฒ=1v Aหแ๒S›ว๛โ๎ฃฬ๎9Œ์ผOใ ™Z/ฆํ*ซ žO~`๕Fv๖'มX๘วศี}๏ๅ็ฯื4ผใ97v’ฤู่$†_3h2VE/ฐ์ถํ๖๑›๖Rฺ๒4ฅ-O4๎BR฿Bvงมr๗ซ๛nรsฑซz0ูนMb๘ๅใlƒไ—ะ-\0ฏ{)‘3œ คDDDDขqn‚ิ้ๅ;$G]u๒ฃ|™`ๅoไ+ๅ šโํ‰า–'๑๖ฎ?ujH{$ฑ{$;๏38ƒ&Px—ธ๕ฯal;žQภ๗p๚#sๅGภ#;สAj๏บ๓=๏xฮMช’ไ˜น$†_Vถg๙›|๘nŠฅดๅ)’cฏ&;๛mW{ํ&ท่๎๓ื<ป็02so'1๔2 >๓K•ะ/]0ฏ{)‘3œคDDDDขYjŸ่9)ฃg“ฟปฯฌtUZE!a1Gpb?พ๕”ถ.ยทกs(่;†์ผ;p\@แนŸใึฏย$ำ๑Œ^ gะd230๘‡ถ–#ฮ]n[ญlOใๆ—รT๏QX™๊Ž0–rx6_ย<“ศเU—NWฝลC9|~gะ%ๅใ์๙_‘_๑ใNOŒ;)‘3ฬSคDDDDขu๊˜๐%ณ$Fอ"5แ:์>ฃ1ฉJ0VSญ{q๗ฎรถ๏ภfœ~ใศฮฏม๎7)<๛ๅ •ฎŠgp $†^Nz๚๐l"Ww7ม-]v›ญชพ$'\Gb่ๅุ=‡bาสใ๘„‡ฑๅE๎้…x๛ึวn\์>cศฮ ฮ€‰V‚ส๕Zeฏ:๖คDDN??Q‰ฦ๙ RฟT%ษัณINธป๗HLฒฒ|ๅM[๑๗เํ}‘โบ฿aeบ“™๗œ€ŠŸโึฏยช่ฯ(เHŒผ’๔ิ๗เํ]_RGvt๙mท{#9แ:œม—`๗‚IdOฎ1Eyแ๚าQ\๗@์ฦล้?žฬผ;p๚ ๐์ๆ>โmŽฏ:๖คDDN?/Q‰ฦ๙RภLu9L_€{&™m็LXlม;ด•0w ป฿x์C ๐ษ/7†็ฐช๚ฦ๓ษw $Fฯ!5ๅ=x/ฟPRวบ๒TSรŒำ<ษฑืเ นด<.vขใwA๎๎5ื=€ทcl†ล0‘์ผฯ`๗„ไWŒยช๛/จืฝ‚”ˆศฮr R""""ั่*Aช< 4XฝHŒšu2L9ฉถwะa)ถำ๑ณ“฿ยทซ๛@N๗ญ|]> ธ’ใฎ!u๑-ธ๕ซศ/น๘ž8Lู;=฿‰‘3ษฬ+์#;๏ฃW$h>Œท{5ล๕โีๅ๗ฬt ูyŸ.๏K’_c k๋‚z+H‰ˆœแ์ฆ %""".คฺYvG˜JฟถNน๒ฆป})๙ีฟภsส:R๑ Sก[ 9แ:Ro*๏ฯฮๅไ–€ iœฆ๎ฯwfฮงH_๚๒พyล๒oํdพๆ š๖โ6ฌฆธ๗'๖wู๑J ฝŒฬฑ{ƒ0 ทไ‡ื๚‚z+H‰ˆœแฌฆ %""".คฺู ฌlฃf“บ่:์ž#ภvNพฉv๓๘ทเ6พOPS‰F,‚T›ไ„๋ษฮ๚8&[ _Žฦ:๙&ปุ‚h๋ษ0]:L…n๔”?"1z6ล ‘_๙Sย\c&๐ษ,ูนท“ผ่+(ผ๐kŒ“ฏ„=h2ษ3ฑช—ฌ7| w ๐J๊(m~โิ{UIvgHŽ_”ฏ*ฎฆmํฏะ+บy’cๆ’1ซช&‘ ก_"l9Šw`#๎Že”ถ->๕ž#ฏไุ๙df}ซช/กW$๗๘?ฟb›โOAJDไ ็3)‘hฤ)Hฅ&Lzๆ‡ฑฒ= '(พ๔Vท'‰ีc(v๗ๅ+oฺ฿t[;"‡xะต?}๔eLbุ4 ฯ’ยช๛ ‹-๑›ภgบ—ƒT๛วทBฏ„ำ{8‰ัsฐ๛Œฦ$2ํฃEXhฦ;ดฏ~ฅํK šž›ใl๊๛HO๛ณ๒•xนFš๗ฟ๐nน ^๗ R""g8)H‰ˆˆˆD#VA๊Šฟ$=๕}˜d–เฤ~ร;Kญฏcvicา0ษ4ฆข7vU_ฐNฎm[๑๖ญรพ” ุY˜2v‚๔Œa๗ a@n๑=7<พปใศ๎1”์ี5ึร๒๖พุ้สดือฒ! ฑz#9fv๏ปฃ•!Aฎภ&๚g)ํXJ˜k<ปวูๅB๚๒t\‰ื๒ภลฟp(H‰ˆœแฌ %"""8ฉฬ•E๊’wc’Yฦ}GwพŽ uสZC–ƒIU•รTฆGyฉNaชo฿๚r˜*4แซฏฮฦคืI“ž๙!์žร ๐ศ-บ‹โฆวภ๗bwูฝG’wGวzX๙g๎ร?ธ™ทดฮS๐ูป๓๘ชฎ๛๎๗Ÿ=žIณ„„˜gฬŒcใyสิดiฆฆอmฺไ6M“fhฺคฉดฝiโไIœฆMำด้“ฆ7O๛คNว‰ ƒ ๐Œ™ัŒ„@๓pฆ=ญ๛วBƒ ^ฟ๗๖ห>G็œฝืึพึ๚ญ ;„Uท {ฅำวซ’=xํฏโ6๏รmฺNฟผขk?@tๅ{FGโ ๔ฯ๐ปฏซ๓^)!„˜เ,”B!DnไU ต๑ฃD–>ˆfล๐๛Oโ๗4รฅŒ ป˜Œ ฆ0L๐\Œฉ๓/ ฆœษ—qŽ๏De‡A๙Wงำkฝ้Caะโป$Ÿ:ฮัง!๐๓๎82*็ฟ๕˜ี‹Ez๗๗ร็ ์;ๅf@)ฌkฑ็†^\=าžก`่ ^KธMฯใถ์ ฿VŽณ›~›ศŠw‡#๑:้๐{[ฎซ๓^)!„˜เ,”B!DnไS ฿๔q์ล๗กYQ‚พ6ผžfpS—ีd4˜า๔p*Ÿ ‹ŸT\Lน-๛qO์@นู+Liั"b76zq สห’ฺ๒Uœใ;@yw™ี‹ˆo๚รฐ–RคŸ๛nX| ๎3ๅป ๖์ Xณ7 Vž{1๐ ;ร๖jูผ๗M๏วุ๚นแํแHผพ6’?๛โU/คžkH !ฤ๗f ค„B!r#ฏฉอŸย^xš!่m )/fปœœ1e วJมŽฃลK0`X็3Cธm/แฟB‘/#vใั‹ชQNŠไ“_ฦmฺ yุ6k—ฟๅcSๆBเ“z๖;จกำaˆt…)฿Gณ"XณึcีฏA/จ8๗bเใดใ6์ยm}ฏํๅหุฦY๚@8ฏง‰แŸผ6๏ IDAT9ม@วuuK %„›%B!„ศ| คw~kmhfฟท%œฒ็eโงŽŸสงวKมŠกลKะๅcŠiC๊รk ๗ุ6”๗ Ÿ>zษ4ขซ฿‡^X‰ส“ล_แถ๎ฯห@สช[ElใวยํพGj็ทQร=จซX‡K)ะฃa05}%Zฌxฬ‹~Oฮ๑xญ/เuพไฯ฿๚ ์E๗ YQฎใ ?ƒืีy/”BLะ+@J!„"7๒*บ็ Xs6ข6~O3~o3xWjEผ‹Sv-V‚ž(Lฉt?n๋K8GŸF๙.šnpนลป•็`Tฬ&บ๊=่จ๔รO<Œw๒UR!๐kฤšนŽุ†฿ร(ซGyYา;Ž ู A ดkzผkึzฬiKั"็^ |ผ3วqoวm{ๅ’Vห‹฿i์w ™ผฮ#$Ÿxˆ`่ฬuuK %„R$B!„ศ ค4๗} kึบ0๊n M๛ฮžqมTขอŽกลŠะโc‚)ฅาx-๛pŽ?ƒ๒=4ไRร$ๅf0ซY๑k่๑2‚T/ษŸ๙eไ™Lฌ9‰ŒาZ”›!ตใoQ้h7l๔xึœ ˜U‹ะ์๘นํe๑Oล9ฒ๏ิมptw ึ[ร@ชใษ'Aฒ็บ:๏%Bˆ zH !„BไFR†Eม}Yฟอฐ๐ป๑๛ZภฟZSยฮ ฆ ฆ„มTด-VŠfFFž์‚แnึp?ƒ 4รโ‚)•Mbึญ"บ์hฑ‚แฎp5ทฎyyู๓7[๗แฐ@ป“"ฝ[ูกซถBแ„๛ีsPnณj๖[1*็ขYัsฏ;)ผฮร8‡Ÿฤ๋VŒถ•rRh‘ฌ้ซ0gฌม(ชLษ†]8'v[๛Aฬ๊ล ้8 ฯ‘z๚kจl๒บ:๏%Bˆ ๎H !„BไFR…SI๗็˜•๓P* ่n GH]“80>˜Š W…#ฆฮ†S† Jกœมเ)–ธ ฯA3m‚มำDVผ{mhVฟง‰ก๓)Tv8/ฃ่ช๗Y๙๋่๑R‚แž0 <&วЁc‚)฿Eaึญยช]Ž^T๚ู`J๔w€E• ็ศึp๚แ[อqr@J!&ธcH %„B‘yH•ิRp๏1*fกฟง™ ฏT0y~คล(ช‚HAX=R€ฆ[ ”“ย๏kรk๏ไ+ƒงˆฎ๙ึœแjnง1_ŸFน้ผ<Žขk?@tูปยzXรgH=๓(ŠษH>fŒฅ@aีฏฦฌ]Ž^Pš>๒>พW)œ†gIm๛*=p]๗H !ฤw ค„B!r#_)ฃ|&‰{พ€QV‡๒‚พ6Vฎํ”ฐ X1Œข*ดH!DโhV M7!Pูaพ6ฦ]˜ตห1k—ฃ&ฉร ไsy;'ถ๎รDnxZค`๐ฉํ฿mฬ(ฒษ๕ธq๎wi:zมฬ้+1k– วหF~wHe‡ศ์wœ†็PC](฿น.ฮ{ ค„b‚;„RB!„น‘7Tๅ<w)FI-สอเ๗ท๔ถ29Vฃธ:œฦgวั" จภEฅะ ;(ถ—๏ฯ‡Cw๒Plร๏Yršวh'ฬทA7&w๛Œ ฆt ฝh*๖œ[ย:ec Ÿป๎FœCฟฤmูึ๙๒ฝผ>๏%Bˆ ๎ H !„BไFพRf๕bw zq *›$่ภ๏mar#[ป•ย(Ÿ‰^\ฎบงแtCM~_+ร๕‚dO^G๑Mว^xwXซท…ิŽoฃ™‘ผhŸณŒŠ™ฤozขltๆศ?PูaผำGqฏํe‚ฬ ~^ถ—RB1ม=[)!„Bˆศ›@ชv9‰;?‡^X‰ส โœ kHๅSเนhv ฃb6zมดHœัฐรอเตพ€ฒ็๘Tf0ฏถ-พ๙Sุ๓oG3m๎FR;อŠๆี6ƒงA$๎8œ๊Œdณใแ ‰#SUzฏูCฟภ๋8ˆr’“ซ–ูฅ‹H !ฤEI %„B‘#๙HiX๕kˆ฿๑i๔D9AบŸ`เAษ|์๊‚C•bTฮE Pn•๊ร;sฏe?ฮ‰จl2/ถ)qื็ฐๆl ๋a9Fz็?Œn๙#๎Fณใ$๎๚ยŒ YQ์waV-ผpฤT_nห~ฦ๘gŽ_ี`J/จ เ`”ีฃฒIœ#Oแ6๎]%0šลฤจ˜M์ฦ‚fเ9Fj๋#๘o3 {ึอุ‹๏ งhF‹รขTfฟทท๕Eœ#[;ฏZO)!„˜ ฯ!”B!Dn ๓{”9ํฌk1งSš>๚z๊ ‹gŽื๑:AบTฮaดุอฟKd้ ภ๏mม๏m/“ง{]G/šŠQ9อŠ๔Ÿ$ฝ๛๛จห ุ”็€—A/™Žฝ๐"ม”๏๔ถเ6๏รmืu+?•O/ฌค๐]_C/ฉEe‡ษ|ฏ๕EะดอN„๛ว๗ 2๘ a;5‚sl;nร.”—พโ#ฆ๔ยJโท}kๆM็ฉฎ9ฏeuๅ6ศ@/ชมฌZš†ืy„ฬuลฟFe†F uฯ ฆๆ^ธ*_O๓h0ๅtŒuv้ก‡Q9‚ท=^ŠJ๕“y้?๐{๓ฏ]T€ฝเN์w‚ p›๗’๒UTzเ๊>X1๔ฒ:"Kฤšน=^2ฒG‚ฉŽpๅห†]x'_๛—ผู`J)!„˜เš,”B!Dnผa 5ๆแืžณs๚ ฬiหะ‹ฆŽ 7*3Œ฿u็่Vœฯข๔ซ1ฅN%~วgฐ๊VRm##p๒ดฯจ›่EU˜ี‹๐N$ณ๗_ฏZ๐0˜ฒ0ฆฬยž{+ฦิ๙Nๅ๋i ๋ƒ5ํฦ่ผฌัgfอ +ดhAชฬ Nะื–ํ๘ุKยัJจทaษญ_Ee“นyŠbL™Mไ†ทcี.G‹ŸkC'ฎœุ๚nำผS‡ฦ›—{.H %„\‹%B!„ศKคฮฑfญว™สงWL ŠUvฟซ็ศœฦจฬเ˜ฉFoŽ^\MโŽฯbึ.Hอ฿ฎ›่Eี˜ี‹๐NพBfฟƒฎ_ีฏ=L™U๓ฑfm‹ชŸLy a}ฐฆฝจdฯ%Mร4งฏ เ‡ั"ษ2๛xๅ ็’๏YฌY๋A8วwฺ๚สอํjŽzผc๊|"K฿†Yณ-’8ื†ู$~o๓่ส‰~wรุว(.5˜’@J!.N)!„Bˆy3ิYVZฌู๋1ซกUฌฆ ย็๎œcqžEฅ๚฿๔o4Jk‰฿๑9ฬš%แhžvำG๒wง๋ึศฉ0r[_$๓ย‡6ฆFืีค2C`F0ซbอบฃbึธฉ|๘.^ื œ#[รขฺฉ_LY๕kI๗%4;N0Mf๏†ป๒ฎY”๏]๙X3ึ†ิัm$ท>rอŠ็๋…•˜ีKˆ,นฃf šaŸ๛ญูpDขธทy~_ุ๋ว)(˜’@J!.N)!„Bˆysิ๘^ซn5ึœa0U8อއ+๓ฉ•ฤ๏nยix็ุ3c–ฒฟtFY=๑ป>9u~X{ #ฟ)รฉช…ธอ๛ศผ๘#4ำฮEW{ดํTfอŽcL]€5sF๙ŒฐํF(/Žv;๚tX<ัpฦšตžฤ=_@ณขCgH๏๙Tบ/๏šE๙.ฑ5๏วœพ็ศ’[ฟvmk•izQ5ึ๔ุ‹๎ญ;6๚›GpO<‡ฒŸ`่๔ฅmซRBq๑หฎRB!„น๑VFH]LญยšฝณfqLYฑpZเ‡5ฆzšpžร9พ}ฬˆฉ7อa”ฯ$q๗ŸbL™Rํ๙=eฯˆ WaN]€ธ‹์ห?†œRถ]L%0ช`อผ ฃ|ๆ๘โ็gƒฉรOโ6๎&ศ Œ+\oฯDฎฯฃ™‚มSคw•สปfQพG์ฦ฿ยœv>ูƒOฺ๖I๒„คc”Lรฌ[Edษๅ3ระ๗์oO๕ใuภixฏํฅ7\P)!„˜เr+”B!Dnผต@jด๛ฦุPษœถ {m#มTUXcJำ!๐ฒรแสnปqŽ>=fฤิฤม”1eNH•ฯ ฉพ6ฎใ๙ปำอFq5Fๅ|œ;ษพ๒šน]oฮฆฬš%˜๕ซ1สgิ )/‹๚ูCฟภm~• Wฆ›;‰;?†E0ะAzื๗ยข๖๙ฦ๗ˆฎ๛p8•2๐ศxœิ3฿šdOJ:ฦ”ูX3nฤž;FiธSAฒ๏ไ+8วwเตฟึpป ค„b‚หฌRB!„นqeฉ‹3k–bฯ฿ŒYณtd*_, ฆ|— 3Hะ‚ำด็๐Sa]ฃฐ+ศ๙ม”1u>‰ป ฃt:สห๔ตWฬ9ฯ˜Q๔โฬสน8Gท‘=๐ำqแฯ5่‚sA05}ๆ๔•ฅำวOๅsR๘gŽ‘=S๖์ฤo๛#0,พ“คw#\B1๔I'๐‰ปS็ƒ๏‘y๕1าฯ~gr>06Fๅ\ฌY7cฯฝฝธzฆ w……ฯ๏ภ๋<„rRใ^—@J!&ธพJ %„B‘W3:หฌZ„ฝ๐ฎpUพยส‘S๘Azฟทฏe?ฮ‘ญฉณต‡ฮ$fี"๗zqMH๕ถเ๗4ๅ๏Nทโแฉ)sp?I๖เ/ฎq ล๛]e†ะbล˜ตหฑj—ฃOC‹ฤGพ๎:ˆrำX๕kะ"๘ฝ-คŸ.uตทษD>๑ลจ˜R/'้]฿›NV ฃj๖์XณืฃL๗z0ุ‰ธ็ฤNำGQ^6Vๅ?\๖ษษP!ฮปฎJ %„B‘นคฮ2ฆฬ%ฒ๔ฬฺe่‰Š๑มTfฟปฏ๕%œใฯ ;ณf)‰{พ€^XN๋i"่mษ฿n'0Šk0*f}็8GถL’@jดKฮธ`*^Š9mYL•L;ทขbเฃ|7,ศฎ้#ิw๒ฒY”Rฤ7~ ฃ|๘.™๔๓?ศจHณf)ึ์X3ึข'สวn~_;๎‰ธ ฯโu7ขผดŒBˆ‹]O%B!„ศ\RgSๆY2LU.gฏ•ฤ๏mมk{ ็ุv‚มNฬช$๘K๔D9สMใw7๔ทๅogืN —ิ†ม}๕'8วถ„<“๎ืr~0eีญฦœถฝธf$Dณ๊››!๓โ๐Z๖ฃE ๓ฎmbท|ฃดๅ;d๖ฟd๖0ฟŽญhVํrฌ9ท`ีญD‹•œ{1๐๑๛ZqŽ๏ภ9พแโเ!น !ฤyืQ ค„B!rใZRgณย`ชnU8•ฯ)๊ํ{™žfใฯ]>๔โ๊ฐ~QOAษํ์F ัKฆa”ีŠ์ห…sb็$ คF5cƒ)ฝ ณ~ f๕Œ’i`Xฃ๏T™Aผ๖ืpN~wใรFๅ‡ไ („็ $B!„ศkH 9Œาุ้Kภžu3Zแ”ัSจ€`ธ •ซH!*3Rƒช•๙&ug7R„^Z‹Q:Pd^๘n๓๓hV>7็˜*ช"ถ๊=•๓ฦผG…กbชฏ๓0nรshั‚Iพi๑>^8ๅeI?๗]ฒฏ$฿Žฎq็„^8ซ~ ึœ˜5KฦcษP!ฮปŠJ %„B‘ื6๓ญieuุ‹๎มžu3zQ่f๘ฒ Fฆƒ p›๗ก2>„O๚ฮnดฃt:zษ4P™?ฤm{9ฌร”?[(‚ฌyทป้CaSyYPA*j:สwPษ‘`๊ฤ‚แ๎ษ;•O7‰฿๖I๔‚ ”›!ฝ๓๏ษพxพ>R;'๔’Z์Y๋ฐfmภจœ‹fE%Bˆ‹]=%B!„ศษHyˆ6 Œา:์๙ทcอบ9œv6˜แw7เถพ„fวั sย‡๐Iู•`”ึกWCเ“๛ผS‡ฮ– าXsn!บ๚ฝa๔4 œB/ฎF/ฎ>Wฬห ๗เwฤ9๑,*ี7&˜šํฆ้ฑ?…/C9)Rฯ-ฮแ'๓ัjพ5*faอ\‡5๋ๆ‡อช…ษP!ฮปjJ %„B‘“+ำ!4l๔’์น›ฐŽ˜ฅP™ažfผ๎tำ˜๐!|าm[ผฃฌฝp*้]„฿p6ไๅคฑๆl$บโธMฯ“๓}๔X1‘Žฦ‰•ŒิS('M0t๏ิAฦจtไ ฆฬ‰อŸB‹• ฒIRฯ<Šsd๋๕๒ˆ5n฿S็=\๔›๐\…โผซฅRB!„น1Yฉฑขซ฿KlGFK1nUท‘"็~ื‰p4ŽฎO๘>i:ป๑rŒฒ:๔ยJ๐=Rฯ~‡ ฟ}์fๅ ภšตŽศฒwเถ์#ฝใ๘}'ม0ฑgoฤ^pFๅ<๔h&(…r3ƒง๐ฺเ6?ึฃบึม”%q๛ฃE‹PูaRพsl๛๕๖จ(”๒.๛ไฮ‡ไ („็]%%B!„ศ|ค์E๗ฟํะฬ*r3h๑าsซ๒ึ.๒ป๑NEทข i<„Ozขฝฌ>ฌUไ;คŸ๙[‚แฎ<€ ซ~-‘ฅเ6๎!ต๓๏:ฮํ}3‚5g#๖‚;1ฆฬA†ฃม‚ๅฆ :๐:เ6ํE9ษkLiv‚๘ๆKe2 IDATOกE P™A’O๗ฤณืๅyฏ”pู'w<$W@!„8๏^ ”B!DnไC นแmฤ6~ อŒ t๗oD—ฟฃ|ๆธSสwz[๐NYQl๒’า ฆ„TขๅeIm•๊อฯŽปวฌ_Cd๑ฝ8'v’๙‚กำพืŽcอน…ศ‚;1ฆฬF‹ŒชWู$@^๛ซธM{มหไ<˜า์โท1šGฅ๚I>5ฦืๅy/#ค„b‚{RB!„น‘S๖Vผ;œฒgX'I>๙7x‡0Jk1๋oฤž;ฦ”Yฃดa$˜๊;‰ืyอฐC`Rl^85 คโฅ(7C๊้ฏฃฒC๙y™Q์Y7c/ผ ็ุ6าฯ~๗WŽ๘าb%ุs6†ํV1-gt*Yfฟฟ ฏ5ๆน ฆhฑbโ›?‰fลRฝคถ<‚ผ๗บ<๏%Bˆ ๎QH !„BไFิบ้wภ0๑๛ZIm^ว๋แ‹†‰^8ซn๖;ย"ฺcฆ๒กพถpฤTด,(šn^X…^>=VŒrR$ท>n:?;๎บ‰5o3๖อ8‡Ÿ"?ผแˆ/ =Q62•๏Œ๒™##ฺ*;Œ฿ำ‚ื๖n๋KธW7˜ |๔ข*b›>Žฤ๎"ตๅซธญ/^—็ฝRB1มI)!„Bˆศ‹@๊ฦ฿"ถ๖ ›๘=Ma ีy๘ผคŽ^4ซvyXซจjแ๘` ๐๛;ยฉq^– wMถG/ฎม(ซ?W<{หWQพ“ง=w {แ=ุs7=๘้]„J๗_โฮ0ะc%a0ต๐nŒ๒็ฺM ฆšq^ฤk{๏ชSส๗0ส๊ˆm๘0:M๒ฉฏเ|ๅบ<๏%Bˆ nkH !„BไF>Rฑu&บ๚ฝ ๘]'Hn™ccปŒ &๔โjฌฺX๓nลฌZ„fวว}^0E0ิnš =›ำํั‹ง…มหH๑์ิ–GP9 WLนแmXณ7}ํงค๗3*s™Su=Q†=็์๙ทฃ_L แ๗4แถผ€ืฺฆ”็`Vฮ%บ๎รฃตส’[พ‚ื~เบ<๏%Bˆ‹“@J!„"G๒"ฺ๐๛DW:h:้ฃคถ~ ฟปแbH.Lอ€YฝxL€ ’=CgภMค!Gฃ”๔’้แฉH‚ ีG๊้ฏAเ็ๅ๑ฃ|่ส_วšq#ูW#ฝ็_Pูแ7๗#S0ํY๋รSๅ3มSด>3ˆ฿ˆฒฏUP๊ŠSสMcV/!zำ‡ะ ฟฏิ–ฏเ:t]ž๗H !ฤลI %„B‘#๙Hล7‘e๏ ฉSI=užๆ_ีd\0UT9m)๖์ ˜5Kะb%ใค๚Pร]จ์๐H0•ฝชฃ—ึ…”'๎&ตํ‚ ๒๓ |"ซƒUท€ฬKAf๏ฟขœิ[๛\รย(šŠ5{ค๘yY=่ฦ่ห*;Œw๚(^ห~ผŽpำ[ ฆ”“ยœพŠุš๗‡ตสz[H=๕7xง^—็ฝRB1AB)!„Bˆ˜๔”ฆฟ๕D–พ 4 ๏ไ+คถ}ฟฏ๕R˜qมTa%ๆดeXณnฦœถ=^6!=3D0ิ๛*SzษtŒŠYhV”`่4ฉm฿ไชญwต)Et๕{1k—ู๏d๖u…Šดkfฝฐk๖†ฐ๘yู ะดs_?LนM{๐G๊Šฝ™`Je†ฑfDtีo†TwษงพŠ฿uบ<๏%Bˆ ๎;H !„Bไฦคคt“๘mDd๑} iธญ/’ฺM‚๖ห้^rA0UณkๆM˜ำ–กTŒXw’ƒจT?Avผ+L้%ตSๆŒึ*J=๓ญ|๎บ]>ฬiKศ์W2/ๅfฎ์ท˜‘p5ลน›ฐ็ŠQ:๔1S๙ฒCa0ีฐ ฬQ@ปฌ`Jeฑๆl"บโืยโ๙ง’๚~wใuyK %„o$B!„ศษHif„๘ๆOa/ธ3 คš๗’ฺ-‚มSoๆำL%ส1k–`อ\‡Yป ฝ` h๚น‡v'I0ิ…J๕dมsธ#™ฦR~_+ฉ‡6fิO^ัuขซ?€Yฝ€๔ž๏“}้?Q^๖ชzษ4์9ฑๆlย(ซ฿fู!ผฮ#ธป๐NEณbhฆ}ั๖+H๕Yx'‘บ‰ืyˆิ–G๐{[ฎห๓^)!„˜เ>#”B!DnL๚@สŽ฿วุ๓o4†็Hํ๘vXŒอ*cƒ -V‚Uป kฦ˜ำn@/จ_H;›$H๕ ’ฝแช|^–ทL้%ำ1*็„ลณปI?๗ใB•ผbุDืผs๊|าปพG๖ๅฃฎrxอŠข—Lวž}3ึ[1J๋ฦOๅsRxฏใ6ํ!H๕ž7สํย`*H๖Y๒‘ฅ„ตสฺ_ k•๕ต]—็ฝRB1มE)!„Bˆ˜๔Tค๘ํŒ=wฮฑํคŸมp๗•ฎhๆดฐfˆUป ฝp*ึน‡x7C์B ๗ค๛มsห/Fn”ึaL™†…ๆ8้]8ฎ`w^1"ฤึ~ฃr. Hํ{ฒฏ|77ว‡A/ซรžฝk๎-%ำ/ ฆฺ_ลmฺK๎›p๚e0Cdู;ˆ,พ7 คฺ^"นํ—954H %„W$B!„ศIHลKHฌY7เ~Š๔sŽzนฒ฿ฤูQ3šวฌ]5cm8•ฏจ อฐฯ=ฬ{‚แTฒ‡ ีพsYซไ้ฅu˜#”ืyˆฬž๏ซ‡”Ww+Ftํ1*f Hํ๘6ูื฿หํ๏0#3ฑfoฤšฝฃxฺ…ซ๒uผŽธ› 3pA0${‰ฎx7๖‚;@ำq[๖‘ฺ๖่›œ:๙I %„O$B!„ศษH้ฤo4ึŒศพ8้฿Gฅ๛ฏVW”ั้\บŽ–šฑณf zQ5š=๗P๏fย๚Rษ^‚dฯHฉ7ฆ๔า:ฬสนaญข๖ืH๏๛Wด| ค"Dื|ฃ|ฉํ’=๔$ต๙=vฃlึœX3oย(ฉ=/˜ย๋8S้ั•Uฒ—ศ๊฿ฤž{kH5๎&๕ฬทโิะษK)!„˜เ>"”B!DnL๚@ชp*๑;>ƒUท €์ซ‘~จฬเU๎‘j ฦSkรU๙ช†ม”# ฏยโ็*=H์ ง๚ฟj*ŸNูซœบ‰๚"ู—๓์Gๅ_ว=Zސ*พKr7pŽlภฟถฟหŽc”ฯฤšฝkึzŒ’i็ฌOแ|ทแ9Tv˜่š๗Rฮ๑คw|; ฏCH !ฤ๗ ค„B!rcาR%ำHiฬฺๅd^฿d๖•ฮUื”s#ฆ ฌ๚5a๑๓๊ลแT>;JกTLฅ๚†NS็ํ^M™ฒ7; คšž'๛๚ฯ!p๓๒๘ัใeDืผฝคๅeIm}็ุ3—5…๑jถ™fF0ฆ.ภšu3ึฬuลีใGL9)ฆ็q›vc/บk๚ส0:ฒ…๔ณ฿ฝ SC' ค„b‚;ˆRB!„น1ู)ฃฌž๘ํŸฦฌY(2๛ฬ‹ๅคrEelธdีŒ˜ชY<2b๊l0 œ4*;Sƒงฦ๘ึอp„Tล,ะ ฯโ†rำ๙ูqOT[๓~๔โj”›!๕ิ฿เ4<{ntูตuŒ ฆชcฯ€Yท ฃจzJŠ้~@C‹‚ฆ“}็คŸ๛nƒฯ’@J!&ธsH %„B‘“>š2—๘ๆObV-ฅH๏๙>ูW๋8็Skฐfฎ GLWกู‰0˜ |”“Be†Rฝแˆฉภรย(ŽQRฮัm8'vLธ๚dงV]๓^๔ยฉ('E๒—$ ค.l3อŽcV-ยšฝs๚Š‘`สบเ/ฦ=คw~OำuyK %„1$B!„ศษH™U‹ˆ฿๖ Œสy๘คw}์kบๆฮ๘`สœพ2}Sณฝpd*Ÿ>Le† †Nใ๗ตขY1๔ยฉSf‡Sร็๘3y{่%ำˆฎ|za%*;D๒‰ฟฤm}‘ ฆ*NŽวŒั฿ฅE˜SŽSซ0Šชฦ˜"๐p๗=๐3๎†p5ล๋ˆRB1มB)!„Bˆ˜๔ิดˆ฿๚‡แ7฿'๕์฿ใล$ค&๘ฝำWbฯูŽ˜*œŠfลFƒฉ =€฿‚Q\ƒ^4ะศ๘)ฮฑํใV๏ห'zi=ั•ฟŽ^PJ0๓‡๐ฺ_crRฃฃฟOณb˜ำn๋Gอธ๑‚vP™Aๆ}d>฿ำŒJL๒mป4H !ฤw ค„B!rcฒRV*bท฿ๅ3PžCzว฿แ~ ๅ;“zฟšำW`ฯZ9ํ†ฐ๘นMC๙.šf€aูW#{เg่…•yyๅณˆฌ๘5๔D9Aช—ไใ_ย;u(_;8.™ี‹‰฿๙YŒาบ‘้†jช|Aชฏe?ูƒ?ว๏iAe†ศ็`J)!„˜เฮ ”B!DnL๚@jๆ:b?ŠQZอ-œcฦ Ÿฤฬšฅุ๓n ƒฉยฉhvl|ะ1ุI๖๕'๐ปŽ“‡Q9่ฒwกลK’= ๔ฯ๐ฯฯฟํ(ŸIŽฯ`N]€๒‚พV4+ŽVPfFFฅ†ฮเตฝL๖ภใ๘}m#Eฯ๓ฏ$Bˆ‹“@J!„"G๚ฝ]Mๆj{ฮ-ฤ6^ธŠ›“&๕๔ฤiุ พ—W๛ูฌZˆฝ๐nฌ๚5แh(_|‚T/~O~วAผ๎†ฐ๘y>P ณf ‘ฅoC‹ a๘ฟ4/ ›ี‹‰o$Fล,”“&๓โ†บฐ๊VbV-LAฒท๕Eฒฏ” $สI“Oม”RBqqH !„BไHz็฿+ทีI;ชล^p'ฑuฟƒ^4•&น๕ฆ็๓'ด9Oไ†ทป้Chฑโ‘d€pๆ˜๏ค๛๑ป›๐;แ>AึŸšฌs๚J"K๎G‹ œb่'Bะ2๏ฺลฌ]NึO`”ีฃ|‡๔3฿"{๐h‘BฌY๋ฐfฌลœบญ อฐร?๒]‚d7nำ^ฒAะืŠ๒๒!˜’@J!.N)!„Bˆ\=˜บiๅwภ9ถฏ~wรค๚}‘%๗ฝ๑ทยขูฉ’[&\ล-๐๓r›ำW„มGi]8า&;Œfวัฬ0ไPพ‹J๕ใ๗4ใ|ทใu4 E '฿ฑใปX3ืYt7š]€฿฿ฦ๐cB0t:๏ฺลช_Klำ`”ิข4ฉ฿ฦ9๚๔่ิP-Z„=็ฌ๚5•sะโeฃ#ฆ”—%๊ยkK๖ะ/๑๛ZGF๐Mg ค„โโ$B!„ศแณ)€r3๘gŽแู‚ื๑z๘P= ๚d‘e๏ บๆ่๑ฒฐh๖“_ฦ;๙ จ /wถ5c-๑MG/ž†r†ษพ๒Zผ๔\๑๓ณำย| ‡฿ำ„ื๖2^๛ซ€6ฉ‚)ๅ9ุs7aฯฟอŽใ๗63_Ÿ%H๕ๆ_ปฬ@|ใGั‹ชQN’ิ๖oโ฿92๏\๑s=^Š5wVŒŠ™h๑า0LT ผ ม@n๋‹8ฏ?฿rางH !ฤลI %„B‘ณP!ซฮmG{๘งแ†ื@ว5]๙DVฝ=VL0M๒—w๊๕I–ฝึ์ ฤo๙za*3ˆsl{2ฉ-V‚^:#Q†Aเค๐ป๐NพŒืZุažม”rำุ ๎ยžwšล๏n`่วŸAe‡๒ฎ]์y›‰m๘zA%*3Hj7pwMx์๋…•Xณ7`ีฏล(Ÿ+ง๒ฉๅฆ ๚รS~J0tf๒๗H !ฤEI %„B‘#™ฝ?Pึฬu่e๕Œ ฆ4ฉC8GŸฦ๋8@0p๊šŒ๖ˆฎ ัๅ๏B‹ v’ล_โ>F>ฎl`ฯ฿Ll๏กTคpwซIคแ๔ฝH!zแ๔x9ๆHƒ#มิqผ–๐ฮ฿นฆม”rRD–>ˆ5{šaใ9ฮ๐?…๒ฒ๙ื.‹๎ k•%*าคถ>‚ผ๏ yฝฐ{๎ญ˜๕k0สg G‹@7!๐Qn ฟ$nำ^œCฟ$๎š4+”B\œRB!„9า๗ญ•9mV*ฌ๚ต่euใƒฉ์0^็!œ#[๑:^G{ไ0˜Šญ๛0‘ŽIเ๗ท“|โa๎&๒6Ztฑ›/๔x)Aฒฏํๅ‘m9ป=่&šE‹กTŒ1ฅTzฏปฏy/~w#สM_“`Je†‰ฌ|7ึŒ›ะ ๏ิa†๛tญ€Y๚`Xซ,^F์!ตๅ+ธm/]๒H<ฝจ{มํXuซัKงฃG ร0ั๗ฒƒ}mธอ๛pŽlม”RBqqH !„BไH฿ฃ›รŽ—ฆaึฎภช_ƒUท ฝคอŠŽ †๐Nฤ9ฉƒษžœSฑ%ฒ๘pJXo ษ'ย๏;™ท๛;ฒ์ฤึZฌˆ`่ ้ฃเeนhภfXhf-Zˆ/ร(œ:fฤ”Be๐ป›p›๗โwศy0ฅ2ƒDืผณn5šfเuผฦะcŸหห๚^ั๏&บ๚}aป w…ตสฺpนมงQZ‹ฝเ.ฬบUล5h‘่FLe๑{ย๖rn#H๕]ณํ•@J!.N)!„Bˆ คF{b:Vjฬ๚ีXำWข—L?b*3„ื๑ูCOโŸ:Dธz5ฆ4๘ฆ?ฤ^t7šaใw72๘—๒rท‘ "บ๊7ˆฎ~/Zค€`เ~_*3๐ซฬฐะฬš@+šŠQ0%œvถMฒC๘] ็‚)'•“`*Hป้w0ง/ภk{…แ|^ถLtอ๛ˆฎ 4;N }๒ฏ๑:ผ้ฯ3สgb/ธ#1U\…fลAำยUำ๘]'p[_ภ9ฒ•ฮ๙๖J %„ฉ%B!„ศ ฉั'jซn Vฬฺe่ล5c‚)…JเuผN๖ะ/๑N ชฏt0ฅฤ7 {ํแœฎใ$๖ลk:ฒไญ๕r๕ฐ&ึŠw‡#พ:๚Oข2ƒ—ธ?ฌp*ŸE+ชย(ฌL9)ฎใธอ๛๐ฯG9ษซL้โ๋?‚YsJ๙xญ/0ณ?ฯว†!ถ๎ท‰,{'šร๏?I๒—฿uโ-ฒ1e‘E๗`ึ.WQuจ<•๊ร๏ƒD็ุv”“สูK %„$B!„ศ ฉณtkๆMa0Uณฝธ๚\0ฅ‚T^๛ซ8‡žย๋<„rำW.˜2Lw|k๎-h่x‡ูฏษˆ’+B7‰ญ๛ฐ&–iใœ"่mE9ร—9šGณ"hS0Šซ/ ฆบรSงขZคเŠoN๎'พ๑0ซขทiษ'G>}่ฤึ.‘ฅo ฅท•ไ/ฟทๅ ตปY9{ัa0UX9z)7ƒJvใuภm‡{bgN‚) ค„b‚[‚RB!„น๑†ิhMรžณ ณ~5fอ๔‚J4+h๘ษž0˜ฉ1ฅ<็-ืาฬ๑ป>=k= ๐:0ำ/ไๅ*n๑ ฟฝไ~4ภ๏oว๏m๗Mบ‰f'ภฐะ่%ี็V์#\)ั๏iฦmฺƒ฿yๅ9hv๔ŠmŽJป๕˜•๓Pพƒ๐ษ'ฟœํข›ฤ7~{๑ฝh†N }โแpeษ+๖„ฃก6ฦิyDScŠี+/K0ิ…๚pL5๎รซD)!„˜เr-”B!Dn\r u–abฯฝซnFีb๔ย)hฆ haแๆd7ษWศŽS%ฏTvAงะŠ‘ธ็‹X3ึ Tึ(๚ูฎ^อชซษ5#ฤ6๖ยปะ4= คzšมหผต>L้zAลyำ+รฐร๏iฦk~ฏใ สwฦฌณTf๘mŸย˜2ๅfpŽ๏ ต๕‘kร&v๋b/ธM7๐ฮ#๙๓‡†ปฏย—้hV4œสทไ0˜Š—ŽŒpS(7K0|ิก0˜jฺsUX ค„b‚หดRB!„นqูิู›ลšฝkๆ˜S %สGBึวI๖เถฝ„s๐—x‡ฯ>_wD$๎๛ ฌ้+Qพ‹ืฒŸแวฟ”ฟ\+Fถ?ยžทเ$~w๘ฮ๚-RšSฅำว˜ยw๑{[pwใu@ธเ๊r)'EถOb”ฯD9)œฃO“ฺอk3ึ*iฏ๓ร?•๎ฟŠ_ชฃู Œส9D–>ˆYฝ=QšžCn†`๐4ฉƒธMฯใตพpEƒ) ค„b‚หณRB!„น๑fฉัŽ›วž{+ๆŒต˜Sๆข”„ cชOพL๖ะ/๑ฯฟผฯŽRpร˜ำ–…Sย๒ตFั˜}ฟำุsnเ๗ฤ๏i G‘]QzXฬ\=V†^^?>x <พ6†็p^ รรธ์oQ^–๘ๆOa”LG9ร8‡Ÿ"ตใ๏๒ธ]6‚Rธํฏ‘๙_ไฆศธฆฃลŠFjLƒ9ํ๔x  …๛ุอ žย๋xทy/nห>๐ฯ/—๒ŽถRBq๑หฒRB!„น๑Vฉัœล^x7VŒ)ณัb%ฃฃs”›&่ภm}็่ำ—ผz™+ฆเมฟ‹fปY†g๓ณFัูํ‰’ธ๋sX3oF.Ao[HฝลZ[ฟ๒;ฃE่๑ฒpฤ”?๗bเใ๗Ÿฤmzทe?่šฆ]๒g+7CโฮฯกWฃ2Cd‚๔s฿อรvIธ๓OฐfฎเถฝL๒๑/กฎิศตKก่ฑŒฉ ˆ,บณvY8ฺํ์พ๖ฒxm/ใถ์รm{้-SH !ฤ๗ ค„B!rใJRฃ9;Žฝ๘^ฌบีณัbEhบสG9iผึpŽnร๏i๚ีฯ่๑R ๖`Lrำ8Gท‘z๚๋๙ษ‘ธ็ฯฐ๊ึŒRญ๘ผูQ.—๛(…/E/ฉ GP๘๘ง๐š๗โ6?BCำ๕7L•M‘ธ๗‹่…•จ๔ู?%ฝ็_๒ฐ] IgX๕kQม˜ฉกืโ™DำัๅS็?_6.DT^– ฟท๕Eผ–}ธํฏพฉ`J)!„˜เ2,”B!Dn\้@jดC/!ฒ๐nฌ๚ต่ๅ3ะ#…`เ๛(gฟฟฏ๕ฒ‡Ÿณšู๘j=QNม;พ‚Q1+ฌQtd ฉํๆo'7^Bมฝ_ยฌ]Ž๒‚žๆ7 ๅฎ๘oˆ๒ัโ%e๕ใFแ ม`'nำnๆฝa0๕+FL™! ๎ฝ ‚ ีG๖ีวศ์๛ทk—XqX<ฟn%ส›$SC5 ฝ`JL-นณj1Z$qฎฉ An๋KธMฯใw3ข๋ƒ) ค„b‚หฏRB!„นqตฉณ๔D9๖ขปฑfฎร(™ บฎศ—$่mลmูsd+มpืธjฝฐ2 คส๊๙ูป๏(9ฎ๛ภ๗฿[U{ฆ{ยƒH3)f‚$DQYTX{u,ู–d’`ฏณฝึP–ร๓yปฦฺฒฌณ๖ฃd[ฯkหส –@`ŽˆŒม Ožžะฑช๎}žˆ ™๎ม๏s%Q“บBwU}ฯญ[ฆœงฒ๗! ปถnืต“j!๕ึNผ•Wู‘.C๖){‹qยKƒ1จXทuรไญ}€ Sใ}๖Vพ๎'1กrfฮ1eยฉ๛'ู„. Q~๎‹”žื๚.ษ&Ro๙ชk1A๐#ไฟ๓gต๓๚2ํx+ฎ บๅx+ฎœฆ‚2z๘8๑g๑>Npf฿ด9ษๆSค„bžใฃ)!„Bˆ…qฑƒิไEuช…ุ5๗Yw+NถI€r1ฺว”ฦฺI›?‚๋ซ^ˆฏคแ‰“]…)S๓ Š~ถnืตำฐŒ๔[จ‚X":†๊^MกชO็sšVแ$›˜˜Pcะcฝ๘วžถaส/ฃ\0˜าธQาo*‘EPz๎P~?๊oปคZHฝํผWฺ u๐‡ไฟ๗—ตv‰„“]…ทb ั-ฏวkฟfฦD๕&ฌุธ{๔ ๎'z€'vv˜’ %„๓|ฺJB!„X ค&/Wป๖ํDึ„“iGEโ€ฒaช#่ย?๖•ƒ;!(ั๘๓/Nรr;i๖พJ๑๑ฌuํ4ฎ }ง์-ˆ~=tŒp่Xmผธh '‘EE“จdNผัŽd0=Opโy*]ป1…aงค฿ฺ‰Š5 ว๛)=/”๔ต๚. หHฟํOp—mย๘%{k่ชv_ov5ส+‰^๑zผUืL><&ยิ1*Gvใw?I8pdฮ9ฆ$H !ฤ$H !„B,…RฦNvีด0ตrrด‡ ส˜bŽ ๗:wŠ่ๅฏลi\)RzแK”ž|ฎk'ำN๚ํjoAฌ‡ฃk%HMˆ$pRญจH•hฤIdภ๑์ืŒA็Ž?Kๅเ!'u฿๏ b)๔X/ฅ'‰๒K฿ชฟํ2+V^๚6…‡?]๓ฏmZƒื~5ั-ฏว]~ขcพ IDATลู#ฆปm˜:๚8z่๘Œ9ฆŒ๑%H !ฤ\g(ค„B!ฦโฉ‰+j7ณŠุีo#ฒแTบerด‡ ส˜J†‘HSศQ|๊๓”_ (ต8O@{ีกƒ๔;'ำnƒิะq๔๐ฑฺ|ฑ^ 'ฝlž0ฅัใ่ nำj;Bjไ ล'คฒ{uท]œL;้wnำLฅ@๙ว_ง๘่฿ืฯ~ีฒพ:b๊>e—aซLPถaชk7~ืc„ร' ๔e„”BฬC‚”B!ฤYิ eOPnงฉรฮ1ตVœTหTภ BŸสกvnŸ—™งฆรA๓Zา๏ { bู>ipั็๚‰/:Šำฐ IขโiœDธSaสn=ึgƒิ‡๊๎=0;–_2ลวก–ฃuสซˆnพwล–ท๒๚„ƒGฉzฟ๋1‚แc4ฺ:ๅP!f•HB!„X‹ค&OQ‘nห:ขW฿Odอkpาญ œษ๏0…ฑ'๑ปŸย?ŒXป๚ณ๕ฆึ ค฿๙แคZ0ๅ1๔ศยมฃ๕ฑฃ8Nใrฆb จD#ส‹25บ&8๓ฅง๘3v{ิษ9ฝฒฮฉj(,=ลบพ5ิm€ท๊Zข›ถแฎธbV˜ ป(๏}่ไถ_๋”O@!„˜u6"AJ!„baิNš<DEธ-๋ˆ฿๒๓Dึ:ใซ&(cฦ๛ z๖แw=ŽiL9?๙ณตฆๅ›ix๛Ÿฃ’YLq=ฺCX๋#คฮฺ^Ÿ;ŽใแคZ๑V_g}โ] ํƒž}T๖่c5ฆe›Hฟใ/p’Mv๒งฟ@้น[2๏qw๙f"ซฏ'ฒq+n๋†‰9ฆ:ๅP!f’ %„Bฑ@j9HE.ป‹ิๅละ๙A๔hNบ งaูิ7้=ฺƒโ9ฃOœ|ใ—&N+ฉฅ0ๅu@๚ญŸดOฅ+ฃsgะน๕zสF๒Pฆ<ŽฉPฑ4*j'ี6AS&่=€๐‡TŽ>aPsKโญุbCa"ƒ)ๆ(>๕ฯ”_๘า’{ฏ{ห7ใญพศ๚[!ภ[ถนS>…bึัM‚”B!ฤยจ้RWG๊พ฿ืC็NQ|๚_Žฟ้ฝD:n@ลงพY‡่ั3๘วŸล๏zœเฬLฅ0qzI-„ฉศบ[IฝๅQ‘:?„99Uงg์ส‹น์.ป๚sง1~PvR๚hข:วฟ\ S๛๑๏ขาต{Z˜Zmใญบ–๔ŸBลา๖iŽO>H๙G_[J—W3ึฑปl* แงWง| !ฤฌOL RB!„ ฃ–ƒT์ช7“ผ๗7ภ๑‡OP๕ท๘Oก’Yผe›‰^๙&"ซฏ?kฃpด‡เฤณ๖ibง\3#ฆ"ท’zำN๘99]งg์.*09วW˜;‰:(T"ƒ“jEล’เฦPีง๒™ ‚ษ๔ย?(•#ปj"LEึผ†ิ[@E“่ ฅ'คผ็›K๑2kr<ะผ}Wง| !ฤฌOJ RB!„ ฃฆƒิตo'นํื@9„Cว(>๒w๘OM~I6ใ.ฟœ่–7Y๓T,=๕รFฃGNใ{šส‘„g^ยๅE]ž้sb้๑~t๎4zฌง>wวลIถเu@8|; އrLขขITฒ ๅล์S๙œ`์ฤ๔๙!ฆบร?ดkQ็Šฌฟิ›ศŽ\๏ง๘ุ?Pู๗%พ— %„s“ %„Bฑ@j6H)E์บB๒žŠp หฉใฯž๕ญNชwลbWผoอkPัไ๔Kot๎•ฎว๑>NุณoัยT๔ส7‘บ๗7ํ-ˆc}v„ิXo}๎8އำฐฏ*๔๐qยi”™๑m& Q‘„ Rฑ4N<ฎŒ_ชŽ˜:‚฿๕•C;!๔'ทBM„ฝ์n’o};rmฌโ๎ฯR9๐ƒ%พ— %„๓œ~HB!„Xตคโ7W[P„‡(<‚S/ฮ๛#NชoีตD7฿‹ท๊zT,5œp๘~ืฃ๘GŸ ์;8ํVพ…ปๆ~;โหqัฃ=่‘S่๑๚qงฉoูๅ„Cวะcฝ(ว๓Q^•ศขโ 8ฑ†j˜ยŽ˜ ่;ˆ฿กำขแล15cไฺ่Š~–สก‡—๔๛^‚”Bฬs๚!AJ!„baิlr<โ7 ‰?@ะ{€โรŸ&8๓า\งLNร2ฆ6mรkฟo˜v%ฎ s'๑ปว๏ฺMุwhมFLลฎ)’w ”šœ?J็๋sวq"ธญ๋q[ึvฃวPŽzู3:DนQ{+_2‹M3-Lๅ‡z๗แ{ฟk7ฆ46็6พfŒ\9Maื฿แwํ^า๏{ RB17 RB!„ คfƒ”๋‘ธ๙็ˆ฿๚>‚3/Qx๘ำ„ฝ^๎4’™ajy5Lƒท๊Tlz˜2„นS๘‡wแw=J8p๔"‡)E5๏ž๑ฅsงGNa ร๕นใธถMธM„ƒGซAส9งuat0ฆœx#(๛ณ&(c Cฝ Ž?CๅศnL17๏v~ตฆ\ณ“็ฟ๛ษ%พ— %„๓ก$H !„B,ŒZ Rสฟํฤozมฉ)์4แภ‘s๙iฮ SซฏทaชšYท๒ู นC;๑ป#์พ8aสq‰฿๔žษ_แ๐I๔ศฉYกฅŽธQถธMk์๒ ta๒ƒpNAjj; œศT˜Jfซ}taˆ ๗มฑง๑ปG†ๆฮฏT์บw‘ผ็ใS“็?้9็*[J$H !ฤ9k2๘Wฆโ7พ›ฤึ_e'ฯ/M8|๒•6f„ฉL;‘ต7ูp;๒-gฯ15tœJuฤ”:Ž +ฏ~yf๘ ‡บันำ˜๒X}๎8^ทe-n๓:ป<Gะ๙กWคฆถ“ั!J9จD•nลIdง} ๓C„ฝ๛ํSวžBœ™w;Ÿซ๘อ?KโŽูๅ่;Dแแฟ!8ฝgIฟ๏%H !ฤOุฃiœl;nหzป<9HM0Z9ฆRอี05kฤ”_"์;€d7‰็f…ฅณร”๒b$๎0ฑ๋ํญ”ฏl๒๚#AJ!ๆ9พIB!„X5ค–“ผ็ใD6n ผ็woLi๔bž†2#Lตฌ#ฒแN"k^ƒบมŽ˜ช”ํˆฉ}฿ล๏ฺฮ‚็_žT ‰{>>ุ๔๐ ‚#–๋rฟQฑค&&5๏?‚)^ 5มhBกRMจd NrฺS๙&ถO*‡~Hp๒Eย#ฬ5JJE$ถฑk฿ผฺษ๓๋‡)!„˜็๘&AJ!„baิlสด“ผ็Wˆฌฟ €๒‹_ก๘๘?bส 1 ๘ฌ0ีบศฦญD:^ƒฒ๖์05ะEe๏C๖ฉ|…a0๚์ๅiXf—งุยIยพƒ็u_Mฐวqฒซp›ึุๅ้?‚.ๆชGM2:Nฒษฮ3•ศ€ใN}=ฌล?ผหŽ˜๊;4c๛จXŠฤึ_žผ•า๏ฺMaืgf=ฝo้‘ %„๓฿$H !„B,ŒZ Rnำ~…ศš›(=๗๏”žฆRXศำRf„ฉถMD/Šืq#n๓T,=๙=ฦ/ู0ต๏ป๖ฉ|…ŒŸุยมฃ„GAืiJdp2ํำ‚ิaLqd๚ ฅeย”ยIdQษ&œDธSaŠ0 >Fๅะรวž&่‚ะGEโ$_๛๋Dทผธะ“็ื. RB1ฯ๑M‚”B!ฤยจู ีบไ=ฟ‚ท๚zJฯ”ž๚gฬขL>3Lyห7ูtชkqณ6L)ฦ`*ใ๖Vฑ฿งrไัษ[ ฆ~u2ฐฝะน“็4TMžฐ'špณํ8ูี„}ซฃืww2a(œD•lฒธ‘้฿aoต<ด ศ#˜ržฤœœซฒ๛{{ ๆ&AJ!ๆ9พIB!„X5ค–mฒAชJOฅงฟ€ sฮฅ9ยิๅฏ%ฒ๊:œL;*šดท‹)๔กฒ๏ปT๖ทi ษื:^ว ง~„๏ฏ฿ •lถA*ณ 0„ฝ1•<‹คฆถ }ภฑa*‘A%›Q^tฦw‡]๘วŸลkปlrป”๗|“โใ€)ไ–๔๛^‚”Bฬs$‘ %„Bฑ0j5Hy+ถธ็ใx+ฎ ๘๘?R~๖฿0aฅNW™ฆV^E๔๒ืโต_ƒ“Y‰Š$ภq ัๅQ‚“/๖!ฒvผ๖ซ๐=moq3a]๎7Nช'ำŽ“ic๚ยขฉณทฯD˜RัสโdWUoตฌ Œ Q^ €๒K฿ฆ๘ศg0ๅ’~฿KBˆyŽ ค„B!ฦ๐_รฺZ{]ชkH๕1ๅ›(>๚YJ/|ยZQ4+LญบŽ่ๅl˜j\aร”ใ—1ๅqT$f'DวฮUDX™s๔zเคpWโdV‚ัฝภ/ิุซœฆ*–Fลา8ฉ–™aช*์;D๑‰ Nฝธภ๓•-, RB1ฯ‘C‚”B!ฤยฺqwง2v2ต๒šผŽI๕หธm—†ยรŸกฃฏึ่-nณยTวD7฿‹ื~5NชMT+“O็๓?‹)ƒฎำR้eจL;nใrะA๏AŠ5๚j็1•h@ES๖้|ีH8A๕แ}‚สม$8บ@Ov\Xค„bž#†)!„Bˆ…•ฑ-ซัk%LEึBb๋/แถฌฃ)์kส{พYW'ฒๆ&ข[^ทโJTCสšรศ”FGz0ลฆฆN…ฉ^žำฐ'ณงa„A๏~ห5ชงญ[Sืh7ณ?{—ื๙AฃSู๛ยกcK*LIBˆyŽค„B!Gญ„ฉศ†;HlEฆ5  ?๘+ส{‚:@8|โฌ๙คj;Lู๕Vเค—aย a๏{ b}\nLฎ[S)โดฌรอฎbยŠ ‡ ะ…!‚๎ง(๏๙แะq;y{_ฏHBˆyŽค„B!Wnวถฌ1fŽ๛ล๘๛ัM๗ฟCธMซ!๔ษฆฒ๛ิร่ก9—็Š๛H๙œt›F‰ฯมT ่ฑ>ยแใ๚ณๆ•ชอ0ๅdVแ4ฎภIทb‚ฒ Rฺฏปํbทyœ= WŸศCESเz฿‰$8๕"ๅ=฿$์?\ืaJ‚”BฬM‚”B!Dศํุถฮำนะa*บ๙u$nœL;&(S๘๎_ุ‰ภ๋Tt๓ฝ$n ]žr=ึ‹Jdpp<ภ`ส๔่iยมใ`fฯ•U[aสษฎฦi\Ž“jล๘%ยพ5:ฟืห3aˆบ' ส{ฒ“ž'ฒ8้6T,^ๅFช?`ะลa‚S?ขฃฏ๖ฤ๘ฅบ›œ^‚”BฬM‚”B!DY่0ฝ๒M$n}Nใ Œ_$ะŸโw=Vท๋/บๅ$n{ฟ]žJยPั+฿„ทl“}โ›r˜ Sน“ƒ](ิไD่ีSej!L9MvฉT3ฆR ์;8๋–ร๚`ดถ๋?‘c๐ปŸุ‰่ต†jœRฑDSaJ‡่า(มฉฉ์๙A๏>๛Tพ:นŽ‘ %„s“ %„BQฃr;ถn3&ฺ‰ร=๓๏ฤฎนŸ๘-?‡“nร”๓ไฟIcOืํz‹]6ป< ห0•๙o}@Eโx+ถูp'nFT4m”1˜Jžp๘$aa”๋ีT˜ršืโ4,รI6ืูwจ.ƒ€z*‘œz”Qด ่ตถฃฆ’YT4Y Sีฏ๋]!8ฝ‡สพ๏ฺŸฏj~™%H !ฤ$H !„Bิธ‹ฆbืฝ‹๘M๏ฑs•ฦๆ'NพPท๋+v;‰฿๔^ป<ๅ1ฦฟ๑ };๒ฦq1Aฏm#‘uทแถmฒฟM˜า8a๎a฿a;Bวq}yๆu8 หQษฌ}}ฉฯ๙ฝœึ๕8‰,„>้=Vlด—&“หeรT 'ูlฃT$†rc6๊"่oริ๑g1Aํ>uP‚”BฬM‚”B!DธXa*~ใป‰ฝๆvN1ว๘ืˆเฬบ]Og/ฯทฃmฆzr<ะ!nห:"ทโถnDEโSกAแsฦhงs:I๖โ nหzข—…ดฆอ#eสc„Cว1ลภTGN]n๓Zœl*–B็ะƒณžX'ั4ชqN"3m.ฌW๗C๚จh'†Š%มูษ่™ฆz๖โŽส๏-สญ|ค„bžใ‚)!„Bˆฅใ•„ฉไถ_#zล๋Qฑแ`7c_๚ML!Wท๋ นํืˆny*š$PฟA*žมiXnoฅ,ๆ๛T'4ฟPื#ช:b*…Š7ุIะใี๙ร ฦ/ฃว๛โw?๘aป]/2 RB1ฯงถ)!„Bˆฅ+ทc:cL'Ž๛๙พ'๕†฿%rู(/Nะ{€๑ฏฮEฝํbKฝ๑๗‰lผ ๅลz๖QฟQ‘่๙&๔งยิ๚qณซgสW%์F็‡PฎwAFLน-๋pš์$๋:?€>ม…‹8 ฤ€J6ู[๋โvr๖p ๋"…ตj˜ŠฤQ‰,*€kœN&(cฦ๛ zœx–ส‘G1ฅ‹7˜)!„˜็ำZ‚”B!ฤา๗ra*๕ๆ?"ฒ”%8๓ใ_}LฅPทหšzห'ˆฌปๅFฮ์ก๘ฤƒฏz„ิl& ˆฌฝฉฆVอผ•ฏ4F8pฤฦ +_ŸNหฆ”E็๋4HTช'ŠŠฅ0๙ก˜œ]ู[๙"qT"ƒŠ7ฺSี‘m&ฌ`ฦz๖œxŽJื๎๊œ`zั%H !ฤœŸาค„B!.ี0ตว}วฤ—~'๑ึŒr\‚S?f๋ธ ท2],้๛oอM(วร?๙<ๅงฟ^๔ข-(วล๋ธศ†ญธ™•3oๅซŒฃว0ลtiโy ทu#NSส๑ะ…!๔๐I@ืี61Zใ4,วI7ฃ")tapเ(สqโ’ฃC”CลQ‰ N"สฉnร f| wม‰็๑>ฮ^ธe— %„s:KB!„ธ๔ไvlfLด‡{า๏๘sผŽP8๘'žcBฟ^OoIฟ๓ฯ๑V_o—็ุำ”Ÿ๗‹ค&ุ[ฤDV฿@dญ8+ฯšcJ๕bJฃ่า่y…)ทํ2คpะลat๎ไข<-๎Uญญq2+q’อv.ฌ|5Hน๎‚๎Fk”ฑ“ž'28‰์d˜"๔ั๙{+฿๑g๐=๋{๕ห.AJ!ๆT– %„Bq้สฏปทฅ๕W‘Uืc0O1ญO‚๊๓ไึ‹‘~วŸใญผƒฦ๏zœ๒ฟŠrฃ ๒๗MเฤRx7โuX15๓V>=)ๆะฅ1~าH4งคVกPvR๓ั๊o„Tˆ›]J6ก\{๋a8ุ…r#‹ฑ—`ŒA9ž<™ลI4UŸ๘่$ู่W Sฯ วz_๙ฒKBˆน?%H !„BB›1z‡฿๕ุu๙‡>uzŽจbiค–mฦ˜๐.ส{Z๐๐aดฦ‰ง๑V฿€ท๚ฬŠaJ—F0ใ˜B]Ÿ?L9nFฬjŒ ํ(ซ๑๊m)ธMkชAสณOป์Fy‘ล[0”rQฑTบ'ž™ Sฦ  Cง๗{ ิํ่ด๓]v RB1๗งฐ)!„B1กฒ๗กไฟ๓—8ฌญวื๏$›IฝO๑ฺ6bBŸสP9ธso ›bŒม‰7เญพHว 8 หf…ฉQฬh/บ˜ร”๓–g7‚บa*HๅNV'ฎำ •jF)ฏ… 5ใฒศgผ•jž9bสtq˜๐ฬ^*Gv๖ ์>}@‚”Bฬ๙ษ+AJ!„Bฬ–q๗Œ๑๊.L9+H฿)ๆต˜ Le฿w๑ปƒ™<{~F‡ธ้6๖kˆt\“^6mŽ)ƒ.Ž GํSฆ<aล~ษ‹แ6uT—งB8ิŠ&F_l&๐q›ืขา-๖ึรแเฑ R“—G๖?c จdNชe*Laะ…aย๘Gv๔์#<๚“—]‚”Bฬ‰+AJ!„โไvlหj๔vgGv๛ฮา_ๆปทWรTฆNmq›:HฝํฆL%OyฯทN>_3ฏะh›Y‰ื~ สซpฺฆFLUoำ#gl˜ ส C;Bชy-ฦ/๖ึ~dทeNชwฯ's IDATc4&?D8|l‘ๆ:ท} *Zฝ•/ู<-L)๔์ว?๒ม™ฝ/ฆ$H !ฤ<Ÿดค„B!^DˆRฦ>f4#F;.…05็๒ืhDp6’~ห'p2+1ๅqส/~• ็ฅš|ญNใrผUืแญธ'ีn5L้=ฺK0pSชNŽŽ๑ g๖ข\ฏ๎๖!Tp[6เค[0:ฤไ ‡Oิอฒจd3Nชkœฆสy‚žฝ๘]ป N๏!่:{ู%H !ฤŸญค„B!ๆvN!FยT ู*ผๅ[Hฝๅqาm่bŽ๒‹_&์;Xรgใnฆทผ[์Hœ‰H่โ0*GES˜๒8มษPฑTํ;&๐q[7ุRaS&>นhs{๗๋7ฅTช'™Eล@MjสyยพTŽn๋Fคาไญ‰j‘็๖:๏ๅ0ีง๒%›P‰ Nผqฺ\`ี0ีˆสแ]6L ว% RB1ืกO‚”B!ฤ”W=™ทๆ˜RA็%ฆึUริ๛kโ9.‘ŽIฝแ๗Qษ zฌŸาs†ฮฌฃณsทuส+q.ณ#ฆฆO~>>ˆ>Ž }Pn5่ิ๙ผ รฉR•"บ0ˆํฉป 5น<ฺ •ศ Yฆฆ~h"a฿aฎGฉt?๑@ๆ็?ื)ŸฎB1๋'AJ!„โ"ฬn 0aˆr#จD#*ˆJdง?A๐ S>m…b& RB!„ธ$]๔5›ๆEฅ*ณน๔ืํึmฦD;…bึัA‚”B!–ขšQg]น†ŸSJufท๏์^๚ๆโ„)MปแงI๚~PŠ g/ฅ'>_ฟgœฆ’๗*ธzฌ฿)ข\w๒L่ƒ๒p—ฃb จhๅFํื‚2„๛dพ  S“?ปPaJrซA*)ๆGฮ@Jy^o๋ย0ใ฿ค)!„˜๋่ AJ!„KInวถ๋qvิMˆ:๋ ๖า SC;๎๎TฦŽCๆ‚œุฦRฤoz/๑›~Pง~L้้ฆฆ&S:ฟ}งi ษป?Ž‹๋#:†Rjฮeš˜PiXŽŠ7‚ณ#ฆ”0~*taSฮ/`˜Rเxธห/GyqLq˜0w‚โ’<า…ใ฿~@‚”Bฬut %„Bˆฅ ทc:cL'Ž๛ฅq%{i„ฉŽmY~!ย”Š7ธๅ}ฤn๘)‚ฯQ|๚ (ืซ๕ใ6ฏ#ฑ๕—@)๔hฏ RำFGอล„!ส๕P้V๛DพX#ธ`0-E%oรTฅ0m\ฌ0ฅภเ.lo5, Žœ‚ ผไ?—tq”๑o}B‚”Bฬut %„BˆzถไBิYWดฆฮ๙ฤ6‘!q/ป๖ํ๘วžฆฟูงะี#'‚ฒŽฤฒปยhแ๐qิ9-ย่ๅxจT *‘ม‰ฅม๑ภLPฦ๘EL%ษaโE S (๎๒อ(7‚. ฃs'!ฌ,๙ฯ']c›,AJ!ๆ::HB!D=Z๒!jฦU-#F;œูํ;sK|ปf1;^ษvu’Mฤ๏๘0ฑซ €๔qส/|&'๓ฎ3nฏํ2โทฺUกGฮๆNN›œœN๗1Z[๙Rอhฤ‰72Œ_ฦT 6L†0~้"„)^ oูf;Va;กฟ๔฿บๅ<ใ฿๘# RB1ืัA‚”B!๊ษ%ขฮบบฝคยิyog'ีBโฎ_&บ๙u€ม?(ๅ=฿จ฿9คoลUฤo~ฏนS่‘ำฏ0ฐ)Œ16L%›Qษ&T,5๙U”0ๅผง0Œ Š(72๙ณฏ.L)ˆ$๐–oๅ  C่ก`‚%–5ๅc฿๘C RB1ืัA‚”B!๊$Pผโ‘3KŽ„ฉ99้6wŒ่ฆ{CๅเN*๛ฟ u{พ๋เu\OฦwๆNกGฮ œWุชqษฺ0•jAEโ“_5ASว”ฦl˜ ห L)T4‰ป|3 0๙!ยแใ`ย%V5•"c_ RB1ืัA‚”B!jๆf—wฆ฿ท.b๋6cขs…)'ำN๒ํDึฦP๛mรป๊vY1D7n%vอ่แ“„ฃ*HM^ุ๒b8ฉT";kฤT Sทqช0„ ๓Sฺ@,=ค ร่มฃ\œ'๚ีุ6๔หŒ}ํ๗$H !ฤ\G RB!„จญเ !๊œOไœ†ๅxํืYs#nำšc*‘ํTฑิƒK?9;LนM$๏ ผีืƒั”๗|“สมขผh}.คึD7฿K๔ส7ู>‰=s‘&iWLL>๎คšQฉf”;ตLPถฃฅJฃvฤ”>0ฅu5Hmฑฟซ0D8ptฒ…-e&จ0๖ี฿• %„sy$H !„ขŒ}แ#Yฟ๏€„จŸx๖ฆPัNชล†จwโ6u โ”ล ~๑˜๏๏t6=ธิWGnว0ฦ๋ฤaญผ–ไ}ฟ…ท๒*ค^2•?Dลำ๕นpa@๔ส7ฝโ>๛ฏร'ะฃ=x„ิY;(<;ว”“jืช +˜โฆ8‚.ไภ?1LญQัค.€ฐท์IBˆK๛”F‚”B!ขอ/nืนSฑง3ๅ=฿ดOณฮฺส‹ฃ’Mxซฎ%บinv•}Zšฦ/ข๓ƒ่แ๘'Ÿว๏z๒˜=ั™พ๋มฅพzr;๎€ำryg๒ ฟฝึ[พtH้๙/R9๘œdS}พ/BŸุ5oฏNาแะq๔X๏ER“;œ Sn'Š“l™ฆ|L1‡) ฃ‹#`ยyริYAjด‡0wฅ–~‘2aภุW~[‚”Bฬuค‘ %„BˆEผ\๛จN`-ฦ`*ยม.ฎว(๏๛ฆ“U„ืรI6แuHtใV–uvฎŸ‰”ํผ<น“๘'žล?๒˜ฝตk‚ๆaฅ*ูํ๎\๊k+์?ทํฒNtฐถ๔ฬฟR9๘Cœ†ถ๚|w>๑ ‘ wฺe[ะ U} ZุkฤIทฺ:žช#ฆ 9L1gGLaPฎ7ต๏b0aˆŠ%๑V^mwวI๔X—ฤRค„b3 RB!„Xh๙ฏม"๏้ŒฌฟmญJdf_cสใฝ๛๑ปง๒าท1aๅR=UรI5ใญฝ™่†;lˆJ6W็DR“ฃTยI‚๎งจ…๋ŸBา SYB{๑ษฺ๎™q2ํuน&๔‰฿๘n"๋n'HM-€ S m8‰&˜ OajSฎ†)=ฎŒQัิไฉpฐSฬ —;ุ่ฑ/–)!„˜๋,G‚”B!สไ|?žทึm]›YEdำ=DึˆŠ5ฬfขK#„=๛จIๅภธFTLp’Mx๋n%ฒ๎V–u8ษfT$Jat€)ขGNใูmCTaย๐ึั%ฆŠ}ถด็kฟๅ5m๘uOี฿DRกO์ฆ๗Y๓๛ฏCว1c=เธ‹๖’l˜RจxNช'ี2๓๕„!บ0„) ก‹9ะ6:ฉDf*H๕ฦT  %>6Z3๖ๅ&AJ!ๆ AJ!„๔‰งg|ม๑๐–]†ำด–่๗แญุ‚Š&gฐะ๙!‚ำ{จ์6๑g—๔บrR-DึŠท๚z–ต8้6T4eCT่cJc6Du=Fๅ่ใ๖‰g~^ษ9%ฆr;ถeษฌ๘=7ู๖๑บ Sa@–ŸณO ยกc่ฑพE!Uฝt`"xN„)'‘E%›ๆSล!๔h/ฆR@ล&Ÿฒ๔์ฟ่%ู'AJ!^ๆจ"AJ!„/lfLtืฝ์7:ฒMธห6ป๚m8M(/6ฒย=โ9*/}^ิ.!“#ขV]‹ำผงq*šB)ฃงBTp๊E*‡A๕c*ใฏ,Dอฆรฯ)ฅ:ณwv/ํq:•j3งq๙{Tผกๆ_ฏ Cทฝฏภ๊ฆว๛1HM^B03L98ษ,*ั„JfPntj‚2ฆ0 Jแ4,มษ0ก_หฑะฦพ๔›ค„bฎฃ‰)!„B\๘ ญŒ‰vโpฯy`uฤ”ท๒jbืฝ'ฝlฦ<5`0A=ึKpYJ/|;Y฿'cฑ4‘ wโญผทe=Nร2Tผๅxำnอ;Cpz~๗่ฑ>t~ฬE]"aชฆ’ธƒี‘E†pเ(:?XC!gV˜R.N"c'Ofg„)Œ๊S๕‚ำ{0•๑“ฃ/Uค„โeŽ"ค„Bqแ.๔_aˆšอ๕p[7Y{3ฑ๋…“ศุGะOปธ5~ับึ$ฅ็รN’\?ง`6Dญฟ oูๅธห.รi\‰ŠฅQnคขช#ขฮผDp๒Eย)๔x฿ไœ<•„ฉฺ`4‰?„ป|36Huก๓C58ฒhพ0ี„“lš•A็‡ะ#ง œ˜Cj้^HBˆ—9zHB!ฤซฟฐฟ@!jฦ.6L5uดุu๏Bล’S_ณW{˜Jžp่8แ]”u;ŸRอžy)T"Cdีuธห.ว[พ'ปzฺˆจSC๔๔ผDpfฏฝMkฌwฺล๛ฒaj{v๛ฮRวพ๐มm&t>ฅโษ;ฯšรl‘%๎๘0ne` แภaLqdrคQ ๎เฬ SN2ƒJ69ฆฆ t~]ฟ\นฅw]b Œ}้7$H !ฤ\G RB!„xฅ.|ˆš็"ืuq[ึป๊-Dทผ‰ฯบ๊ำ˜๒8A฿!*๛ฟOe฿wj์Œห†(oูๅx+ฎฤ]ฑทy *ึ`GDU_ฟ9Mะณฐ๗a๔h&ฌ,๎kืŒ์ppv,๕05๒ู๛ทaขŸrฒ+๎ฌSŠฤึ_ฤmYFงำ•ฦf4ูฝฤ`z˜Rั4Nถ'ู|ึwšฐ‚) ฃว!(MฟKfŸ’ %„/sด %„Bˆ๓•ฑm1ฆว}‚žธDธ+ฎ vๅ›‰lธcึ๙ h.ž~‰๒๏แy๔ฌ ไ…พ0w’Yึ vDิสซp›ืข’M3Cิh/a๏>‚พC„ฝะ#g?Dอv …ฉŽญH,๛7ป๒๊E Sส!ฑ๕—p›ื‚ ๚A%_O—€AWŠธMkp›ืุงf–ฦPฎ‡ŠMญ[ใ—0ลœ-(.โ{๖ย’ %„/s” %„BˆsฟP_œuึ L2k'>ฟ๊อxํืฮบ•ฯ€ั๙!‚S/R๓M‚S?Z๐ q•ฬเ6ญล[พฏj๛ไผdผ่ไญ†fฌŸ ๗a!‚ำ{GN/ฮญy็ใ’ Sw€xห'ฆ๖ŽE SŽKb๋Gq›Vƒ๚_จป๕hย`rย~BŸเฬKฟˆ“iวiX>cฤฃ J“#ฆLPFฉ๚Sค„โeฮ–$H !„โ'_˜ืFˆ:๋z=ณฏbWฝทํ2T4มŒ0†่๑~ฯR~๑+„]ไ*ˆ›]…ป ผีืแถl˜ข ˜๑‚C„‡ Ž?gC”๊kงจ†ฉKแB{2Lตญ๏P^tแฐ!yืGq2ํ†}ชฃ‡๊‹ั!ฒหQ‰,มฉaJฃจHยŽŒงQ๑ ส‹MŒ_ย†ะ๙ALPฉ๋05๚ค„bฮs& RB!„˜Bผ6CิYืํ-๋๐V_O์๊ทแdWอธฐƒ }๔ศ๎')ฟ๘U๔่™ RoภI/ณ#ขึ„บ'ู„๒โฃม/ขว๖ฦ๏~Šp่8u[’ๆ˜RAgv๛ฎ—๚๛aไณ๏๘ˆ“Y๓?U<•^?่ลlj\ }ย–๋nฝญ๑VlAลา` ~๗ใ`@EbvŽ)/ŽJ6ฃb)๛7mฤT%oGLๅ‡ํˆ)วฉป๗Œ)!„˜็I‚”B!fหํุ–5ฦ์จ๕5›ป|3‘57ป๊-จT3v4Kuฤ”1˜ Œ>Nฅ๋qส/|S~๕๓๑จX 'ูŒป๒*"๋nฑท&ฅšmˆย@ฅˆฮŸ ์=€฿$แเัฅทำ\"a*ทc[–ฬŠ฿s“mฟุaJE$๎๚(Nร2LXฉฉJญ4๎ฒMจx#่ิ‹เ—Q‘ฉัf6L%์๛6šBE“จHŒ‰นคLiฮ1Uฒ#ฆ—z Sค„bžใœ)!„BLฟุึ่ํสxqศิ๋rx+ฎ$ฒ6ขWพ '‘ืe*LiŒ_"์?Bๅะ)๏๙ๆ+˜ทIก"1TผoีuD6ฒ'ี ฃณ2บ0„>Aะณฯ†จธepัI˜บ@๋Qฃ6HฅZ0Aู)ํืแฺRธญ์-{: 8c;ฺษL~}ฦS๙"‰๊ˆฉด฿^ ”ฒsร•ว 8Š. bๅบ5ฟ๔ค„bžฃƒ)!„B,•5ƒใโญุBdใVข›_‡“lๅL}ฝ๚„ป g•—พMๅ๐ฎsบฐฦ๕pโxํW฿ผ'ู\ฝMPM>ฦ>ฬ$8cฎวป/ฝJsL){v๛#_Y๊๏ฆZ~๗BN|nย'Jโฮุ ๅ—{๗ƒ ๋๐Šร|บไไคๆAๅzgฟฟf„ฉ$Nชbฉj˜ชŽx ty Sฮcฦ๛1aeŽ฿U;$H !ฤ<‡ RB!ฤฅkI†จg: Iเถฌ'zล}D/ป•ศุั“W]ฬŽ๒K฿"8๙ย<ฟหAลาxซฏ#บ๙uvDTฒลVคL่cŠ#่‘ำ๘วŸกrh:wRv2อรJU:ณนฤ฿K๋Tช๕ฯœฦๅ๏นaสL;‰;>ŒJf1~ัސชว ๅx6H%ฒvคWฯ>œgพ7.Sa*@ES8ฉ๛4M/>9Gœ +”1ฅ1๔h5ฆ$H !ฤ<Ÿ๖ค„BˆKฯ’Qg๑(œtNฆุีo#ฒ๖&l4˜ฆtˆฮโw=Fy๏C„}ง~<ึ`Cิฆ{์dๅ้6๛จ๚‰UG๖เw?‰hW๕ฉy!u?a๙…$a๊ผฟˆผŽฤํฟ`CNฅ`GHีใ>ๅFq›:์rLŒ๔ามฬ0<๗—a*–ฦIตขขIpฃL<๑ะh฿>ฝฒ<Žํลhฺํ€‹O‚”Bฬ๓)/AJ!„ธด ํธป๓’ Qg๙8ธูี8™•ฤฎ};^๛5๖ษ_Sย=ึKๅะรTํฤอฎ"ฒ๎ึjˆZัสq1:œ Qวžม?๒ˆฅแ—ภhูัๆs)…ฉDห?;ูwพ’0eสye—“ธ๕}จDSฮฃ๊peธ1ๆ5จx#ฆR$์{พo\ฆยThรT2kฃTผa2>™ bรT%ํึD˜’ %„๓|บKB!. นwภฏ‡ตrคp›ืโ4uฟ๎]ธหฏฐ#žฆr„!ฦ/`"8ž}๒—๋M…จ‘3vฉƒ?ฐ!ช<^%ฮ‰ๆaฅ๔๖์๖/,ํ๗ึm*ฑS็ฆLiฏ*โท*ึ€)๖ฌฯ ๅ%pšVใฤ1•Aฯ^”z% 2-L้kฐŸวR8ฑp=ะ”0~SฮฃG{ฝจaJ‚”Bฬ๓ฉ.AJ!„Xฺ$Dฝฎิป๒Jโ74nSฬธp5SฅCti=ฺCpf/~ืn๔h:?do?ฏŒ?ง”๊ฬn฿ูฝด฿‡็ฆLqฏใFโ7ฝKcŠฃ‡P๕ค"I์jTผSฮ 5๏Q็วhƒo€Xoภ‰&ม๑์C *LฅhGL๕ฑXaJ‚”Bฬs&AJ!„Xชภขฮ๙„(–ถ“žoผ ทช๊E๋๔+Zฃ C๘]Sz‹่ฑ%D]0—P˜"๖yทฉฝใๅย”. Yw+๑ื *šฤs„‡ฉว"ฅขiœ์*ึสc=๛/Xš|‡pโ๖พXI€ใ‚ํhฉาจ S๙!ภ,h˜’ %„๓$H !„Kํ‚WBิ9Ÿy1ผuทเตmย]~นล‘ศฺงxM^0ฯ|"Ÿ)๔๎งฒ?ฉ์žฌฤ น=Yผๅ›?็ต_ฟ๙gป—๚๛”xห'็ Sz|่ฆป‰]S6H† ๛€S‡A*ึ€“Y…ŠฅะฅQย(วฝXอFฉxKู0ฅ” Sฅq๔xŸ T•"8๎cs‘ %„๓|bKB!–ส๎ึmฦD”uฌั๎๒อx+ฏย[q%n“ QxQ0ฦ>ญ+?สฑ#;"qฮz"_1Gpz•=฿ภ?ฌฌึW,าx+ถุmฒ| ns*ั๔9ศvๅEsK๛}[ Sm๋;&ž ว๚‰^qฑk฿Š&ัลบ๏p)*‘มษฌDES˜โA฿มA ผ8*วi\aŸฬ ti 3ฺcoศ ส`.๎oค„bžOj RB!Dฝ_ะnfLด‡{dmผชŠ%q[6ุ๘ฑ๒JผึีQQฬฤœ3c}} z๖ู[ค‚๑›Kdใ]จX’™a*@็๑=C๙G_#์?$ซ๙|ถHฤ†Aทm#สซq[ืใ$›ภ‹M„มณ๗Av^็ๆsฮ๎ฝo็t#gฬ”DRเHVฒdำดฦvูซ‘ึตฎ™ู0ฦlีฎ]ต;ณPีxw๕ฯjผฎ๕ฬ์he{g'ุ–-K'ˆ”(RL`‘นsบ}ำฮู?ฮEฃ@“ ˆะแ}J*ชิ$๎ํ๏๛}็<|฿฿;{๙P:๎กฬ_\ีbjๆ_}แะ๙มฎฒ๕ fv„pื็ศ์๙*ศE‘s›ฑUื‚n๊ฉตN‘Žž\Px_ฺ0)*ศบ๗ะุuux5˜ส ถZ„ธŠญ๎˜˜!%‚ฐฤ>@„” ‚ ฌLDD}€ Oฆฏu=^็Vž]x[ัu-(?ƒลBTยฬ‘Œž =A:yขข#Qย:ฒ2~^T˜ใช˜r๙La„x่*/{Li๒ส+3Œ.\ล๓๑;ถโตoภ๏‹ืพะ>ฝ็ลเุI’หo“ŸI&Oา–C๙‡งW๏wzžๆ๎฿ึAใฉ6f๖>Cธ๓35!5E2vzลEHYcะ ํ่ฦnT˜ร–&๏q+ฝlšิก๊[ั(/ผ๒1ี9lyโ 6*v1%BJa‰™)AAXYค“g๗W_ำƒั้็>nห3rAkฃ“iD็{๑;6ใ๗WQญdP(l\ฦฬ“ŽŸ"=N:zชvpอ๘`kAY2{Ÿฦ๋z˜ฒiŒ™นL|โ0•W•dโxญx๙>‚มG๑:6ก: ฌsทถฆ0ŠฉPJ ›FFคS—ส้ไ้›ž{ๅŸญv1e0๊?๑?wLณ๒3๎šฬ\บใํeทk บฑะแZ็ฦI'†๎ชบ๚^Rฐึ;IV฿žๅ‡˜j[šคโ*ง0ทๅuEH ‚ ,ฑO!%‚ +†ภAเใ6HวNQy๑I.ฟญฮษีYธž๎ ฒ IDATมษ4 ;๑:ทฌปฏ}“ซภ ฒ5๑Qม”&I'†HวN’ uญ=a๎ๆ^@๛่ฦN2;>n]ฟ8cสZla&ฯR=๚ทT_3๗šk/@ืทใตo xฟ{;บฑฎN'ULq S‡š4ฐ•ฅ[จLaขฟ๛ืข๑แ๏ฌๆหฝ๓ื๙`๋ƒสฯf:u[ž†4ZQฟƒ5)บฉะŽ r˜นฑšา๗๐=ฐฦIฒ\kv๙ภๅรU ุา4$ีšTpbJ„” ย๛5R‚ ‚ฐผ)‡<˜ศฏ๒{wตแฺ6ฉ’\|ƒส ุ้ilณ–[ฤTX‡ฎoลฺ๋Nฐ!ผŽอW[ม”‚ธŠ)Mb&ฯ‘Œ น๔6ค*Sk/่gะอฝdv,บฑJฝ@L%าั“DGš๊ต๖ฤ๓ัูftห:‚uเฏิ… ๋Pสรฆ‘ Š&˜๒”Q&yฉ&ฤงžIฮ<๗๙ฯ~c•_ษมไ๒;›ญฬŠ๒ƒ๕ฦmš ›๛jB*‹™รL • ฉ๗}oฦ‰&ะแ2ฆฒ ๔๗ื”งœSทvo!%‚ฐฤพM„” ‚ ,OฆํดึD๛_Vู2;>Mธ๋ณn๊›ฐHLU็ˆ‡^ค๒โ’ฮ\rU&kiCใgPนfผฎm„?vUDYืš—D˜าf๚<้่ โ๓G ญขฒP›DT%๕9tฎ<๏๊๚XƒŠ$—฿ก๚๖&>๙๊_ํฃย:ผ–~uฌ‹ส6ขด‡5ฉห์IcฌI0…Qle๖ฆDิuื?ฎŸ๙้šS3๚ƒญO}=่฿๗ิ-KิปŒMผ|?ชก๙ึรษณหBHอฟGcQJกฺั๕ญจฐ…a]ฆ<-Maใ ฤe>จ˜!%‚ฐฤM„” ‚ ,/ฎŠ(๏หื๓›zศ๗ยMO ปฎๆŸ€๛7๚ฅIโS?ฆ๒าฟรฬญ‹ๅจฐฟk;แึงๆ3‰Tญฬ&ถด_ธ๋๓lxd๗rS6‰g`^HNž[–ำญต(ช.๏Z๙๊[Y˜gส3ุาดซ่Kชฌ˜!%‚ฐฤถA„” ‚ ,›Cๆ’"๊Zผฮ-d๖ม†วn >LaŒุ่๗จพ๑-Lqb๎`4*ศโw๏ ๑ฉ๙Œจy•&ุส,fv„ไ๒[$็^ม&Tฆแฮj+PŠp๛งท<‰ส6]m—QsE๙&f๚ยjXะบกpำใ๘9 ‘หปj>k]€|a SwํOwจฝ๔ช˜๚แฏไ่๐๊พg<พ?๕๔๏.g1e“ฏe=ชฑฅLa”tjy ฉ๙๗l†Rู&7•ฏฎuAล”ล”ฆฐฅ™Zซi๔พŸcR‚ K์DH ‚ ยฝ>Tผˆบฟู}ฯเ๗๏ฝฆอค6๑m๊<ีทšุ่๗\สjุผ๘ผždv|บึšืแBล•ฎUเ13—H.พA|๎ืšํรบย&U@‘ู9‚Gœ [ะ„I0ณรDวพOๅ๕?c%OLTนfยญOฌฏu=ชฎๅgjBข๊๐qชELa„ป‘sfใ ษน#oฤ'๎7EL; )S#:Oฆ์ฺ‡[ฃย'ฆUL)N`หWฤิา‚U„” ยทXR‚ ‚pฏ‘nดปฒ4อๆฯ 6~„์พ/โ๕์Dyแb1WHGŽQ}๛ฏˆ‡^p๓ฏย-Ot.1eำฏe=บก”ยฬปช@ฅVะ•U51U๏rฆ๊Zิ”ฆฐล lTยš˜k3R‚ K]EH ‚ ย>4>u-™]Ÿ#๓๖ต|ฉbชZ$นp„สkJ:zUฌ\9l-c1ฅ2๕๘=ป uQM=ตpl—IDต„™#น๑นWฐi‚าmษ%บญZํฃณM„;?…ืฑๆX,ฆ’๑ำDoล๒Ÿศ็„>Aะw^๛FtC'„นซ“๓ส3.จ<*บ5JขZะฝ๛œญ-1๕ไW‚mŸฺrS6Mฎ )lMH]ญVเ•uญฉ*l@5ดนv้˜าvnUL-ธˆAXโฎ*BJA๎ึ!๑ฮ‰จkeAv๏/๎๚,^พฏ–/ต`โ[e–่๔Oจพ๖วค“็ภšซ‡ญe$ฆTX‡฿ปxํ๑๒ฝจl3ส ฐึ@Tv"jไ]ขำ?F้Zภ๛-Ljปซ่/฿Kธ“่–๕๓ญmตยฦUาัT_3ข‡—ืฦ1ศโ๗๏ซษมอ่ฦฎZ•š็ชิสณ˜าค›˜g“žiฒฌ>WWลิ~>เ๐ะ๊พ็ิฤิŽOvช…๎ๆ๕NSผึ๕่†vฌ5NTฮฏฐ ฉ๋พ n’dถUื‚ฮ5s]+_e[šํ1๛วญ)A„MEH ‚ ย>%u บฎ•ฬƒฟDธe?บพํบ‰oฆ<ํฺฤŽ|sYŸ+?ƒ฿ฟฟo/^๛&ผ|*ืŒ๒3XkฐQษ#$>๙ถ:ก“"+kฆ๑;ทl๛$^s7่ลm4Gr้-ชo~‡๘ฬO๎ํ[ ๋๐บถ >โึคฅ฿ษม+“๓*H*˜jัฤซW2uฬฒฝ6ฎ\~็oใฃ๓Wป˜*ลo^vื~C…ูเฎ_gc๐Zะ๕ญXc0…Late๛จซwY๐|Tฆ•kชต๒-จJ-ฯb*ณฟ๛ตฏ6๓ < Aฎู_ˆA„;วไก'mu-^็V|>๐k1™Ÿ๘ๆฺฤLqœ๊๋฿ข๚๖_aซ…{ท)๑3๘}๗แu๏ภ๏ŠnY‡ฎ…c_QvnŒd๔8ษนW0ลI@กย์ŠŒX“nมฆ'œ8\8‘ฯLy†ไยkT฿ษ…ืน›ีF*Sืพฟ~็ผถ NzกQQ37ๆฺ๑ข2ฆ:็ฆŽYณrฎSำ‡๖็3~้๗ฮํฯM1eลk@ืตธA ณ#ุโจUtq•็*ฆ2 จ๚tvแํbf‡ฟช›zสQแšง)AAธ‡ฟ'ฟbญอภryOมเ#d๎{ฟg*SฟHLู$ยฬSy๙฿?|Wƒต•โ๕๎ฦ๏ฺ†฿ตบMณ๒3n๚•ึผฑ“$_วF{MซสวV‹„;?Cธ๙ Tฆ๑š‰|)ฆ4E|ๆ'T฿๚้่I๎ค˜RAฏc~ฯ.ผฮญ.'ฺ๊5)ŒLกณMุ4คฒขDิuื_ฤิมXt RI3;Œ-Mญ.!u๕f^ˆสิปVพlำ•Ÿ|8(OFA„kn›"คAแv๖–Ÿˆบ–p็gศ์YWํไฎŠkฑq™trˆ๒5ษล7๎์&ฤฯธ๖ฏ๎ํN|ดot-/AึIธŒ™';Ir๙wต)ส V๕gศZKf๛ฯlxฬ‰ร…'๗4มฬ๘!ี7ฟ™แถŠ)/ภk฿่ไ`๗—U฿Aฮ<*cๆF1…๏…ุจฤrnอ๛ภื?ฎŸ{๙?$'Ÿ๛ว๙‡งW๏ฝj`ธ๏™ฏ๛žบ“ม็ึ‚ืถkฦฦeฬ์e—1ถชOXNL้l#dะนWA”'ค ย5ทKR‚ ‚p;wห_D]Kๆ_$ณ๋s่ๆ^”r5๘b+ณ$ร๏P~฿’Nœqงสต๙rxญ๋๑:ถเ๗ํY =ˆจโ้๘i’แw1ำ็ฑf๕‹จE‡๘$‚คL๖แ/แ๗ํEe๊ธv"_:}่๘จพ๚วุค๚แ^P๛nMฺ7แ๗๎v-“]ึDT\ม'0ณรฎ ส ฐๅ–๓tฦ‹)LTโ ฏ฿้นW™ˆฉ[ถเตo@e›]‹็ฬๅ{ฺ|ืพรฦธI{:€ด๚ี`รGส“Rแšง„)AA๘0‡น•'ขmย:ฒ*แึงXvoแD>‹)OŸy๒›T>”˜RA๏รุ๋Lะw^็VtCปQ0/=า๑3คฃวI'ฮ`MฒฆDิu‡ฺธ‚ ๋ษ>๘หx›QaŽEกษI„™๕ฃใ•kยk๊ม_w?มบั๙>Tถ้ชˆŠJฎ0ฑฅILiL,—พ†)LTโw๚_4ƒ?ี~ฏ๛๐bJาฎB*ำเ„ิ๔€ฟ†!%‚ฐฤSB„” ‚ แl5‹จk 6?Af็g๑{wฃย๚ล฿า„tโ4ๅ—๑ษ็ฎ฿\๘Tฎูตๆ <‚฿ตm>h^DUfHg.“ŽŸ"96*ขย:๙ ๔ฮ#x`ใใ.๓น*ฆ ถZ$พ๐ีื„ไา[ND…u่ฆ๛รkY‡ส6ขด5)6.A9)Uœภ”ฆ\›žp6MˆO=?’œy๎ท๓žฦjฟ๗บ˜R <ผฮMจ [™&บฐๆ>W"คA–xJˆA„๗>Œญ%ตx— ษ๗s„[žย๋ฒธM ‹+ครG)๔%น๐:x>*ฌw<?Šืต ุ‰ ๋œˆชต™้K$c'I.พŽ-Mกฒ๒AปU มภร>‚ฮ5ปvส+˜Sž&9๗2ัฑ ;6=ŽืฒU—w-‘ึbฃ’“O liSšu“ุธB|ๆงkDL=๙•`งฟnyข๓‰)/tRAฎVy~อU‰AXbซ)BJAnt๘Zร"ฺ๊อ‚Ÿ!๛๐ฏlx ฏuเšjœฺDพหoŸ1^๗Nฮ-่†NWฅ=W}Sรฬ\&=N|๎elyFDิmย&˜”ฬฎฯl๘ˆปฎืดZฺ4†$rาฐ–อeใ*ฆ2ใชขชฬคาšwKk b๊ฦืลZ”Ÿq~SžฦLžuำ็ึ"คA–ุcАA„…‡ญƒึ๊oˆˆบมฆ!—'๗่—A7u_|ŽIฑ6E)ดv:ี9la”d๘โ3/ธึผLƒ\ฬท*€ถ2 aŽ์}Oใ๗๏ปพีท็ปา’gM ี"้ฬEQท Wˆ‡^9•œ•?๐ฃรซ๛^YS;>ูฉ<ฦ“1เ‡x]Q~ˆ-อNœฬš๚\ˆAXb#BJAฎˆ({ํ}Yฎฦ{ฃ›{ษ=๖e‚‡Qนfฎถ๑X๗ŸคŠ™ฝLr๑Mขำ?†4F๙ู5wฝ‹[:ภbฃ บกฬ๎ฯ9 ไjหณ`ฌล'HGaซ%ทfศ~๐vbใ ษน#oฤ'๎7Wณ˜š>ด?๏m|์wฒปพ๐*ฬ^7ำšิๅ๕ํฯร–gHวOญนฯƒ)A„%v/"คA„ตŒˆจธq๐3x›ถ์ว๏ƒื6X›๔‹ค‡I1ณรT฿๘ษิ9W5ตฦฺt๎&ถZD7uโ๗์ม๋Šn๊BePฺฏUIฉkฤ”uแ๔ใงIg/CR]ฐ†ฒ7ผm๋ฒ†ฤTๆั/พ฿น™…bสฆ)˜”`๐ะ[ž%;นุaฏDH ‚ ,ฑฏ!%‚ ฌEDD}ภ Cล๋J0๘(^็ผๆ>Tฎๅ…W—J/ฮ.lT";E๕อ?วฦPaR%u๛ฐ•*ˆ฿ฟห๎ส๗กฒอnržMฑ•Z6T\F5tข;jqA8}‘ŽภฬŽ€I!uึiญ‰ฉŽ-ฟฌ2๕.ป,M6~”r-{ใ'ฏi%]ˆAXb)BJAXKˆˆ๚€… ‹ืต ^วtK?บฎๅgฐˆ+˜โคkŠJ๘๋@7uฃฬยใ8ถZ$~‡๊ซโrค$ะCaฃ"สฯโ๗๎ฦุ๋Šืบ•หปœk\ˆ์ษๅทH.4 xˆ`ใวะ]ตp๚+ ›ถ— ฟƒ-Mอฏ›p›ื-ฎ\|ใ๙๘ุ๗~-เ๐ะjพฯ†๛ž๙z0๐ศSfv˜ฬŸwฟiŠd์J๋5ต๎"คA–ุgАAึำ‡๖็ ๆ€R"Wใ&6~ฏ{~ฯ.Wี:€ฎk… &šโ fnœt๑้ŸNวฬ\kศ์}šฬ๎ŸญIฑ2ึ`หณฤ^ฃ๚ฺ?ท OธlTๅแ๗์ภ๋Šื6ˆฎoE๙Yฌ5•I #คร๏_8‚)ŒขณM‹+R”Gฐ๑cƒป5]No0ๅi’Koน๊+/@ฤิXวธB|๒น?9˜yเ—†V๋๏9๓๛?7˜}๔ห3๗โ—มb‹“คCาฒ'‚ ธ-‰)Aa53/ขฌMณ\‘๗ม๓๑{vใwn]$<r๎็qลbŸ&>*frˆtbW1บกฬฟDธ๙I'=Vใ˜Sœ >๗ ั‰gืZ๗ฮ-aฃ `๑:ทเwnqีj ํ.ดฐq37Fr๙’‹ฏป๖;/xoแง4แ–ง๐B็๒‹ฅ•I1ลqโ๓ฏBšึู3~x4์์^วfผ๖ ิุƒสฯ ญโ_|์กt๚ยฯ™ะาฒ'‚ ˆAV)3ฟ๗ู|—(๋‰ˆบฉsฒ‡ืพ ฟ{~ฯNผ๖่๚ถ๋Eิฤ’Ko‘ŽŸ"?J๏๙วzํษ>ซ๘๗ปJ๙j‹Mcฬฬe’ก‰†~ส’ฃใื06*ƒM๑Z๐:ทแwms•g™:สM3,NŽž น๘:้ิP๊ฆ+ฯlAšyเ‹๗ฃฒ ,*_Iาูaโกะูfd"฿ญฟTถ ะ ภo฿ ™:ื*Yš$น|”ไยkŽ;ุ๘ซzhต^†๘ฬ๓๛ฃc‡p๓ใ๗ซLšY~R‚ 7F„” ‚ฐบ๐ีBฬ ˆ‡^:\<าŸ{ูm[ า^๊ ์ตฌว๏แZ๔บถกฺˆR โ*ฆ4I:q†๔๒;$ฃ'œˆช>ะห๋"๓เ/ใwmuมๆjqจถ™ขz๔oHวOฃ‚ฌ|Žำโบฉฏk~๗ts*ฌGi›Dุ๒้ฤษล7Hง/b“Jญล๎^ฏR@e๊ษ<๐ห๘;PaŽลb*&น„™นŒM*Dˆ˜บ™๏—ส4ๅ…่ถAฎˆ[)` ฃุธŒ2kฬฆ0ซ/ั?ส8<ฝZ/ห๔กว๗‡ปž`ร#ปื‚˜!%‚pcDH ‚ ซSฯ๋บึX{ภฆQ3&มฦˆฯผ@rแ5โsฏˆ˜Zˆเ5๗บชจ]๘ฝ{ะ๕ํๆPJปส›า$fโ,ษ่1’แwIวN`+…๕ฒแถฟGf฿๑ฺjโi˜Šสค#วจผ๒ฐฦ ๕pำG7ฌf1%BJa‰])AaฅSหฏsวAฟ{๛€nDืๅม2_ษaJSDว@r๑ษล7ืด˜R~ุ…n]Oะฟฟw7บก๓5™:G:v’ไา›$ฃว?ดˆZ๐@A๖ฟOธใS่|_ญฝL-"ณ$—฿ก๚๖_AZ]3kcฅ^ว=x-จlณห฿Jlต€™พH2r 3užด0rหQ๏๛^โ ~ฯNยญOก[ึ_ณFWฑลqาูa7•ODฏC๛.ืหฆเg๐ZPu-๎ชE%lตI[žมฆษ๛Jืต#ฆžJฐํำ_ ท<ันล”)A„%v…"คA„•|ˆฑึ?ˆงts~็6ฝxmƒx๙uจบผ;ิ%Ulu3;B|ๆ'$็_!>ฦZj9R~U฿Šื6Hฐ๎ผ๎]่ฆ.TX็DTcห3คำ็IGO’\|d๘šw๓oHฃยzฒ มฆว๑šบOไ|~Uข7ฎ6>›ฆ`ท6เตฎGีต ผkาฺg๗2้่ าษณ˜ยศไเ๗๎"ฒีุY`51e 6ฎŽŸr!๊6]ป7#ํปI‡iŒ ฒxํPนฺ'.CTr๗กา6>ฐH\sbjว';WSฆœ)A„%v"คA„•xhฑึ?ˆf`๑กะCืทใwo'ุ๐ผŽM่†ฮซญ2IีŸ:Orแ5’ GHฦOCฏฝขrอxm๐ย๏ูn๊tYDJcMโฒlฆ/Œ"9๛ษ๐;๏V~๛ ฦkYGๆ_$xุฉ๋+Q (ฬ์0๑™็‰Zฎ‚•qฟaeฒžpำใ่ึAt] สฑึ`ฃ"ฆ0†™8C:v‚tf๘žH›DTw|š`ใวD>ฯc‘˜ชIFŽb็ฦืฏด^ฦ &k๑:6:Uห_ณq •ฑฅ 'ซ>dE›*q|๒_ญ๛๔;ซ๙ฒ๒Ÿ}-™ชยlฐ~R‚ K์†DH ‚ +…%Eิ ‰บพ ฟwมฆว๑;ทบ žL;Dง1้์0้่q’หo“\z3}WVฯล๒|Tุเชn6<ๆZ๓ปP™Š}ฅlf˜trˆ่ฤa’Ko;9ง4~๏ฒ๗"~ฯnTฎษตVบc8XK:yŽ๘ฤaโณ/ืฆมญศญส๓ฑT˜%ุ๘8^ บพ ๅgฐXˆสต‰†CคฃวœˆZญ‹ถR?Cf็gqk ˆ)“bสำตฯQดบ๘”/@g›PูfTฎ•mD)ฯ‰๏คโZ๔ๆฦnฉ"๊=ื!MˆŽ~w4>๖7ฟ•?๐์7V๏~>๓่—~฿๏ฬJS"คA–xœŠA–มไ‰งญ ฝฏˆบ/pbชแๆ'๐:ทึ„Œ๏าiB:u–ไ๒;ค#๏บlž™หฎลfฅข=”Ÿq"jำND5u_QWZภ ฃคใง‰O>K|๖e–O๛ข"ุ๔1ฒ{ฏs๓๕๙า˜tไ๑‰’ŒžจMƒ[[ฎZvYŠ ๋]_็–y๊jไYโKoaf/Cฒ2ดlฅ€ชk!ณ๓3๘}{ิธyyˆSลqฬ์ฆ4น,‡๑s฿ฑlบ.jhG‡๎๗ทILŒฉฐ…‘R๕ž๋P-xNฤิ @„” ยป#R‚ ย๒=ˆ<พ฿ฺ๐ š ‚,*ืL0๐0มๆ'๑7Aฦe'ก<ฌ‰Iวฯ^zห…xŸฦวWXล”ญ๑ฺ6n~๗NtsฯUe D%ฬุ้)ข“ฯŸ} ฬ๒อษ์Yย]?‹ื6xดทจLrแัฑ๏aๆ&–yฦ”ยฆ1:S?๘~ื6tC‡“iสรฆถ<ƒ™พH|แ5โณ/ก‚\-H|๙b+ts/แฮOใwํpSๅิีpzLJ:uŽt๔*˜ฦงœˆส4ข๋๒่ฆ7%๒Jkmrž-Mบฐrญ๏:ฌ%1๕เฏ‘฿ณ๓๓+-๘\„” ยOWR‚ ย๒;xuƒ‡^ถ k"ุ๐‚มGX๛ฐมy ึฆnฒๅทI.ผN:1ไ˜หพยCแตฎ'๕Y๎ตŠจฦ๙\—1sฃ$#ว‰O=Gr5lมŠุ(ฒ|‘pื็๐š{Ÿ[‹ญฬ~ž๘๘a๗EpSฒ ช 2๕ใu๏ภk์rEฺs"ฃZฤฬ^&9๑้็๔๋Vฤบ\ฉชณ•^็VยmŸภุ๋ไDอ‚|ฉt๊<6*aๆฦ!.ญผ’๒P9ืšง›บœ,ิ|จป)Œbซณุ4ญ‰จ{๓ฝฒี"ัฉ็ฯฤGฟ๓๋๙?:ผzŸ๛ร}ฯ|=่฿๗ิJS"คA–xฤАA–ฯAใฮˆจ๋~uyt};แฆแ๗‡n@g›k็็ฤUvŒŸ"=N|ๆา‰!ฬrmฏ}'ขถŒซบi๊vYY~ๆชˆ*Ž“Žž >๓๑ล#ุ๊ค+ญZEก2๕d๘%ยŸชิO๒œ IDATŸ/ฮถ37Nt๒Y’‹oบjœ{<๑อV‹จl~฿^ฎํ่ๆ^ท6ฺวฺิ šย(้๐;Dวƒ ผ0+nmๆลT๔Gฐ๑#่–๕ตVDภคุธˆญ–ฐี้ิ0+`€๖\>TึUEฉฐัU๊Yฺ๋+ #ุJkSิ‚๊ฝ{ญ‰ฯ๔ญ่ํ?๏DL-DH ‚ ,ฑ‹!%‚ ๛ƒลQื7๋ะ๙>|พ๏ฏษํฺ๕’ˆtrˆtbˆ่๘๗]ลTฅp๏^ˆn ๘1ผฎํx-จ\ตxY๋ช6Šคc'ˆ‡^$น|[žยฦU–OVิญ ห“}์+Nzไ๒ืd%ค3—ˆO>G|๑อEcwMT เe๐๛๏ร๏‰—๏ซญM‹j S!=N|ๆyWฅฆผ{.ะn๏:๙๘;๐ื=ˆ—๏Eu๎;e๔]žu-Š…แๅ|~EDe๊]‹^. sn๒a\ฦงฐ•ูZโ!ทพWkJLํ๚ทƒ ์^ฎbJ„” ย{ZR‚ ย=tCปห‡‰Jุ๊้ิyฬ๔Eขc฿%8ƒญ๏๕ผถ ƒโwnAทฌCืทข|—Ÿd“ ฆ8้ยสO˜t์fnฬ…ดฏฆ็ฝาxmƒไ๛ ~฿}จLใขเsา„t๒,ัปG2rฌึBv‡•(…฿ปวIยถม๙ตq“๓\~W2rœ๘K`ฌ“P+>[i‰๋‘DุธLธ๑ฃ๘,SI-3kๆฆ<ฝฌBฯUฆ‚:—Gืตข2๕X,ถ:็DZuŒqŸณ2Epํˆฉว๗‡ปžๅ(ฆDH ‚ ,๑!%‚ ƒรAkํAด๗ๅๅ๔พtC;^๛FยŸuีSM่บ—๗•0ล ฬิ9ฬ์0ีwฟ‹™<{w‚ฯ=ฏ}Ax[๐Z\%W˜C]™ฮVœ "z‘t4fๆ"ถZbEWDมเ#d๚UผŽอต‰{ ‚ฯใ*ุ้Iขท’tๆโษfบ"^๎๘][๑ฺ7ก: ศ:IW0sใคc'‰ฯ3;์ควมV  }ยญ๛๑๛๗ก:็ืษ&Ulq‚t๒ฌk%ฝ—ŸUkมZts7:ฟ•krี†ี9๗฿ส,6*ก<ๅฎEตH|แศข#฿๕รCซ๗๙ฒฤ”)A„#BJAธ‹…ๅ)ขฎE7uใun!ณใS๎ะŽฮ4:1—k“๊Nb ฃDวพ™พpg‚ฯ=ฟ}^๗Nฎmxํœ์ธ"V’*ฆ4M:q†ไ์หคgแ>*ฎฎŠจ› ณ๛๓d๖=ใrดNไณอ‘\>J๕ญ๏`K“ทIiะะ‰ืพฏs+บฑึ;•T]ตฺุ)’ G\n’ึ+Zh|(R) ๊Z6~ ฟwOญzฬeLน<ฆQาฑS คw1_สฯbJSxอฝxํPู&๗žH(•…าjuฌลSมถฯวpห๗ZL‰Aธ1"คA„ปp0X"๊jŒ๛ซืา๏ฆ‡m{ฎZชฑรตวi๏๊!zไ]า‰ณD'่ฆˆŽรด๖๐Zึใ๗์ฤ๋฿พ ีุ้*|ฎศŽา4f๒,๑๙ืœˆ?…ญใ*“{ฝz^Hๆ_$ณ็ จ๚V7epมด7Sš"น๘:ี#ๆBฤ…ก7น8 ”ซ k้ว๏ู…n์BePฺร&ฆ4‰™TฺUวY ~ˆื:เ*ข”r•P•Y๗ญฮaญA)ต6ึbญ‰ฉŸ์ผ•Š"คA–x4‹Anฦพ&ข~sี<0ณx๙~ผ๖๘ใตmภk๊ฉy ‹5‰ ญพ๐:ษฅ7‰ŽฎUฬฤaZiผ|^๛&]x];ะM]‹D”-O“Nž'=F:rŒdไถ<-ถ๗ภk@๖ก_!xคVณ J)MHง/๛ษลื฿#_ช&น :฿฿wŸนf”๖ไตส,f๚"ษๅทI'ฯaซ…Zหค์ฑW†$~๗v‚มGั-๋]kฌ็AšbขDeW 8s้ึ'*ฯญฏIA๛x›Qู&”า˜๘Šˆชb+ฌIWmEิ๛ฎET‰“ัwฟY}๑QภแU{s)ลo^vื~C…ูเnฝฆ)A„%ั"คA„ล๔กyƒ9 ฌM๓ju}บuฝ›vืทฏcบฉ่าุUx”ฆˆฯฝB|๎eโS?r•้ ฆฉi่&๙}๗แ๗๎พฺฅjำศ*3คS็]5ิศQาแw1ฅ)๙ฐ}}dež]W3žŠAšŒžpม็“CN\]๙ฉ1(@ทฎ'่฿‡ื6ˆสต ะ‰จ๊fv˜t๘]าฉsฎeำZ@ชข>ฐ ฑฟw7ม๚๑๒W'๒™ฤU,•ฆฐ•ฆ0สM‹>ํฃ‚6‰Pž็‚๏๋Zka๓Ulต€+ุส 6Mคญ๒สZฌ15}h>๓่—~฿๏ฬS"คAnŒ)Aแถl๎Wปˆบ๎ฌเD’ืตฟk‡ o๊rบ$‚4ม–ง‰‡^tbj่งW,x>บฎีๅD๕๏ล_wๅaMญkุ๊้I’Ko‘ ฟ-IEิ-ใ๙„[?Afื็\…ŒŸ]$ฆl‘^~›ส‘oขผSœtญy๋จMฮk?S I/a ฃ$c'1S็HงฮKEิํ!II•`หว ึ=€n๊Aีฆฺ$ย–ฆIg.ธษ}๏ีซ}”Ÿqž็ใwlAี/Qqษ‰จาิผฌnฐ"ฆn"คAnŒ)AแCmๆืšˆบๆ1Šฎoฏp๒บwเตฎG7ดสUKE.'>๛ษลืIงฮฃ๋ ึํร_๗ › —mtํ}i‚ญ03—IวOŸ•ไา›ุ๒Œ|ุnืŠ…ud๎๛yย-๛ัญ๋›ใdSR%?-Mข›{]^XเDqSœ ?M2~ 3}้๖ๅ ๓ุJึl๙ธซl่@9ภbใ ฆ8N:1Qqqฆ๒ภ]+eใwlB5t8ษ›VฑQ—ฑฅIl\ฎ… ๏ปQ%ฎผํ“ž~แZอb*๗ฬ7ƒ}O‰เsR‚ K์หDH ‚ ทฒy_"๊ิl~ื6‚G๐zwฃ;ัu-ต›๐fK“ุจ‚สิกฒอตษlพkKŠŠ˜ย้๘’ณ/Ÿอe wะAf฿/nzฺุ้*Yะสgบa›จXœภL'>Jrแ๘™šฬ๎ถR@7vl~ฟk‡›ศ็g‹ส˜ูห$c'ฐฅits P™tSบกํชˆŠซ—1ล l\u+k‘&DGฟ;๛›฿สx๖ซ๘ู6๎{ๆ๋ท[L‰AXb,BJA๘`๖'ฟbญHDิ ซจL~๏}?Jะฟw^<ก”ซฒY8uอššˆ%8C|ๆโกฑqE.ๅ@{๘ศ>๒k๘๛\{ ญ-ƒ™ฝLt๊วD๏สฯ,ส™๎<ถ:‡ืพ‰`๐ผŽ-.P ๗'.cๆ&ฐIkBีตึDT&q๛ ฃุD*ขnฯZ‰N<'b๊"BJa‰ณ)Aแๆ6่O~ลZ šน๏ƒ๖Qaแ๖Ÿ!ณ๋3่–u(ิ\‡›ฺv%‹ศฬ\&:q˜๊YZ๓๎๖ๅ‡่|™=_ภ๋†—๏Cež/SiB:uŽ๊฿ยฬ-–Šย]รFผฮ-51ต ir๙ๆภค˜๊,ถZฤ'jaๅJ.ํ^‹ต#ฆ๖…ป>Gม†Gv1%BJa‰™)Aแฝ7ไ"ข>(^K?แถOโ๗‡n๎Eีๅ)d_[7Ao๘(ษๅทIวO“N_tc่…;ด๓ัx๙^ย]Ÿร๏ฝ ๋]๕ŒI]6ธึ0ฯcก˜ฒI•t๔8ี7พญส lTๅ‘{7๐;ถิZ-<‰ๆง๑ูjuอฯ…ผี"ั๑gฯ‡Ÿ๚็มฦ}c๕>฿๎z๚woUL‰AXb[&BJAธ๑\DิE7๕๎๘~ฯNผๆ^—yใ…\™โf“ ˜ผึกดW‹+2˜ฉ คฃว‰ฯฟJ:vาจฃ’\ิถใQx๙~”ทืUDๅ๒N<ูิeอ’N]ภฮCX‡ืฑฏu}-ทhŽส$฿ ๚ฦŸcำXZม๎6*ƒ๒6>Fธ้๑ซk7฿ kAk@aS'ฅlRล'ฑqQึ่vฏGฃผะMBฬิป{šะš๔ ๒3‡W๏s๑ึฤ”)A„%ถg"คA„E็๛ลฏ˜j๕ ‹"ขn๊Iชั ํ„;?ƒ฿น า็ยฬ 5ˆNž%น๐:้๘I=๘๐:6กฺ]ๆI\ปั๔—'u๚'$ฃ'0…‘-bตv?แก›z6 ๆฎŠยา$fv[™Ee๊km•ื_+กูมภC่†ะ ฤ“I1ฅIHๆฐฉ\๘!>*๗|>tc:ไ~WฐๅLyส}—ŒA…9tC'*^ๅNึชmฅ€™ฅPZหE ๋‘ฆ บฑไๆk1;้n+3& 5fnœ๘ฬKozm}$๛ศ—ฏึ๋rณbJ„” ย!%‚ฐฦ™—฿๏๕ูyฃJIR‚ 7F„” ยe๚ะใ๛ญ ข๙ธืพ‘์_$๖ PkSˆซคำ็I‡฿%:๑Cฬ๔ELir [ฏe~^—-tEt„uNtค1ถ†ืฝm„๙C f๚ษุIโฯ’NŸ_[2D{xอฝx;Wd‹จฉ $็_ลฬ^ฦฤU”า\[๕พ‡@@y!แๆ'ะM=่ฆn๗:~าุeQŸมฬk'ฉชsฒ™ษ6โ๗ํล๏Šืฝร–g›\ฅYc+3nšแฤYผๆ'‘>๔=†4Aๅ๒x[\xฝบ:FัFeา๑ST฿ฆ8.ูEK]วZkžืนฟw7~็VT] hJ๎็Qษ $k?ธ@4]ืโZ2รWง=ืjฑU๗็›าŒศCภZ &Aeš\^Ce๊jmฎั|ušญฮaญฉUพฯYBiืๆ๊๙ฤD' :๒อ_ฯ8<ด:Ÿฑ๛๓™Gฟ๔๛~็๖gฎˆ)R‚ K<"DH ‚ ฌ ฆํ฿gญ>ดPD-z ๘ผ๎dv}ถึ>ถiฯวฦฬ์0fๆ"้๘W15sัฏฺ'คB7๗โwnร๏ืyตโญ!Mฐๅา้๓$฿ฤฬ^r-`ท”๏tอ?ฃ4ส 6~ฒฏฅผะI “:15z‚t๊ั‰g1ณร๎`ฝถถ0จ0็ฺบ:6นฟถฌsกไพปNถRภฬ\"พˆ๒3่๚Vnw๖–)McŠS}{๐ฺ7บC7๊ส้[-\z›สซษตŽI9Žป4•9'{ˆ๊‰ชou"<*9ั•ˆ๛Š๚j่yX 2ฎ4k%ULi [[ปแ๔สsำ๒rอ.#*S๏dRฯW”ูJk’›Qืโ…nสจMฑq…๘+kBL๋|f๖Oษ*BJแR‚ ซ›้C๛ญตั—o๊มiฤ๏ใฤTCGญ-อ๕ถq3uŽtbˆt๊<๑ษ็œ IฃUuอtS7^วๆZ๛ะ.tsฯbU™!พH:|ิU)Ufo“่XpศS^Mn@ธแ#xํั-๋ฎๆๆX‹)M‘Ž'>Jt์๛๓‡ฦUพuA…9ผฮญxmƒตษy่บึšˆ2ฎk๖2fๆ2x>*ฌๅ ๋ซ๋•N_Biฏg^พฏ–/uELLy†ไ์หT๏ฆฺ8W+6*๏#่฿‹฿ทwพ"Šธ๊๒โrM|คที฿YcภZtS—kๅ rNLีชHซุjSม&•5TีฆA{ฎช0เฆ^นืล%lตไ๎qit๎s‹E–ญ‰/๙Atไ›ฯไ^•yำ‡๖B2˜?๐ฃรฒ#Aธๆฉ BJau๒AEิuG”๚6unคซ˜ชoE๙ูy1•Nœ&=I:~Š๘์Kซ"๘\7uปœจž๘}{ัอฝฎeN๛ตJŠf๚"ษ่qฬไ9ฬ] FVุjะF0๘(^วft๋zืhมbฐๅ’แฃ$ŽŸx[;XฏบMKE7๗แwmร_๗^ว&t}สฯ`ฑP-a #ค“g][ž๊.ดb]9d+าย(สฯ8‘Y฿ถ ๘œซ๙N&:~•m\;7$cฐับฉ๋@ีทฮอ๊\MDอ`ำไŽ’ู4FyชฑปzžqีkเK\qblvk“U+ฆ, ”v"*ำ่*ขผšิหฎRญ<ํ๎๋w๘>gฃJœŒพ๛อ๊‹๔Vซ˜Anฐƒ!%‚ฐบ๘ฐ"๊Zผ–๕๘๋๎'ุ๔8^พUืZ›Jๆปœœ‰ำ$ร๏’\z“ไโn ปYAีJฃ๋\{^>‚%Dิ์0ุ้Iา๑!๎~—+\ฌ1(kP nYื6ผึืRcฌ5ุส,ษๅwˆฯผ@|ๆyH"lR]๙›• ‹n่ภk฿X›žท ะ๎ฆจกฑq37F:~ 37†n๊qmYw=ศ‰)k fvุฝ็ฎm่\๓ขเsาS&:๖}โกWต˜R:ภj—!๔๎ม_บฑ ฅผ๙๏–+ND%ีป:ะMไซG7ดฃ2 .|ป6ตo^’U็0…QWAt+์๎ ึX”RNฦๅš]lcฑIโฒk_,ฯ๕฿[ฤ” ยฺB„” ย*แv‹จE ?ใd@฿}๘๋ฤkpทึบส”ธB:1Dr๑ โs/‘\~ฌkYถhmD็๛๑๛๗บึฏ…"สค๓ญ_้๘iาฑSND™ไ&S ๏›ฯO๒Zึปlข4มš[ž&น๔&๑ะ‹ฤg_ยฦeH“๗™V~UืŠื>Hฐ๎A'ขšบ ผฒ\qNCตสคะษŽeNmำ•QนFŽ-ฎํsa๐yc&ฯQ}๋;คฃ'V•˜R:ภb]ตX๗N๕บึWฅkืฅXหmšฤฦ•{*{lš 2่บผ“œ™7‘ฯคุจ8m\bๅ&€)ฌIมZTฆก๔๎Bฬ.ธ฿ท<)MโžV†‰˜AXˆAXแLฺŸทึบ"๊บ‡F]ฟsซ ๙๎ูๅr๊Z Mฑi„J˜้ ฤ็^&><้ฤRศ๗D{จL^s~฿^‚มGk"ช ๅ๙๎pV-บŠจ‰!า‘c˜นQ'ุ–6M\fQ็žN6vบ1kฑัฆ4Er้-โก]๕Zฅฐ์~โ๙่lณ ผxฟgท ”๋ฏถx•งIง/`fG฿_฿ถlรจMySม๏qม็*ศ]SึUฅค#วจ๙Slqre‹)ํปฯ˜๖๐{๗ <์*ึด็$o\คŒ)Œaใ๒ฒZ3k :ื„ส4A˜C‡ .ว-M0Qข ถ:‹)ฯฎ jฉZี^ฃย:t};ชฎูM…Daโ"ฤleฮต]รฒš6hฃJ\y๛ฆ๑็๗Fž๖‚ ซR‚ +”้C๛๓s@Yšๆปzๆl์ย๏…ืนอUNulBๅ๒ฎB'q“ฑฬฬ0ั้็‰O3;ผ žxฺต~5uฌเaผ–šˆ œˆห˜ย(้ไ9’ ฏนช›e>อ&Qญ eบ๛ัM.เป–]dหำค3—HGŽŸ{…t๘จซ€X–2รCux๙^‚MOเ๗ํqฒ0ำเZผL์&็M_$- ฃPจบŠษ๘Iง/5๘}๗ก๓}ต๗ฝ@LEsฤg_ฆ๚ๆทGถ–kด2v”ž๛,zžหˆบ"ข<›&ฦn(ย(ถZXkิน๛E]ซkiำตฯ_uโ+๙f—๑๏ก˜—สCีๅkykYPสU|%Ule37ๆ*ง–‘ˆZtKขฃ฿อoๅ<๛ y๚ ‚ ฌDH ‚ ฌ0๎ฅˆZQ.wฉ{'~฿ผ–ผถWa 6.aๆฦ1…1ขใ฿'9๛ฒkyป๏ํใ5u >VQ๋\vส•T0ลIฬิy'mฆ/ ดฯฒช์zฟC[TFe๐๛๖ธชฏบVRฌ]Š)Nธึรัใ$—";9_ฑฯส ะM„?฿ปว ›l“kŸด้|ีš™น&นบ~+tvd^"ฮWต-œศWš">๕๑ู—kylห๙sจ\K(š`๐a‚E7uืฺ^๗ณธŠ)N`ฃJฏŒฆ7k ˜ิMญMžS~ต–Cาชซ*šวฦลe๖YTXkQตjPุAฆV]ƒI0•์ฬ0ึše+ขฎ[“j‘่ฤs"ฆAV"คAVหFD]‹๖๐jเ~^ผ:—“ฉฏUUH'ฯbf.ฝ๛]’‘w]X๎]:˜้ฆ.ยอOบ์ซ–~Tถู,-ฎอฐ4I:užไห$ใงQ~fJ4ถ2‹nhฏ‰ฉวPน&๐ย๙j37N:z‚d๘า‘cคS็1…ฑ{'=”Bๅšษ์tพ฿ษ&ํ_ญZ›รฬ\rmŠaŠ9@ฟfnย:ฮญ.ค]-h3)ฆ0๚ณ๗f1–]ื™ๆฟ‡s๎ำyž3rN&Gq‡”Yถ6บห ฬ •^ ไS€Tไj๔[็C?4ะ‚ ~่๎j@ๅjฯ’lฆIQโ˜ฬ$™๓๓<w>็์ฝ๛aˆL’I2‡ˆศึA$ษˆg฿sฯ_ฎ๕/W แิyz_บ5,ภU ผมoย9YืJกเ.ฏฌQ%QX†ุฅแKฮ„€ะ๕ํ4‰ฮK~v"_Tฅ๐๓<œ ป˜ข … ขถขฆยKQuก345ฏZ ้6ฺฑ-ฎ_๛;ฒ˜b†ู3ฐb†ูแ์X๕๙ŠNP;ภ7 {Ÿ†j๊#๙ใง6of๎2ฬาMืฮยฌNPฆั!ฺ๋เœ"Iึุ ‘jคCฝˆ’ฅU˜•qD“็ญLฤีRfoผiค‚+e!:ก;C๗= YำOฬา€ฐ๙y˜ล›ˆf/"šฟ ป:นอS"Y‡ฤฑ฿†๎Žื(g€ชึ Kิ๎iBภKลน={i฿BAำ6ฟY ~"ีmB˜์‚‹‡hแ:ต=ๆ๗ฉซแl๘ex^กj<Œ…[ถœขสีฎ^)gB™B0 IDATคะD  žKำ*\XŽงqฮวSHๅถฟ>M])สˆ"๑naรP^ƒ-ฎภ™๊ฎซช๗!‰ฉ๘w™ำo๏†avแNˆ…ร0ฬฮ%{ๆีำฮ้ั,ขพ๐`I5@ึ4รz ^฿3Pอƒโ,U€Xƒpโ พ๙ j)็6m"฿บˆRGใi€Mqˆ4๎„aฏŒ#œ๚vmยัดณฝ%:ึ/†‚ซไก2ฝP‡ใ)uwe9สฬZพp๒ฬ˜์L, –พGผ็แ พHkTำ แ%Iะ˜ถธ ป6U!ต๑{รํอ5ฺ ฎฒQำvˆคว_+0หท|ื0นi?ฝฏ1(ึภ๘ผแ—iต๔ต(„+ฏย–ฒ€ hญ[3gยx"_# ”oฆHธฐฉ ฉœ`ทๅ๕’ชำตTฅ“จ:ีU๓q•ZBศmyMพ&ี"ย๏}\ซ?อœลY90 ร์XH1 ร์@ฒg^}=Qปึ…ิถ@ค›เt๗4]L๙t@. ฝ‡h๎‚๋oาA.(ฦ™9๚4$มF^ƒn?ีL’~ฮ„pๅฬสขษอ_…Hึึ๎iษqg14`#ศ†.จๆAส.สtC(ฮ™๖0ป:I๙ๆฏา„Dm๎ฆ#ีฏ็I่o@ต AีทSลO~X`GXก6ร–ขณWฑๅ5ุ4tฯำPญรŸk!upีข๙kจ^๘ฏp•]ฟญ>๐[„e +xž‚๓“ BฤUฒฐลีฯ…•๏ํ5sฦ@ฆฟ†DŸฆส#kฉZ*(P๎YiuKชฅœต€3ฉFศD ห(D!‰ 9ˆฝS๙Uื„ลร0ฬฎƒ…ร0ฬb/ˆจฯ=f 3]ษ๘G บ๓(TำUKYg# ฌ ั%„ท~WYƒ‹ช4:kฟฝ„ฌi‚72t๛!ชฦชmฅรกฑˆสยฌN!š<ณxNi์อJฏEj@(จฦ^จฦจึ$ฆtฮ†@ทษๅ็\{ัุ์ิgึ๓aDƒHe ปŽร๋y’~fCDฒ๎3“๓ฬ๊$ฬสJิฦำ ๗๏ลdgบ๓Tc/pw6‘ณฐๅ,ฬ์%T>/€า[3‘ฯZ@๙P-ƒ๐zŸขuซiบ#yื3ขชjSr฿ญ™s€Le 5~ ต(ฏฟฏใฬ&T ฐๅตMส>ฃ้y"Q gCศtsœนฆเL[Zซไแชส๓ฺ‡๗‹)†a˜]tR`!ล0 ๓๘ู{"๊‹จฆ~ศบv๘Gพ ี:L‡l!mด–„็`ๆ.#œ๘ถธ๒ๅ:BBึตQK`A’umฑศP”cSษQX๙ิ˜•๑Xp‰}Q)p?งhVเ๕?™้‚j V>/E๋Q-Rxiมฅ 1•Ÿ๐MFฒบ๓t็qจถ‘;ก๒สฃ l•ใ๘>๚ฬบT‹งฮฟœษw3งฯŽ๑a†ู9ฐb†y dฯผ|ส9 $N๎ืk ฺม๋y’ฦล'jจีN'ย–Vฉrf๎2ฬU„3C(ŸไF๛!่๖ริj–ฌƒšชmชุ์4ข้ 0ซำpa‰EิุL!ผม ๛H %๊๎ˆฉา*์สlq ีO–&$–ฒ_T่T๛a่ถจฮcPอ4O'จ*ซZ€อฯรฎNRำืx}HxุตyจL7TศFึบ„pQณtแอทM‡Hึ%5พ|ฟG"J@5๕“ˆ๊8B"JiQqพI}’ป๖H๗SกตqีฆNlศ'gBส˜ชไ7ชฟ,cส9ะดผT…•'๋จ"สYj\QCx]พr]XL1 ร์8XH1 รl#ฑˆ…ฤk|5uภ ๐_ ฟ๙O6P;Š1ฐ…E˜ีIธJ€€ฌm‰ซ๊้ฐli2™ออ"šป ป:[ษลaๅ–/๎ !$ผม šกZ†ฉฉ•ฯYุJf้6์ส8‚๋gasณTม&tAจ–ก8ภ~˜ฺ๏ผ$ชƒ2l~fm€ุ_Šฐ็"<\P†ฌmฅเ๓xBaUšศ7wมๅŸมฌN%ฆ>๗}ข.,Ceบก{ž„๎<YืF๗VภU‹pa‰ค‡Xx<ฤ: ฟ"DR*YOไ3pQ.(“ค-.ึ@(gHะ ํoHa‘ส@( ็ \Xฅ ตrŽD ย_S ร0;R ร0‹จฏAjxฝOรz บ็$U=N}เฅ4*ฏ็ญอ!Zธป:gN…|-yg!;ฏYจึจถ@ช8ดZภU๓0+ใˆf.ย,^‡Hิฦ•Q)kศKั๗ +ฐล%˜• :`๋œต›๎ฬุRถฐฏ๗ศฆพ8ุ.1U-!š๚ีO?ช‚>—’ฎ4ผŽฃะ}OCึตSถWP5T\ลCSฺxฏ๘HฤD$—R๕~ dข–ฎฟเ‚2ตฦๆ็แ*kดFส‡ฌiฆ*5/X˜.(ภ–ฒ$่…bก๛จ๋R-"šฝ๔7ี๏“9}6หW„aๆ1l;YH1 รl,ข๐ก”j€?๔Mx#ฏBท„๐kปๅ…U—อ^D8uฎZL•/fฏ…๒แ„Ls’ฺ%;C๗‰ธสฃ8Kํ–^’Zศย*lify 6ฟU฿xษx๊ณู˜์ „าPวก๊;พ0‘ฯU๒n แ๕ณ€s$[ภ|ฒพฺ^MtGD•s,ขถB€XK๙’u€Ÿ†๔R”Ÿg#ธ [ฮRฅTชŒspA+TIUฮฮททR†t‚Z_ฅฆ`์  „eชพ‰สเฌ๒ญ_3‘สPีT"กSภ๚=โ่(ณซUh‹จ-‡ลร0ฬcx"ฒb†ู<ฒgN 8็F!ี๓ีธŸง„Hิ@ึถQ–ิะKP=”#ฅ|8XภDิฎ'$UแH VฉฌดŒh๚cDณ—`๓๓ยอlม:)’†^ ๐หะ]ว!“ ฑ”Š…ˆM9,,#ธ๕6dฒžฆ็ฑุ6ษ8 >ฯฯCึตQ–Wบ๑ฎ‰|wํ๙ฌญจ[X† J’k{ˆืรKBึwฦ-|wW‚: -/.รW`"ณฐ˜b†ูฦ )†a˜G‡Eิƒ>}$„—„ฌm…๎9 o๐Eจฦ>jUYQAถธ ››ก|kกš๚ก2]u€าthซๆaKYDS!š๙ฎด๚ฅ!ฮฬCH!เ‚2t๛!่พgh_*CdO๖Š…œƒ หฐล˜ี ภY:ls๐๒ถฏ›ญไอ|‚ไS ฒถ-ฎภนซิ0n3หcpA™sฝถ๋~‚ )เผฆ‰BฯeปgโŠOVโถฺุ<œ YLm#.จ„ม•๘_k~๗GฦWƒaf‹žŒ,ค†až์™S็Q๗๛ิาƒจkฅ๓มกš๚7D@Qถด ป2pโCjหห/Bึ4Qpv็Q่Ž#um4L’˜ฒลธย"ยษsˆf/Q•ลิ#œ…ิpBBึwภ๋}๊3๋DยฐD™6a…ยๆ๔ฦ41”yณ6KmdฮR๕šs\1ต ยรdgเ*yx}ฯ@6๖าšA_๋wคGqถฐ,ฆถl]X ‘ฌ…จ๏€๐RqvWH๗J~.ฮสP๕ก—‚ะ$})hพ@ƒ ‹$๔น v[p&Bp๙็ แีณฬ้7ฬW„af“Ÿ,ค†a•3ฏŽ งOCขฏฦW=qdm+ผoภZQ™รฒ‹ช”?”Bxใ-7฿‚+ๅ๐๙สY ีq^๗I่ฎ้ dบ *SK0หcˆฦ฿‡YพM!ฮ,ฆ่๐์ฌn„๎>I๋”n˜ะๆยj<9oั๘๛จ^๚GจๆAxฯมz™2ฃ4„Ÿข๏Uษo„›C ฟ€`๑ฑ๋f‹+ฐี<ผฎใ™žธŠ pQ™ึ ธ ี2D๕bqธq๐ฎ`๓ ฐ…@jมๆp3ึ„!ฉjP>ez…eช๐,ฦ-“Jร…U’Rฉจฅuด.,ัŸชpี"x‰ถW-ข๐ืฃใBุS™ำgว๘Š0 รlา“’…ร0ฬฃ“=s*caOณ˜บ7ฒฆเ‹ะฯB5๕Cึด@x & ฟ๙ฯอ ธ๑&‚๋gแ*ภF_=3ิFึ๓ผž“q@p ‰ฉ‚€ฃ™O~ถฐH c๏™{บ‚ Tหtฯ“Pอƒ5M^,–ข*\ifeแ๘{ฎ \em#฿ ฮาz๔?ภ+4ฒ^'bแ(แJY˜ๅ[0k๓ฺ'1%5็mถฐ Vจrฐก3^3ช64K7\{แญ_ยW 4’O+๘ ฒฎP๚๎w›—VaK+๗สžb`—ญ ’๕•ƒT๑‡วะ…•ธฺ้ณืุYCRสฏ…HึBz๔ูมE ,ำ็f9วีR[นX-ข๒มy฿ฬŸ2งq–ฏร0ฬ&>*YH1 รlbJ่ฯW้ แW {Nnˆ(๘)ศXDญมๆfN]@pๅgpฅUธ่>วอ  ีุีv^฿3ะ=OB$j คGbส†ฐk๓o แ๘{:๙ตขk_ธ*yศ†.x}ฯPv]+เง!„ค–ขrfeัฤn ฎฐt๏uZSฝOQKf฿ณ ]€๖)'G(ุ๒*์๒ฬ๊„Ÿฆเs8–~wม–`+y่ฮcP๕@"ฝqo™ล›ฎŸE4๑‰ษ)’*ำฤฟ๏ภซฉฬFnQlCH˜—a๓‹\อ๖ภKฃจฒ)Q ๘iศuฉkชโ,,ภ…eศ๛x๏ j•Mิ‘T๗S4=ั„ฐีMใ+็เชˆฯศEๆ‘?ซE„ท฿๛4ธ๘Wส"Šaf‹™,ค†a6Ÿr.’๕๐ผ uœZพ๊ZฉeE$ขึผiDำ#ผ๕6la ฎšฟ+ุ๗A~˜„๐S ]ะmก๛ž+ฆjฑส kaV'\? 3wๅฎ€็ taฒฆ‰Z๓Z†ฉบ&Yv6‚ซฌมฌN!š<‡pุตYธ ‡”ีšPภน๎}^๏ำTqีุ x‰๘Sซ“ˆ–nCฆ๊)เ™ืไ~๐ิšWสAw‚ฌk#aหCณxมอทMž‡อฯมๅ/_/!กปŽ!๑ฤภ๋{Ž๎qW๐นตฐๅ,eL•VYL}-’DTฒPปTp&"มWZ‚R|yอ.ปข็dm\ํ™„ฺจ0uQ…„~Pไเ๓G\dล0 ณ}ปR ร0[วS"Y๘eจŽ#P-ƒ”U“จฝ#ขึวฬ'ˆ&ฯมๆfaหYภšM๘๑"Yีุqบ9่๖รฑ˜`"8ภฎอ"ธ3D๓Wฉโรzบ(€๐ำะO@ท€ฬtSk‘๔เœกสต์4ยษM‡ษNWๅ=฿‰4t๏ำะGก;’ ๔า๔:œ+ญภฎอ#šฟ™j€H7ว•ผ?๙<ถฐ[ฮCต B5tR&ั]Qแญทอ| “›…ซ่พ๒†^Bโ‰?€๎:N•„w‰)pฅ,liฎ’g1uฏ๗นŸ‚H5A๘I@%(ฐ’ˆrๅ\9K"๋d๎Wทึ$!“qลT,Ÿœ ใlฉ<\~ฮTYL=่๕ญ\k!ผ๚๗ฤ"Šaf›ž ,ค†aถž์™SO:'ฯ@โตฝ๗$ฉฬ†Rญ ๋;โ๊‹จp™B'โujŽƒๅ•Or((ยฎอ!š8‡h๚c˜ี ุา*`ยG>ฐหฺๆxชbT๛aจฦ^’…ฮRๆW) W\B4{‘™—ไ๕๚บ˜์d]_um$yM@™^ท‰h๊lv ถฒ๖H‚ื?๚$N>T๋P|c1ๅ\X‚+Rพ” +๛^L9€L7าT ไ5ช Jิmด๒นสLnf๑ข™Oaณ“ Vณšเ Jส‡l๊ƒn?ี2Dำ๏โ)l+ฐ…E˜ล'ฯม,\‡ษMoYๅฺกPm๏ภ+P}๑๋j!1%W)ภๆ็c` ‹q%๖‹๗ŠD‚ ก{ ๋ปํQfuัไ9DณŸฦ๗ีา– แ%‘|แu๘#ง(|๎เsk(_ชดJำ้ทท†5สงชB/Imsส‡s.ฎผฬรWเย Vุฆ๗ซ32UฤA๊ยOCHMb*,SตVต[ฮBžj้L„เ๒ฯYD1 ร์„- )†a˜วG๖ฬซฏ;งG!ัฟ^ฏL7Bต€j? q„๒€Rw‰จ Hy@ณaฎ!šฟ›_xl"๊ ฏฟก^stภn์ฅรeไlKqศ๖์E3kณqxฐฟ๛\ี"U#ีwPฐ|Aศ8XUa K0หc”ต2†hสึ‹จฯฃผXLฝ ี<6หย@ศธตršฺ*k๑๋ท{ท•O(ธ๒œฉ@5๖Cfบํ“ˆสฮ š˜Z^ฎั}ต]/+•A๚ๅ๏มx"UOำื1UL•V` Kwๅํ€zg-„Twฆๆฅ›่3Žฺ๒‚ณZ ๖_ฉำ๋t้ Ul%(RR–U\-…jถœทํ–.จ„แ7C๚ท~๘yย0 ณถ>,ค†a?;]Lษt#d๓t๋t๗ จๆAˆdUm8Gํo๙E˜๙หˆฎSฅัฺC„`o๕SB…Uหผ็เ ฟีะh?žZ%a‹K0+ˆ&ฯมdงHา์’vpaฒถ^๗IจŽ#wrf„ UZ…]G4{ัโu˜ูKpQ๕๑.‹—„l่‚7 t๋0T็1j…๒RT1U-ยฎอยฎัิ8‘ฌง@๚=ำส'aหซpQบe2~O"ขh๖2ษจนKt_=–—จ šz๑฿Bw๘ยD>g" ๏..Q%ฮ†4ฝbŠBฤqง๊(xW]ฎธ˜ถผภ>6๕ลJั‚DD"‡ิS๘ฝซ่s ธ๖MN› *aดpๅ'ีw๒๛™ำgณผ๋`†ู!,R ร0;‡•3ฏŽ งOCขaG“ำ ]Pํ‡แ๕œ„l€Lg่ฐ์UDๅฉๅห,\C8y67Cู);๚้'็ {Ÿ‚ืt๓P ”ร"่PiKห0ซ“oพ ››‰ม{ศ ฮYxว ปOP^Vข.;ย•VaV'อ_…™ฟ‚h๖"URํ'ฃILีถย;๐ Mๅ๋:‹'M๊ฐ ››Yพg T}็–f๔l๑‚ั๛ฌธ–๏dฐ้œ )\~j\๕1lnv‡ผอ|่g‘|ๆโaฉ;bส9bP\อ/Pฺ๋.ฮZภ9’Pฉ๚Š#„UุJˆชpฅlฦงv์๏ฐ1`"]\ฆEย<\ดw'๒ฑˆb†ูแป!R ร0;‹์™S {๚qŠ)‘j€ฌk‡๎< ฏ็)ศๆ~jSั ๎ Šp๙ลธี๋*ขษ`Vฦwฅ~ ภ๓Pญเ๕=Y฿ แงโรต+.รไf\{6;M‚D'ฐ3ฺ’$,„sP-ร๐๚Ÿ%ฉ‘ฌง๐kยUr0ู™8#‹ฆบJ~็.‰๒ Sศ:สา]วกปžˆฬŽฤ[Xฆฉs—!”Y฿พ~๏9ฐ…EุjบใMิ4อๆ็iญฆฮ#œ8ป6ป3 /่o!qฟ‹Ešปƒฯ]Xฅjฉย"I›Pอๆโ p/Q ™ฌt’~ญฐJSใ฿‹&้+™Z“ฺ๋ใะ๓KBlTTบJ6?O๋บGชYD1 ร์’8 )†a˜ษ†˜๚฿o›œIค)ผ๓ผ็!›๚iคy\…ฐ [\†Yบh ตต-ํง!ต{#ง 2ะ]วจฒภฏูถฅุตyWN-nŸisn1%แL8Cํ‡ฯ“ิH5™pX-ภๆfa–n"šพ€h๚cšฤถ[P2ีีิu‚ฆ9vฅ–)ภธฐ ณ:‰h๖„—ข5;ตELP๘u~ถฒFฟSห „๔เœอ/ยฎŒ!แํwhภnธuา$ŸC๘ฟY( 1e l5Oฟs9ทƒe‡ธ๓XำLUQ^ B(8Sฅ๖ผฐW\†‹*;ง5๏Aอ๚Dพšˆd- $ิœ…‹ชฑ˜ZŸธ{'๒นjัโ๕‡Eร0ฬ.ู‚ณb†ููdฯœpฮBช?*#tขฆบใ0‘oA6๖R8ฎNppae#[ษฬ]Bx๛]˜ี‰ฝwฑฅ‚j่„w๐ืก๊ใ0๐v ูถle .ฟ[XDpํŸแยJ2ถฝgWอC5 ภf,Ÿกi_ฐ@P‚Y›‡Yบ…h๒CD“็aK+ปxM4dM3Tt,ฅT๋j่0]-ภfงจb*QYืถƒไ‡€ณ–Zฃชy่ฎ' š6ึห•ฒฐksฎฝเฺwMฌeหิะ…ไ3o๐Ej๋•๋ีCิฺ๋*ุx"฿ฮฉ,"I(€XD5P›žˆ\M%ุโ2\XปB3!DขžขมKาKฅkเ‚๒iๅๅr\ตˆp๊ม๙Ÿ|7s๚์๏†av,ค†av ›/ฆ„๒ าะ]วแผFQ5MYI.ŒCฐณSˆฆฮ#ธ๕Kุ์ิฟุสƒj์ƒไ7กบ Z†H๚๘iSลeุ์1eถบ%IPๅ“ษ:x฿€jZUhrส8ย[o#{oืส{_Amค]วก{ž„nl์‰CฆM+ญภไfaฎวZ้วXอB•Zfu.(ฦQCด^ฐี5ุ"ยซ„เ๚Yุโ๒ฮฯ^ปtวa$žCx}ฯศฏฟ‹ย8ทจDแ๔Q๙ฑ็9Aค2ต-‰ก)+(Q๐w9K!๚b๏}ฤ9k!S ษ:ภKA๚ฑ˜2lXชล;ำ-wp‹(†a˜]พฝc!ล0 ณปศž9๕คs๒ $^{่o"dฒบ็)x^j„L7วกท๔ท่ฎœƒออ œ๘มท`sำ{โภ@I/ ูิไ5จ–a ^Š2ฆฌู@feแญ_ลืoณฏmWตญะฝOAต ๔๚ดฏ(€+็`ฒSˆ&>D๕สOแJ9์ึษf๗uEฺ๊ {Ÿ†?๔U๓ี4“,\>_›ƒอ/ึฤ•Hnี๋aๅหฐ๙E่ฎใTั‹จ๕ื\{มๅŸ๎๎๊ตฏ@w?ฤ๑฿…๎:‘lุ˜bนัW-ภญอรูp›ลUฌ ?Y็*ลCย2l%T๓$ฅฐ๗?๏œU…y)^๔™ใช (ร–spีŽสฬbล0 ณG๖ฺ,ค†av'ู3/ŸŒ IDATrฮ}P1%’๕๐๚ž72TหP\e!6;p}ืyใ`ฟฏ–~ชํ ผม Aต าฃCถ5ฐฅ˜…kˆๆฎภฌN@ Uะ”!ฺ๋แ๕=M"ชฎmcช™3\e 67ƒh๚*็+ ทต…๐๑"๋;่ฝ|เสะ๒k(๗K >ทล%z*ช$j1e KฐฅU +oŒ๏-‡6วฎฦ๗ี>^฿ณ๐:t็qj‹‹ร้]ย…8P{!žฆธตkใฌƒLีCิถQธ๗zuก จjซ’lดง๗อ}D๙ dmDฒยฏขˆ+z.๛ไDQ ร0{lอBŠafwsฟbJคเ๕= oเPอƒTeใื|VDๅfM_@pๅ็ใภมฯ BiศDTผ็ :C5๕RB8 [ฮ"š๙ัิ˜ ค—คš>tจ จ๛$THœcU !–W๒ฐนiDำŸ ธ๒3ุrว~[+j‹“™nzoฟ ีิแ%II W-ยฌNยๆ็)๐Kp›สg๓‹V~ฒฑ๗ฎ,ขfuแ7๚%‰์ป๛ส9ะฏAต„Hg คGนEa ถธBูEAiKฺใึซ€dM3ๅ&y้X๊†ฐฅธต9ธ(ุ˜>ท๎ฃ๘:™Bz๕ํ$ฅผไฦDQq^[ฑTถนjแํ๗> .ีŸfNโ,?†a๖ศNŽ…ร0ฬ {ๆีืำฃ่ฬ}ช^s$7Z†!๋จ’DjQ•5ุตyD3Ÿ ธ๖Fพ\W•6๔เ๔R฿:LYF'ก{6ไˆsฎธ‚p๒ข‰`หk^ ฮ†_่ชไ!4t฿ณะํ‡ :ฉI}vr^4{แท`ฒ“ผVwก{ก๛ž…7๔U'yiฉฉbชš‡ษNรfg(ศ?‘„~ฤ jณ6WษBท‚ฬ๔ฤ“)›Z9)ฯหๆฆ)?W*‰#฿ฆ‰|อ‰๚;นEA*๔yTษmŠ0t.nปญmกV4ๅวR7ข บ•q’๎bฝ:‹๗ฤ@,ฆt2SP~\Mๆเย*\Xขฯขตyบ—ถฐฒEร0ฬ฿Wณb†ู[ฌ‹)‘ชํ๗_€๎<ี"ฒฎย่›H6tSปž”pA™‚ตซDำ็k ’ P™Nุโ*U่x)ศฦ^จLตRšvmŽฒยฆ.4,,qฅแ#เ๕=Cbช0DMๅYKaฺAฎœงjNg!ผ\X…P>Dบ๐๑”ล4K•<ฅWึโ๛g๓ƒ์๗๏วœ"๙—จฅJ4ค๛( ่บGUชไผ‰|,ข†a๖๙#……ร0ฬ!๗ฟ}gภ†ๅQH๕ว|5ถ๒้*!แฝo๘e่ž'!5สงV็(ซ+ž่ๅLWฮย,D8}fแฬโuQ[€l่„7๐x)ชd‹ซืเจ๊ฦ,฿B4uมต7`–o๓ๅฎ๛จถ‰ใฟo่%สําษฯ>ฐ&7ป6O๕pœ๕p&„๐า4ะม‹'๒ญท\%jo{/Wน๘7g2๖/ืๅ{?๘ั๋NˆQ ๔เ[็_๐,ฟ[†a๎ฺฑb†!!ตqพ.ภฺำ?“๏์›c๖ฬหงœ๓GYLmยƒ5Yีะีq^฿ณPM”ทข}š๎–)Hู8๓&š,QัโM˜๙ซวYผVมีR[ถZ$›๚เ๕?o๘จ๚vเ3ฬ4-ัWŽฟp์]ุ์lv†*ฉ˜ญCiศtT๓ ‘ืเ ฝ‘จ๛‚ฒๅl~ฎšาเsf{pฦP _ชžฺ๘’uสหมš3ฎZ<#R ูpไ‡qJZ7*คุxฆฒb†นวNŒ…ร0ฬg…ิ]‹ตv”ลs_T? Y ี~Pf”n„ะ 8W ไ(zeถธ yฒฑชyถgเT 0+ใˆๆฎ ผ๕6ฬโ พภ›บX"Q Yื‘Wกšh2@aุ&ค*ฉ) €3\aแํwN|ณ:Iแอ< `s‘2YOขฐ๗ixฯA6๕Q๋คณ€ กฅใŠCภ…UZทjvmžึ˜ณฃ. M^ศyร/žQ}gDบq฿ŠจuXH1 รcKฦBŠaๆK…ิ:๛PLฝ๚บsz๎๘สว(„๖!j[ Z†เœ‚j‚ฌi‚ะI88 (ร—`–วอ|Šp}ุ ป๋; S;Rm dS?ltฐ.ฎภฎN"šป„เๆฐู)พได\ยOAึถAw‡?๒T๛ajั`หซฐซSˆf/ย,„ฌkƒ๎~บ๛ษะ์๕ #[XD8๖ข‰s0หทaหYภZp5ฃฌ‰Bีะ๗,ผก—จยPyp6‚+ea–วxเ <q”Za•Gํฏa.,มU๓pฅ,ฏวcภ•ฐr๑ฏs๋dNŸ"๊{?๘ŸŸ„3g๎%ขึa!ล0 sG? )†a˜ฏRดษ†๛oกtงฯพฑr]XL}้ใ“๒‡’ $ขT๋dm3e@ภEุา*์ส8ย้ ˆฦ…YฝทPRฝะ]วแ พQ U฿‘ฌง๏W|˜ี D3Ÿ ผ๙6lq๙ฮ๋เ๗‰€จiืผ‘ืHd่[อร–‚‹ทq}Eชบuช๓(tื šส—จ'‰Uฉšญฐ„๐๖/N ณt ฎœใuy˜%๒’ต-ะฯร?๐T๓ „WV๒tM~„hๆภั„7WอC๗<oเจึaศd=ต[juA‘r–ซฅถW-"œ:Fp'ร~Q฿๓ัง๕(€ฏยBŠaๆฯR ร0๗'คึฑ9RvtŸ‰ฉำฑ˜jเ'ง„๐ำPญเ๚5่Ž#ตm^ŠD…เส9ุ์ย้O^? ณ2q_‚Bต A๗ณ%ขพ›9}v_<DDญรBŠaๆ;5R ร0&คึูob*{ๆTฦยžNŸทbJyะmแ<uฒฎยฏ”L[-ภฎอ!š:เสฯaV'๛€“๒ค‚j=ฏ็I่พg ๛ R Rpa f้ข™‹ว฿…™ปสแฺ_ถษIeเ |‰#฿†j;HQBา8๚โ2‚ko ๚้฿ยๆp?ยP$๋ {ž„?๘"T๋0Dบ 2ู(Mm|๙ุข้ฉํo๑\eโหฏ(ผแo"๙๔ฟŽ3ผR€ ‰mvmแท„—ข‰m_๛ํtื1x}ฯBึwาภ!แLWษรEธโ \Xโเ๓M`?ŠจืGG3‰HŸมˆจuXH1 รใัอBŠaๆแ„8‹œ‘8cฅๆ์๋ง๖EIฤSบใ0ผแ—ก;B6tำ๔(ฉแœ‚l~ั์ET/=lv’‚ฎ๖gฉฦ>่งแ๕> ี2HU9ฮัฯŒ˜ล๋'>Dp,l~๑มๅื^]ญd=ผมเ5จถˆD „P$:๒๓oม•ŸมdงแA๋Dฒžยถผ ีz€ฆ%&๋ ”Objm6;…hๆ"ขนKิสW-๐ยฌฃ4ผgx๊)#*Y!Mก,.#ธ/oฟCืฺO?ะ๚ธ(ฌ…๐5่ž'I๋ฤฦืœ (_*ฟgS๓ง"JW๔i%๑ะฯ=R ร0๗ุSฑb†yx!ตฑA฿Ÿbjภ97 ฉx/žชeะKะวก{ R Y†‹Eิข…๋.LvŠฤร=ฺพ Iํfฒฑ^๏3ะ]' Z†่n œ ลa้ ผ~ถ”#Œ๖฿๓]$๋แ๕=ะฏ‘(JึCH ฤถksวAxใM˜ี)ธฐศ๋$k[(รh๐๙8_ช๐SŸSf๙6UKอ]Yบ V๖๏ฆำKBw‡์ทกAค›๎–W๒oแํ_ยYKษ=๚ธJ"•?๒t็1ˆšๆ๘{ฺ;๙_•5ุย" `ฮ˜๚๚kZ-"ผงมลฟ๙=Q )†a˜{์ XH1 ร<บฺุฐณ˜ฺ3จฦ>xƒ/@wƒl๊ƒL7Qห”` ‹0‹7xf้li0แึผฉกบ ›๚(วจํ ‰)/ุ.ฌ6B8๕ข‰zฎ”[W๎‹{ุ?๘-๘#งhญjZ t‚DTnแ๘๛ว…]‡ญๆใชจM\žšf่็เ <~"QO9HRมeุฬย5D3Ÿ šฟณ2ถu๏•ธู๔RPm#๐GNAwวญฎ^’หซE„ท฿Ap,ตฅ ฑyB$ฆdฆศซPญ#ิช}ภZธ [\!9–มA๔_r 7Dิ_iๆ๔/๖P๙w?ัiXฑiู‰,ค†a๎ฑG`!ล0 ณyBj๋0.…้w๓ว๛ๅ’˜’?†ฤkป๙๗ ๐_„n?ี2YำBU/paถธณxแํw`ฏร–ถฏ๊Eiจฦ>จ–axฯB5๕C6๖‘(s.(ภU T15qแญ_ฦญb{๔Yฏ<๘C฿„7๔"Tห0d}U'9›F8๑ข‰a–วเสน-ฯฺR}ะ='ก{Ÿฆ  Tf#D…eุย2ขนKˆฆ. švmnOWฒ /ี:L๗S๗ ‰:8g Œpโ}„ท~ ณ6‘จsาถHช่ŽCะ฿€jุhน…ตฐAลx"ŸณEิ๗~๐ฃืฃ›;]–…ร0ฬ=๖ ,ค†a6_Hญณ?ลิหงœ๓Gw•˜ฒฆ™ฦวทP๛U]+– Dli…&MžC4w6?๗๘ฆ)ชiบผ‘W!k[Iฦฌgๅ”s0ks0ณŸ"šฝŒp}ธj~๏l^5”ญี๗,t๛!ศLฯต6‡h๒ย‰s”T\†ะwu้'tชuชใtื ่ึˆšธ5อ„@X†ญฌ‘”š๘แิ๙=|.t‚&F๖?Gmฆฝ้ Iำuaz๛ุ์ t<๕p{๖ฃฮZ่ฮฃ๐ึ๘5€Œƒฯซ…๘^_ื๙XDmฎˆZ‡…ร0ฬ=๖ ,ค†aถNHญรbjง>Dช^฿s$ขฺCึทC$โๅ๘pjWวM‚h๖S˜์4\9ท3^พ๒กZ‡กปNภ?๘-ˆšfศT <ฎœCดxั๔ว0KทM}”v๏ฆ%YyŒ*:ŽB5๕Qkžณ*?๕ขษ`–nยๆ(XqพึŽ#P-ระGกš)วH๙qฐv\อ6yแ๘๛ˆ&ฮํ‰i‰ชe^฿3ะ' š‡ jš!เช˜…ว฿ƒYเ[ ธ‹ *ร~•&๒5tฦแ้‚พfธ ป6U๖M๐นซ\k!ผ๚๗ดŸDิŸ๐/N)ธ3€8น•?‡…ร0ฬ=๖K,ค†aถ^HลฟXkG'฿ู7›า์™W_wNBnอ฿:?ำO@ฆก:Bท@w€l่ŠCฐU<&>ณ2Ij*ฬ๒mุย2vV๛› )ชm„ฝ|›2ŒtPŠชR*kˆฆ?A8๙!lvัๅ]%ฆD*vบ๋8tืq’;~zc*[8๕ข้O`ฎมไfvT>“L7Bw?ี2 ี~*ำY (ยตKซpA ั๔„ท฿E8ฎผฯUct๗ ่๎“ะG jš)j fe แd\ฑUwLKœซไ!ผผƒง่3 ถ5ฮ‰ด6a…&๒ญอรมํูเ๓;"๊,s๚อ๏—gำŸ๐/NI๋F…๒—&,ค†a๎ฑวc!ล0 ณญBjSSnดCตคvขๆ~ส๚‘šG5Oาf๖"ข๙ซ0 ื` K€ณ;h้Au7๐ ๘‡B'!”H8 [ZฅŠœฉ๓ฐ+c0หใqีฮ ศt#TหTวQ่๎' [†DD8๑!ขษsปโพ–๕ะGHD๕œ$ู&V`Vจฒะ,„ Š;๖wp•vบ๗)ˆdd*Cm–6‚-็`ณ3'ง฿qๆใ|gฎฉถ่ฎ'เ |ฒฎP0ฬ๊$ฬ%˜๙kฐ•ฮ—น1ฎR€j=@ฺัDพ8๘…eธฤ”-ฎBHฑk?ƒ‰\๙พQ฿๓ัฃๅ ๙ใ็ณb†นว–‚…ร0ฬcR๋๐Ÿ#eGฯพฑpฝณgNe,์iแ๔้ญS"QYื~บ็Iจึ49ฯKฤ“้Jp…ED ืaๆฏ"ถธด๛Dิsศบ6xฯB๗< y,ฎHPVQP†-ญPธ๖๔Ds—a๓ ธ; {_qฒชก ช๋8ๅzตC$๋hJซ0K7ฉ๕p๊#˜…๋ปtYญM*C-nวแ ฟแื@x)SฮมUrH?๑>ฬโ ˜…๋5‹^ป„L5@6PnูW ๋;)ฐุตY’นณ—Hๆ๎าj"Ui`ภภ M‰:j5lP‚\e ถผกvืD>Tย๐ฦ![?๛ๅ๙?pZ๘ใว๙:XH1 รckมBŠaๆ๑ ฉuXLmโฮKBึถAต€ื๗,TตyIช8 +ฐล%˜ฅ[ˆฎลSฟfฐSืีzเ ะํGจEฑฆ™ฤTT…+็`‹+0ณ)‹iๆำmŸ๚Fาฐบใ(ผกกฺQๅ,ฬ๒8ขูOŽฝป{Eิ~iHMSิ๒ๆx…ชูคŽ,l9‹hโ„“ม,‚อNm—‰ZจLtืqx^…j €vXธ"ฬส8ยษsฐนูฝำึ&$T๛!xฯCeบ(๘|#c.OŸ!ฅธ ธใƒฯ]P ฃ…+?ฉพ๛—฿ฯœ>›ฯ—"ขึa!ล0 sG- )†a˜#คึ!1ๅŸ>๛๚ฉ}qpศž95เœ…T|pส‡จi‚j L˜ถCuญ€Ÿ†ˆรŠmqfy fแยฟŠง~ํqค†๎<o่E่ถƒเ\Bb*ฌภ—aึๆ`ฎ!šั์Eธฐผ•[?Eญ_Gเœ‚n?LQ‰ฒ ขฉ๓nผต๋Z๓่:x ˆtt๛!่งแฟ ‘จฅPp็เlW^C8๖.ขฉ`oยi}ถr'„Ÿ&Yุu๐หะํG่= WสยfงŽฟ‡p๊ƒ"Tห0ผกoB5Bค๊ฉ]ฯธ  I„—s2‘ฯU‹งฮฟœษw3งฯŽํ—u๘~๔บbT;ตฒb†นว๎ƒ…ร0ฬ๎R'tต7 IDAT๋X‡q)ฤ่Oฟ๛›?/๋๓E1% :แผง!3wFดรQ๋Y~‘*ขฎฟ‰h๎\PฺผŒาะG ๛ ๛žn;Q !$เ@UAมีฆ)wใ๏Q(๗}\Oj< ๐ฏSE”_!œ5pๅย[oฃz๑`W'(ฏผF_ผˆบ็$ผ็ก;Cฆ3w‚้MWX†-,!šฟ 3wัฬ'ฐลๅ๚บ๋'~*ขาRื•s”ใuํŸแชลธ5ืhgBxวก๛žj์#‰'Iผx‚‰ฉ-ศืbต๓Eิ:,ค†a๎ฑลa!ล0 ณป„ิ:ึaผ)•/ใk?/๋”ู{๓๘บช๓P๛ูำ4อ๓dู–-’lใl,6† ‰Œ N.%้Fํmo“@sO’ๆถ๗~UšฆIšถHฐ€<ฒe[’5ฯณt$s๖ฐพ?ถl“ข$<ฮz~?ƒฮฐืz๗็๏zW†[•ค‚zฃ|m‰Qฒ5ญu๖มQaทa๙` ัฆุ}8แqฐm๙}>I๎Eฯ_Š(ภ(]ƒ–YŽš”y๖ม›ูสHใ3X]‡ฑzŽ๒ป*ฅo"za ž…ตn#l*Š๎qEิิ0fkDO>=า†0รเุ2อภ(ฌฦ(]^P…โKF๑ฅบMถmห]f9ํJฉ็ตcข–ฝ๐\…aRถ#แ "!ฌฮƒ˜-/แDBณ’dŒ~'ชŽžW‰^ธ-ญลH8WžDXaฤ๔่‘/^Eิ฿~๋ทŽ„&๋cIDA )‰D"™#๗”BJ"‘HbSHd$x๙๛jฺ็ฅ'ื้ช๒xผฤหlฺฆ&็1|% ชปs๔(ฮHัS/œk๖,+n^rเMD/จFKอC/]ƒ–QŠš nŸœH™"r๔ ฌž์มฆ฿zฟQถฯยMn๏ฃฤ ทถc#Bƒ˜0[^ฤjADBry‰แC/ZQr•lŸ๊๖า=`8SƒุรํX}ว>`}ˆ่๔™wƒชขฅใฉŠQฐ5%็lSrv—ๆ5๏+‚ขhว”“~+ BเYฐฝฐ 59ว•…ณป{ +‘ฮDย1฿–˜ŠWeNmw@๐{>ฒqdl<6ว …”D"‘ผ9ง‘BJ"‘HbWHe'๙^_CiZฆm๏zถฉ'xKeq$ผ"2ตอ™ญwFSอึWฑzํืฯ๖9’ผฃ$ม—ŒQ|Zๆ<๔ยjิิ\WL1+ฆฆ†qฆFˆžุŽ5p5!อ…,g!jrฎ+ข„ใ.Ÿ์>„ู๚*๖`3bf}8—ผณ๘๘…U่ลซะ๓– &คกxฮ-›ลlvซู๚ŽcตžmศmUป†ฮTZฝว0[^ฤiG๑&ษ ~ป๗ฅ๐$JBš+ฆr+ฯ๎b ฎด‘ป#_h๕ผvไ‘)ฬึืขวB ๎ฅธนว๏xๅ๕ฺ๕+ช‚รุุ30ศ๗|”ก‘ั˜‹R‰D2G.#…”D"‘ฤฎสK๖๓ฟฏฏฆ$DฤถyๆT฿{ํฤ.วq‚;๎ุ‰๏ฬฮ ˜=G๊œ๑ก:H•g๓…GMHC/]ƒžปุSพd* ธฅfฦA8วAM€๎!ŠจฎรX๛ฐ[SC๎๒<ษฬไิ”\๔ผฅ่…Uฎ˜Jฬœญฬg›ฦ‹H่lฯ/ล“เJ’ู๊Bซๆ้—qF:(ณฝŽd~๘NแIด๔RŒฒตh9 Qท*J8๎†ก!„่๔๏œ๏xQw๕อj„]‘›7o\ฟชฏว wpˆ๔Q๚‡FbrLRHI$ษiŒR‰DปBช05ฟปฎšโิDย–อำงบ๘๗ืO๙๓ฎจ๊lนmk[<ฤpฌพ6เเิ)BฟขทŽYT51mฌ]P…^Tb๘ฯ.IrปŸยม™ร๊iภ<ฝ{เฮdฟQ;กำ<จi…่9‹ะ –ฃe/t—โ้>(ช&fCeEฐ›0[_ล8((ช†Qven๑Jดฌ๙จdPup,œ่”›-2้6ขW4๗=‘VวธQŸRฐT่zธเ[ฎcใ๊•x=}Cร๛C?งw`(&ว&…”D"‘ฬ‘ฟH!%‘H$ฑ+คJIฝi9…ณB๊‰ืพ฿๎็ใ๎ณ4'ObJQช.ฯ์ 5จจzษUxnBฯYˆโK=':P‡์‰>ฬ๎ฃ˜M;ฑGปp&๛])"น๘!๒$ ฅ—ขฏpำงฃx’]ฯโVN9Cญฬ์}1=‚โMFสจ‹‹ŒœE่%Wก ฯํศwฆŠmf13AไะใGฬๆํ_Œgu†[nจฅvํ*|ร#วรฟ ซo &ว(…”D"‘ฬ‘ทH!%‘H$ฑ+คๆฅ'๓•ฺๅค$0cู๊x๗hž๓ตq(ฆJ…A)ฆ.PยเMFห,Cฯ[‚^X5[้‘2[% 8+>Dt {  ณ๓ V็~œ‰œ™ัณหฦ$5) -งฃhz๑*ิ”lU”Yq๘1%Dd ซ๋แƒ‚ชนั%‹žทฃจ5%wvG>aGลิpšš7Tl S* _œ๋๏๏ด๋ฏ^ƒฯ๋apd”๘ูct๔๔ลไXฅ’H$’9๒K)ค$‰$v…ิŒพRปŒผไfL‹_๋เ'‡Z~›„๘vT๓wnซ‹‡ุฮŠฉzTํyฆฟDม›Œ–Vˆ–[‰QT–]โOq{DอŒcฦ™่C๑๘ัาKQ3หPอSŽ™tลTว>ฌฮC8ใr๙ลˆSB=ณฝ`9zัJดดขsป†'ำฃn฿(_สฌtzร๚=gv™eวข-/‚•z‘qBC(šงr+zAuปšœT<‰๗ฦห๘ทƒ=ฌืi*ฟw‰๕Mฏa๓๚ต๘ฝ^†Fว๘ฯGงญซ'&ว,…”D"‘ฬ‘ฟH!%‘H$ฑ+ค*ฒR๙าฦeไ&๙™6-ihใกรญ๐}ยaVฉwTO}ˆฉ๕ตBx‚จl”gy$$ิ@zNza z๎โูFๆธ"jฐซ๏8V็ฌพFิ„tด Œฒu่น‹Q…(š‡3;ธ‰ฐ๛ณ}/VO๖H›ฌ–บ qJFK/v+nสึขe”ขxฯ๎nh6a๕ล๊kD๑$bVใYผ5! ดูส)7ช`8กAฬฮD›_ํU~’ ŠOb๕4ถ+Š ิํพ7^ฦ}พ"๊์o๓๚ตlฝ๖>/รcใ่ั_าาั“c—BJ"‘Hๆศcค’H$’ุR•ูืฦฅไ$๚™2->าส#GฮกHŠ)ษO < ๎ฎm9๎ฮz9‹ฮ‰จHgคซ๗˜ ปฏ๑M๏W“2ั‹V`”ญCห(EMสB๑๘Fฺแqœฉa์แvฬŽ}ุฝวฑG;ไคฟ๕(กxจฉ่น‹0สฏAฯZทrmz{คซ๋ f๋ซุ#ํœi<ฏ๘’ัณb”ญรSq;JีxW@XQœ๑ฌถืˆv’b๊"ฌ(๖`k'แแฏฦ“ˆ๘_ฏรQ‚oeำ‰๋ืญๆๆM๋I๐๙ใ_ž…ืaฏœ•H*":…3ัูuณ้์กV„9ฯ4ฯฬ(มSyF้รหo5>G "Sุงˆžุ=๛aห˜œ'"<ฒงฟหx฿ทu;วโe๏DDaรชnู\Kข?ั‰ ~๘“46ŸŽษ๙BJ"‘HๆศDฅ’H$’ุR+ 2๘หk*ษJ๔11นw3O|็5โXLีฟ•ๅ$1๓?[%“<[isFษ*๐$ธ"สœม™ล๊€–W๙฿Ÿใ. O`๕Ÿ r๔ Dtล๐K1๕{ˆWuว๗ิjˆzPช้gญซYฮoผžค„ฦ''๙ษ/ŸคแTKLฮ‹R‰D2GF*…”D"‘ฤฎบช0“บk*ษH๐26๙}งุtแv rเ0ŽSทใŽญq‘Dีืœ:E่u๏Z1ฅจ(žD๔œ…x*ทbฏ:WiใXˆ๐ๆ้Wˆž|{ฐ้ยํˆง๊(šŽ^ดฃฐ-wZz1hwW>ฮ‰)ณ๓f๛^Dh่ํ –wEœP5ดŒyx+ทb”ฏw+ื !lฤฬ8V_#‘Cฟภ๊oบ _ซeฮCฯY„wู๛PำK[ล”pโฬVO‘#ฟ;โ.ลDๆ“gˆgฅ:"จจส๋ฯwี๒%v๓f’M๒เฏžๆศ‰ฆ˜œ)ค$‰dŽtG )‰D"‰]!ตถ8‹ฟXท˜๔/cแ(?xํ$/œ๎ป_ตหqœ S1ฃo๘ะrใญŠ^ผ ล›ˆขเุs๓๔"วžยlF˜‘‹"‹โKA/XŽžท-gZF Šf „ใVโ„†ฐ‡Nmู๖"2wยCห,วปdv]bบปcกˆHkเ‘ƒbv˜ฉP\”๏7สึโYtƒปิ๒ท*ฆ86ฮ๔(f๛>ข ฟ;๛š๘E„'q&ฟ/B_–"๊ยฐr้bn{ฯR“˜…x่ืฯp๐๘‰˜œ')ค$‰dŽผP )‰D"‰]!ตพ4‡?]ปˆtฟ‡ั™(฿{ํป[๛/ๆWฦ˜Bิฃjทว๔ฝแGห]Œงโ:Œข_*Š๎แเD&ฑ:ixา]๒eNƒs๑—aอ/o Zึ|๔œEจgฤ”m‚ล™รj&ฺ๐$fวธธiฅnฃ๑’ีจฉนณหโ@˜ำุƒอDžt%วบ๘ว“ฝO๙<‹7ฃ๘oSถ…ฤ์ุ‡ูพ์๘ซhแIœ‰ŸŠฉกฏ๊vถลหธ?ฅ`ฉญซ๕*๊-๋;ชW๐๑๗m%%)‰ษฉ)~๖ิณ์;z<&็K )‰D"™#”BJ"‘HbWHm,หๅOึT๐{™‰๒ฏฏ4ฒง}เโ?€!~iชขn็ถญq๑๐5V_[*„ฦข˜า๓*๑,พ=jbŠแCว]๒ี}ุmT=ุŒ m^๚Dฤ“€šZ€Qผ-ณ -{!Z Tl'2‰˜ว๎?IคแษทีX=PS๓๐,จล(]šV„โMBAAXa์มข'ถปห#ก ทŒ๒ญœGน•x*oฤ˜w5ช/47Š)aE;๖avqf7>…wku[<‹(ก๋Aเข฿—Uฬ็“ทLjR2ก้)}zฏnˆษy“BJ"‘Hๆศฅ’H$’ุRื•็q็๊…|Fฆ#|{O#ฏu^ฒ๏w๗YšŒ31Uชrฅซ^P…gมต๎’ธ”<oข+ขฆGฑzŽmy ปbf์Š่ำคx“ัา‹1สึขe–ฃe” &eƒชนb*<39เ๛ษ็ฐš‰}ัก &ga”ฏว(Y–^์V!ฉยŠ`6=2V๗œ๑žูฅ‹—UGฯ_Šw้{c$PUฮŠ)!\6†ู๒V wGพูฑพ[ฤ”Q\21ฟdA9Ÿบๅf))„ฆงy์ู็ูsเpLฮŸR‰D2G&$…”D"‘ฤฎบqAŸ]ต€TŸมะT„o๏9ฮฎกK~๑'ฆึื แ ขฒ๑J;6ฝฐฃlญป.ญี›4+ขFฐzŽaถฟŽ'4„0gฎผฤฤ—์๖/šw5z๎bิ”\T_ h†ปฤpj{คซ๋0f๋+8cฑื๘\QPา1สึนQ้%จI™(ชŽฐM์กฬถืฑบ`อ๎8่\9ปู)D๔)^ƒมฉ0าq๔ _ถใฑเ๏ีSฟs[m\4๔ฝbฤ”ข ็/ร(^‰žท5ฃิญ^13†ี{ซcVIœ‰>Dt๚สOP|)ู่ 1สฏq—&็€nธอฝgขซฏซ๛(Vฯัุ—ข ๚ำะ‹W`”\…–555฿9ฯ1qF;1๗buฦnล™ฟ$}ขXTิฤt๔ผฅx–พ=wฑ๏JQฮฝๆL๖๎รDOlว ก๘’c๎:?'ข๚๏ิฝ7BแrŠจ3,,+แ๖พ๔ิTฆffx๒…yแีฝ19ŸRHI$ษ้„R‰DปB๊–สb>U=dฏม@(ฬ{้‡{G.๏ร›รธญR_bjรญB๕จ”\า/ึ ๔ฌ๙่ล+ั๓–ขe•ป" Q}X]]5ึˆ„bkb5ี›„–ปุญ&*ฌrล”ขธ=ฆ„ภ๋ฤ๊iภj฿‡=ิŒ3=z๙—ถอ•p๙R\iXฒ -ปย]žงyยฦ™์วj฿‹ูuุํ็55ถ#1าัRr%ขKnFห(E1|œ๋/ๅDxณ}‘ฃฟUu›๊_แK๘คˆโฒ๏2:ฟคˆฯ|่คL‡gxz็ห์ุ๓ZLฮซR‰D2G~$…”D"‘ฤฎ๚เ’>^5dฏN(ฬ?ํ>JC•แ€โSL]ปM=xฑล”b๘ะ2สะ๒*ั๓—ก็-9[y"f&ฐ๛1ป`๗7bด_‘‚ๆ-ื›ˆโID/ฌม(น =)jRึ์‰f#„ƒ3าีำ€y๚e์ัNฤฬ๘•ัห—‚žฝฝ`9z2ดฌ๙ {ภqSร˜]]กึ{gฒ/vDิง๎EMอว([‹งโ:ิ@แ›wไsœ๐8ๆ้=˜ํ{มŠp%๖–ŠWp็]_฿&%จr‰ๅ๚๏`^q!Ÿ๙ะ๛ษL 0Ž๐ฬ‹{xๆลWbrnฅ’H$’9๒)ค$‰$v…ิmหJนmy‰†Nh†ภ๑+ห‡qEU๊ž์ๆ{ใๅ|šS๕บบ@๑$ ฅกๅ,B/ฌBฯญDIธŒLc๕Ÿภ๊9๊๖:}E๖ˆzGใ๗Pา0JVกผaB ์(86๖p+V๏1ฬฆ]ุใ=ˆ๐\†\G๑%ฃe”ข็-uc•ตผ ฎˆ ปช๛ˆป‰“—•Iิ4yi฿!yz{Lฦ@ )‰D"y3RHI$ ฑ+ค>ทบ‚›* ๐jใS|ํนCtOLวjvi มง?ณ%.๖Y1Uช‚ชป$™๓๐.‚^Tใส UC˜๗!ฝทhำ.ฌžฃ—ฌRฌขฆๆฃ,ว[นีญ–JHCQuPUDt {จซง{่4VืAœ๐ไ๙๗/RToZ ฯย๋0ึขx“Xู&bzซ๗ัฆX ˆศค ศsจ๚่…Ux—ฝ-ฃ Ÿ#Eu๛€M c๕6m~1=๚Žล”O…์้ม๏2๗ญ@ฮฑx™๊/~๕›ฅaว ทวโ๑gฆ๘“O~„์,ขฆษžGx๘ษgb2RHI$ษ)R‰DปB๊Oื.bห‚|ผšF๛Xˆเs‡่›Œี†ฦ7ถฌผฏ"+%hจj[<œ{ใถฅVM[๔,ปyฃQถล—Œข๊ฎ˜qwc‹žี}DŠจ?œึณ—ฒฆฃg–ฃ็/ร˜w5jjž+ฆPˆบฯอ๎#X=Gฑ{Ž๕{vปS@ำQ“s๐.‚g๑*Šๆวย O`ถ=4fว)ขฮ7b$๔œ Œ…›ะ๓—ก&eบs +‚3ูีuˆhำ‹ ๐–๛Kลซˆฒmปดฝง/๘๛z๛๔L์.MKMแO?y9ู˜–ลk‡๒เฏžŽอ˜H!%‘H$oฮค’H$’ุR_ธz17”็ahmฃ“๏‡œŠ‡$ฏม76ฏ`Af –ใทซฝ/xcyA[|ฌใเ˜๐ณโUDฝx๐``๕’%A]ำฟุูวฟ๘!&งb๗‘šœฤŸ}๊ฃๆๆ`ูฏ9ฦO26o๑RHI$ษ›BJ"‘Hˆ]!UwM%›ๆๅah*งG&๙๊ŽƒŒLGb6ฉ>๗lฎก<#ำvฺุว?ฝx์>Ks‚;ทmm‹‡sั<๕|mค๑น{ญฦ™ว–่@  ็,Bหฉ@ฯšš^โŠ)วBDฆ\15าy๚eฬ๖ฝ8}๎๛’ณ1ๆoภณ -P่6ใFAุQœ‰^ยŽy๚eDtๆ—I~OfชเYxžล›ั2ๆก๚SA3fใยํฤj฿‹ูwEU฿๔๖xQ‚ม€ึ๋>ม›๋ึT/Mี5ฎ~ํว?cl2vซ๕’๘ยง?FQ^.–mณ๏่1๎์ื19)ค$‰dŽŸ})ค$‰$v…ิ\ฟ„๓rัU•–แ ๎~€๑ฐณqศH๐๒ตj(KOฦดžo้ๅ{Ž#ฦm•zG๕ิ๏V™c๕ท กQ)‘W่K{ะา‹ัrฃ็-Aห(CK+D๑ฅ€c#"“83ใ8ฃ˜]‡Q4ฝจ-ฃล—‚ขhณ"ช่๑฿=๕":‡;็]‚Hy็'#Œ IDAT๐,น O๙ดดboจฺo-ดฺ_ว์>‚š˜ŽBLTL }%Pทณ-^ๆ้ŒˆาT๊PI๘๛ถฒถz9†ฎำ30ศ๗๘รcใ1;พŸ/qJ๒๓ฐl›ƒว๙ัฯ“c‘BJ"‘Hๆ๘ฝ—BJ"‘HbWHอตKูPšƒฎช4 Mpืณ๛ EcทJ#'ษO๐†jJI˜ถอ๖ๆ^๕•ฦณO1uํ6!t)ฆ.h๖ฃขe”ข็/E/ฌA  ฆไบาC8+โV;)šป3œช!,ท"สly™่้=8ฝˆฐ์uฑQ3๐.?z๑ชู 5ฟ๘L๙“˜'ŸฟฯlŒ'๐นปฟ^‡ฃQI=๓฿nปy ืฌฌยc๔ ๑apd4fว่๕x๘โํงค0วq8t$๙ศใ19)ค$‰dŽ”L )‰D"‰]!๕ฅหธฆ$MU898มWžฯŒปKผ๒“๘๊๕U”’ˆุ6ฟ9ีอ๗_;๙ฆืSฯvK0ฮฯฑ๚ฺ€ƒSงฝ๎Ÿ’wˆf ฅ— Va”ฎEหœ‡๊KU็l)!แIฬŽ}DO= gz๔๗4?—\”Peฮร[yzQ+ ภ}ยŠร฿Osq็]_฿&%จ๒fIกฏgรU+๐z ๚‡๙มCา78ณc5t/n๛eE8Žร‘M๐แ_ฤไXค’H$’7#…”D"‘ปB๊ฎMหY[”…ฆ*4Œ๓ๅg๖ตc๗Aน(5‘ฟปฎŠขิDย–อS'ป๘แSฟ๓๕Ž ]U”เณŸ|o<œงRL]„Dศ“€Qrฦ‚Z๔ลจ‰้๎าฐ3މwณc/V๛^์‰>ฤฬธœผห€^ฐ oๅอ๗้๙K‚j ฐ-žฦ๛Dิnผ‰kVโ๓x่แ฿9=ƒ1;fUU๘หฯ|Šyล…Gp๔T3?๘้ฃ19)ค$‰dŽ&…”D"‘ฤฎ ^_อสยLT กŒฟอพ˜ŽรŒdพRปœผไfL‹วŽw๐ใƒ-็ผ*h๊v-วรy;V_[:+ฆn—W๑y&>†-k>zมr๗_๎b‹@ fฦฑzŽbท!ฆFฮพNM+Dั wวC!ๆ fkX]‡0; fฦถ)—๑],โXDฉŽ*ชฒ๑|฿sำฦkุผ~-~ฏ—กั1๓gำึำ๓๐ลmŸ`ai Acs+฿ษรฑy๏ัดM฿๛/๏”ดD"‘ผแ(…”D"‘ฤฎ๚ฺ 5ฌ(ศ@Ž๔๒ๅg๖วt*2S๙Rํ2r“L›6ด๑ำรญo็ฃv9ŽqวึธHฅ˜:„ว๐ฃฆข็-ล(ชAหซD๑&ก  ขSXฝวฐบb๕มnGXดŒRิ”<<๓ืฃๅ.FKษMwwไ3รsณ๕UฌžฃXGpฆ†])%sซ ƒQ฿๊{ทlXวึ Wใ๗นB๊ŸŠ–Žฎ˜ž/|๚ใTฬsW)ž<ฦw๎(ฆŽ_UUV-ซคfษโM+*+vส ["‘HŸI!%‘H$๐ญ]Gลฎึ>l'ถ๎‰๗lYAu^:‡{Gธู๋1‡ส์ฺ๋ฅไ$๙™2->าส#GษGฦ™˜Z_+„'ˆสFyUฯ&:†5%-งฃจ=JB( ˜aฌ“ุ}ว1;`๗Ÿrwุ๛ญงI ={ZFฦผkะาKPSrฦ็Žw›žทฝŽืˆีsิS’ทOœŠจฯ)Xj๋jฝŠzหŒ๋ืญๆๆM๋I๐๙ใ_&#nแฑcไajชR๗์ถอ‡โแ|–bสํฅ$gฃg/@/ชA/จBMฮvETt{ด{ฐ‰hหKX]‡ฯkนžท=o ฦ‚จ iจ‰™nล”mแL แL cuฤ8…ีsT6>ซ8ด+ŠYจ{๑๑x๖็ฟ,บq…ใฦี+y฿๕I๔๛็ว~อ‰ำm1=?๚ษจœ?EQhj๏ G\๑วผta9kซ—SRGjr2CG6ฉชฒS^่‰D๒†|M )‰D"!„ˆุ#ำNMฐฃน‡ฝ]CWqk๋J–ๅคแ๛ป‡๎ˆm฿R—ฮฐ„ฌD““๛ด๐ฤ‰ฮ ๗ผ+ธฯาœเฮm[โแผžS๗ข๎]นuจ:jb:ZF)F้๔ขจษ9(ช†0ร8“}Xง0[_ม๊:„ˆNฟๅฏะ‹j0 k0ๆo@1(T๋Šฉะ๖X7V็A์กฌco๋;โ ‡vEฑ‚บ๗ฦำฐ/คˆ:ร5+ซนu๓&’›˜เ'ฟ|ŠcM-ฑ=OŸ๘0KฬGQZ::๙็=ภ•๚ฒdA9ซ–UR^\D % Cื0-‹‰ะิฆฌ๔ด๒‚—H$’sH!%‘H$ภŒi ฆต†ง#ewk+ฆEแทฎค2;€์ํไkฯŽ้8ฌ*ศ ๎š%d&z›hฟ9ี}แŸใNL]ปM=๘ฎSŠŠโKAK+ฤ([‡Qบ55E5v'4ˆ=ุŒู๚ f^Dd๒ฅQถฃไ*Œาี๎Ž|žWL9๖xŸ+คบbตbฬฑ0‰Sต- ่aฝNSฉC%๕B~๖š๊e|x๋๕$%$2>9ษฟzŠฃ'›czพ๘ฃd๙ขจชJkg7๕?zหถฏจc\4ฏ”ซ–/กผคˆด”d<†(XถลDhŠถฎ4žt็mุ)/|‰D"yC๚&…”D"‘ภฎึ>Q‘™Jš฿ƒกฉfh*ยฑ1^h้ๅP๏ศuฬบช๒ถฎdqv*ถ#xตsoผp$ฆใฐฆ(‹ฟธz1 ^ฦยQ~๘๚)žk้ฝx_(ฤทฃš7ธs[ํX<œ็๏V1ฅxPSr1สึโYxjJ.ŠๆA8&bf {่4ๆ้=˜ญฏโL^ุ/ื <๓7`ฏB/ฌrฅ๋>Pu„cโŒ๗b๗5bฮVLู#เX๑}ร•"๊‚‹จ3ฌZVษm7o!91‘‰PˆŸ>๑5žŒ้yปใถPตx!ชชาึีรท๏}จi^ว6ฏธซk–3ฟค˜@J2^ข(X–อไิฝ์o8ฮ๋Gฐ›ใžปwสŒK"‘HรI!%‘H$p๗ณDfขีE™ฬOO!ี๏มฃ*8ย–อะt˜cc<ิร๑+ร]xuธq%‹ฒRฐมžŽAagl ฉซKฒ๙๓u‹I๗{›‰๒ฝืNฒซต๏ข~งpทU๊ีSbjฌพ6เเิ)Bฟhล—(…Aั ๐๘๑,„w๙-จIYฎˆ6":…=ิŠูผณ๕œะEฌtTTิ„4Œฒu่…ี่y•๎2>อB ฌœษAฌžฃ˜๛ฑ๛O\ในRqŠUŸ^ท;Oรพ"๊ 5•|์ฝ[IIJbb*ฤ#Omg฿ัใ1=Ÿ๙๐-ิT.BำT:บ{๙—๛สL๘๒V–ไณถf JKศคฮŠ(หฒMOำ?ศ# ์;zl5—R‰D๒ฆJ )‰D"ปž= ฆM›ฒด$ึgQš–DŠฯƒGSqAุฒ้อpดo”อฝœบผ ‹=:฿ุฒ‚…™)XŽเฅถ~qwCLวacY.Ÿ_SAš฿รศL”๏พาศหํ—ฆษผSฑ”ฝ((ž$< 6โญ€#J๗ ยŠเŒv9ฑณy7Nh๐า–๎E ธีRyKะฒ $คกhย6‘bjณ๋Vว~ฌ†๘่/5+ขTิ๚@ฮธจF<รw}}›P” สฅฉJ\^ฑ€OrฉIษ„ฆงx๔้ผv8ถnเ๛Xนด]ำ่่ํๅ;๗?ฤิ๔ฬe9–‚œlฎ^QEลผ2าx Šข`6S33๔ r่๘I^=t„H๔ทซธค’H$’9r')ค$‰ไœ:CฤฒฉศLeEA%iI${ Œ7TL๕Mฮpธw„g›บi ]–cN๑ณe๓3Rฐ‡ญ฿c๛มใบ๒<๎\ฝ€ฯรศt„o๏iไตฮมKz ยa•เ๖ฯnฉ‡sฌพ6 „ขj_Œ‰ฤล—ŒQบ๏า›ัาKQผ‰ จฎ๐ i|†่ษ็p&ภq€KŸ็($ดฌ๙…UhY ั2Kฯ๎ศ'ฬ0bfgzซc?fว>ฌ๎ฃ—ๅ8/:RD]2u†% ส๙ิ-7HI!4=อcฯ>ฯžฑ[๐n}W-_‚ฎ้t๖๕๑?ฬDh๊’CNfืฌจbั22ำx=TEลvlฆgยt๗ะpช™—๗"‰ฮ๙RHI$ษ9“R‰D๒f!u†จํP™`yneiI$y tUม‚ำSz†yฆฉ‡ฎ๑K› ง๙=|ms ๅ้)˜ถรฮึ>๙ฅc1‡๐ูU H๕ ME๘๖žใ—ญฉผ#hW%๘์g7฿ืภX}m้ฌ˜บJ<>ล—‚QXQqzฮ"wIœช!ž zข'ถใL #ฬธ๒5! -)zn%z๖ิิ|ิฤ ะ Dt'4ˆ˜วl}v)฿ษwวษว"๊s_น็VGฅR‹จ3,*/ใำทพ‡ดิTฆfฆ๙ีŽ]์{ ฆ็๔“๏ฟ‰ีUห0t๎พ๛“‡›˜ผ$฿‘ฮบšๅT.˜GfZŸื‹ฆjุถอt8L๏ภ GN6๑ฺก&ง~ …”D"‘ฬ‘฿I!%‘H$ฟ[HEภ‚ฌj๒า)$‘ไัั5q˜Šฺ๔…ฆู฿5ฬณอ=๔L\š%8™ ^พถน†าดdLๆน–^eOcLวแ=‹ น}ล|RผƒSaฟ—Žqฐ็๒6“—b๊2'*พd๔ๅxๆฏGหY„š˜ข๛>QำฃD›važ~{ฌ 13ยนโๆTMHs{Kๅ/Cฯ]Œ’†š๎VLEงq&๚p&๚1[_ม๊>Œ=ฺป'c[Q”`ผ‰จ;๎พงVuDPQ•—๓8–•p๛฿Gzj*ำแž|แEžeoLฯํว{#๋jช0tžAพ๗ภฯปธKๆ3ำฌฉ^ฦาๅdgฆใ๗๚ะ4หถ™ ‡แศษ&^=t๔ผๅ˜R‰D2Gž'…”D"‘œ‡šES*ฒRฉฮKง 5มSชŠๅฆขS์ํโน–^๚&/n‹œ$?มช) $aฺ6ฯ6๕๐WOฤtnญ,ๆ“ีๅ${uBa๏‹ ้ฝ"Žอด#œm;๎ุc๕๋k…๐Qน,ุŠ'=)Fูี่น‹Q“ณQ<‰ณ"jณ}fหKุรญ83c`_๙;ืฉ)น่U่๙Kั ชP}I($P5Dtgข{ฐ™hำ.์กำ๎ฒรXมฑ๏›Qm๑๔qฅˆจ3”—๑™ฝŸŒ@€™p˜งwฟฬ๖—^้9พํๆ-\ณฒ aะ30ฤ๗|„ม‘‹๓ปHNfŠๅTฮŸG^v&~ŸMUฑm‡™H„ม‘QN5ณgaF'&าgK!%‘H$sไ{RHI$ษ๙ ฉ3hชBev€ชt๒S$:บช` A(jั16ลพ๎!ถ7๕0<}qvสONเซืWQH"bๆT7฿-ถ—|xi)ซ*#ษฃำšแŸv7pฌŠ+ดุๅ8NPŠฉ‹”˜hดผJŒฒตฎˆ ขz“ยALb๕4`žƒ5ุŒ3ูถ;“ฉ(๎#P€^XใVLี ~ท)ปข!ฌ0ฮx/V๗"วƒ˜ฦ™พrวง"๊ฮปพYฐ๋ฏu†าย|วGn%3-ภL$ย๖—^ๅ้]/ว๔\่ฦู๋pี ผƒพมa~๐ะฃ๔ ^ุk"ม๏cช–-œOnVฦฌˆาp„C$ฅx„-ญผดรฃo๏7I )‰D"™#5’BJ"‘Hบ:ƒกฉ,ฮNeyŽ[1•`hจŠ‚ๅBQ“ฮฑ)^๏โ้S„"๖มน(5‘ฟปฎŠขิDย–อS'ป๘แS1‡U•๑‘ฅฅ$ฎ๚ึฎฃœฟR7ลิฝจฏ7ŽžSQถ-o‰ฐ— €˜ว๊kฤj฿‹ีgผa†cw2Uอ‘/ตฝ`z2Œโ•(†o6;SŽ…3ฺ…yzั–ก!œ้1ฎ˜ๆ็q*ข>ฅ`ฉะ๕ pE๖Z+ฮฯๅŽ>@VzแH”็^y_?ฟ;ฆ็ึอ›ุธf%>‡กแŸำำa6ป๐yฝฌซYNueyY™$๘}่šๆ๎ฌu+ขNดด๑๊ก#๔ผณ~†RHI$ษ›‘BJ"‘Hx๛B ฦ็ฆํฐถ8‹št๒“๐:šฆ#EL:ฦงxน}€ํM=L›fiQiZwmZNaJ"3–อฏ;๙ฏM1‡?ช)็•ล๘ ษiพน๓(อรW๚a๏Šชฮถถฦลƒ๙Xต„ะƒLL) ZFzQ zRทว’? a๗Ÿฤ์:ˆ{{ด™z๗Lฆชกx“ัา‹ฦ็หั‹V h@€pVgข—hใvฬ๖ฝn#๔่ิๅkฺ๎ฐKQœmRD]™ไd๓ว๛ 9้„ฃQvพบ_๎ˆm๒พ๋7rบซ๐y< ๒ร‡AW_;๚LฏวรUห—ฐr้b๒ณณHL๐ฃk:B8„#Q†วฦ9ีฺฮ+ำูAฦ!…”D"‘ฬ‘J!%‘H$๏LHa2bโัTฎ.ษฆ*/œD~CGULa"bา>bwk;[๛˜1ํw๔}๓า“นkำr๒“˜ฑl?ฮZb:Vฮ็‹‹๑๋ำ|ใ…รดކbโุม}–ๆฅ˜:OT]บ–ฟิWXใŠ(E่ ึ`3V๗aฌ๎ฃุรงแษw๏d**ช?-{!z๔ฅhน‹Qt/ยŠ "!œฑnขง^ภ๊:„3ูiซฤv)J4จ{)ฎจทƒฉ…/ฦย๑ๆeer็ว?Dnf‘จษ๎ฝ๘ล3ฯลt ณi7\ฝŸืรเศ๙ณวh๏้}[Ÿฅkkช—Qฝธ‚ข’ ่บ[1ฃŒŽOธ"๊ภ‘ทฟ )ค$‰dŽH )‰D"น0B๊ “ŸกqMq6ห๓าษJ๔แำ54ขŽ`2ฅyx’=์h๎ลrฎ` 2S๘๒ฦๅไ%๛™1-~~ฌŽ้8qีBSQˆOื่Ÿโ๋/ฆc,ถ*bม}ŠAp๛งทดฝฏ›ฑ๚ฺ€ƒSงฝ•ิ๓z“f &gฃgW VนKี3P aGฑ‡Nc๕6`uย๊?OฤัHAMส@ฯ_Ž^Tž]š^|NLEฆpฆ†pฦบ1OฟŒี{{ผ็โ๖ัŠSu็7พp&Eฆr็๖@vF:Ÿ๛๘‡ษฯฮ$jšผด<ต=ฆcฑ๕ฺซูฒa~ฏ—กั1๋‘_าฺี–>CำTV/_JueEyน$'& kB@ิ4Ÿ ฉฝƒื7ะ~qvน”BJ"‘Hๆศ|ค’H$’ +คฮ01I๑ฌ)ฮbYNY‰>ผบ†XŽรX8Jห๐$/w ๐BK/–๓ึaQV*ปqนI~ฆM‹GŽถ๑ะ‘ึ˜Žร็ืTฐua^Mฃ},ฤืž?Lฯฤtฬรซk|๓ฦ•ฟ(+ฅPีฑw๛๕s^bJำQาัฒสั ช1JVกฆไกจยฑqF;ฐšฐ:๖avxwWDjr6FษjŒาีhe(I™oS“ุฃ]8ฃ˜๛ฐ๛O`๕€p.ฤฉˆฒl;ะี[๗/๗>X6ฃฉฑviไ!?; ำฒxๅเa๚๕31“อ๋ืrำตืเ๗๙ใG?-็)EaๅาลฌZถ„โผ’1t˜Q4ทw๒๚แNตถ_ิqH!%‘H$sงฅ’H$’‹#คฮ01 ๘<ฌ-ฮbiNY‰^ผบๆ&ฤถร๘lลิฮำ}์n๋็|๏หKrอตKษM๒ŠZรŠ‚˜วnล8…ี{ {ฐg.3r8ฌ(ับxQ‘จนMืด๚๖žิ๏Sฆgbฏq~ %™?๛ิG)ศษฦด,^?|”~๕tLวๅบuW๑žMH๐๙็พ_ม๗ฏZVYขk:ฝ}๋br*๖ช3“๙๓O”ข\,b฿ัใุฏc:>ืฎ^ษ๛ฏ฿Hข฿ฯ่๘8๗?ไ๏•HKฮ็ชๅK˜WT@jr†n`Z&ใ“!ฺป{ypGN^ฺM@ค’H$’9า)ค$‰ไาฉ3LFLr“\]œอยฬา^ผgฤ”ๅŠฉฦ1vž๎ใ๕ฎ฿PY“Ÿฮ_ญ_BVขษˆษ}Z๘๕‰ฮ˜Žร_ญ_ยฦฒ\ Mฅed‚ฟ{๖ cแhฬ#ี็แžอ5”gค`ฺป[๛๘/C8Œ+ชR๗์g7วลCฬฮ๏” ฎ j™ๅท+บ!Dx{คซํ5ขMปpBƒ๒t>จ:8z2Œาี่ลซฮ‰)UsลTh{จณ}Ÿ+ฆF฿ฐ+กฬq›‹s%%จBษงn}ซ—/Aืtบ๚๚๙ื?ฬD(scJ๔๛๙๓OŒ’<,ๆภฑF๎๙ฏb:Nืฌฌๆ[6‘่O`lb‚?$ว›฿/qษ‚rV.]Lyq”ไณQฆe3 ัึหc8ึxYทR‰D๒fค’H$.ญ:C(bRœ–ศช‚Lfฆ’ๆ๗`จฎ˜Šฺ6CำŽ๗ฑซต}รozส‚ ๒š%d&z™ˆ˜ืพ&~sช;ฆใ๐7–ฒก,]Uišเ๎ํ˜Œ˜17Žtฟ—ฏmฎa^z2ฆํ๐ย้^๊_>~ฮฺUE ฦ‹˜ย6kEt*huo4๗=๙<ฮX—ผ๑ผญฬMEั Œา5h๙K1 ชPS๓Q /แJฟฉa์แvข-/b๗5bvผก๚lVLลฑˆบใ๎{j5D=(Ug'kช–a่:O~ฦ่D์5ิ๗y=ลํŸ ค วq8x$๕ศใ1ฏตีห๘ะึ๋IJHd|r’Ÿ๒)N5Ÿ๛‚าbึV/ฃผคˆด”d<†ข(˜–ลdhŠ๖ž^;มพฃว.kฆR‰D2GZ#…”D"‘\!u†Pฤค,=‰•™,ฬL!เ๓เัTfh*ยฑ1v4๗pดo๔์๛Vf๒ลk*ษH๐2Ž๒{›ุัำq๘าฦe\S’ฆ*œšเหฯ`ฦดbn™‰>พvC5ฅiษ˜ถอŽ–^พณง๑Mฏ‹715yงjญแž *ๅ]็fp Š/ฯยZดŒ2๔ลณbสŽ…ฐขgwไ‹žzซฏัํ/็"JuDPQ•7{๏ฌซฉยะuz๙?cxl<ๆฦh่:_๖ สŠ p‡#'š๘แรฟˆ้ธญZVษm7o!91‘‰PˆŸxšรง˜WTภบšๅฬ/)&-5ฏวƒข(X–ลไิ]ผ~ธ วqœหผ#…”D"‘ฬ‘ฮH!%‘H$—WHa*jQš–ศบโlสา’I๕ปbJมŒi38ฆก”ํอ=4Œsuq6~๕bาฦfข|๏ต“์jํ‹ํ8lZฮฺข,4Uแฤเ8_๚อ~ขถsใศI๒ผกš’@ฆm๓lS฿}๕ฤ๏|ฝ‡qœบwl‹‡•ฑ๚๕ตBx๊Qฉ’wŸwšษ)จIูx—„šš‡–ต5%วํ/e[8‘ฮไฮx฿x๔ไ3๕N฿ษ๚”?๙XลผโB„#8zช™๔ั˜Ž฿Š%‹๘่{o$%1‰‰ฉฯ๏yฏ๚U: IDATิ”d*สJHคโ;+ขlB3ำ๔๔์w|ี™ฐŸ™u๏•ฎzต%Yฝหใ ๔†B ‰๗๛๖๐ )ฺ…dูvฟษฆgC ฝwlllใnฒeษV๏ฝ]้๖2๓!ษ@ฬn7}ž?m™๓ž๗ฬ™็พ็๖Wื๒QU5มะิ๙AC)@ ๘œว!ค`jฉI|ม0Yฑvๆฆล‘mรn6b”%ผก0}./Uร z|\S”Nดลศฐ7ภo๖c{Kฏฆ๓๐“ๅeฬ›N‚ฃฝ#๐ฝ(žJฑG๐ำeค;l๘รaซ๋ไw{‘nSฅโยS‹ืฉชพ™tq:UกG†ฑ่2tQษศŽ4d[<’1ยI8Xฉx†+e{ย%ข๎{ "Cี๋+€;ึ฿^ฟv%‹ๆฬฤd4ะ?ภ๏Ÿ}‰!MฦฝฎศIŸŽชชิ44๑›ง_ะtห๒sน๕สK‰ฒวซŸ"ฬๆQแpทืKW_?‡ีณ๋@ภิ[{P)@ 8!ค€ฉ%ค& „รไว;(OŽ!=ฺ†dภ0!ฆ|มฎ@‡ลˆI'3่ ๐ซ]5์nำ๖ั+ห™‡ ้ๆ๗๖k2Žดจ~ฒผœ้QV|ก0๏ึu๐‡๊พฬ!„˜|ต;ƒ]l:†œๅN]\Fฅฮ1ญRŽL"๊opํ๊ๅ,ž7“ั@ฯภ x๎eบ๛4๗๏ผ…ผฬ TTj›๙๕Sฯk:Ÿ‹ๆฬไ†KWb2šUU'D”‚ว็ฅณง๊บFvฌยใ๕Mู8„‚ฯynBJ ฆฆ:๑ซชไลEQ–MFŒ ปั€~BLษ Ixƒ!~ฟ๗8๏j|Q๓‡VอdfJ,Pี3ฬ6hSHฅ;lxY)iB๊ญcํืพ/ฟลธข๒DHงTl]ทถๅBธ‡*WHช~=2Qโฎ๔QpชRจRgŠฌŒ๚๖[BD}AฎZน”ฅ ๆ`6้โฯฝBgoŸ&๛แ;n&oFuอญ๒‰g5GBl สK˜SRHBl ’$qEมๅ๑า;0Hีฑ:๖ชึฤŽˆBH มษ!%Lm!uโ†DN\$ณRbH‹ฒi2 “วะUUฅsิรถๆ^o่ขkิฃษ<|๕,ส’c8ิ=ฤ7ะd™ั6\VFjdP˜7jx|รWw ˜ฉ\๊PPึ 1๕UJ๘ I’*๋ทถ\Haฏซจp่}๚๕:™ฏล[ถk./BH มษ!%hKHtzX:#‰›K31๊uจชzb _XQqCดปุ฿9ศปu8})“$Iหฺู%8P€}ใๆCšOนq‘<ฐค”dปo0ฤKG[yๆPำi9ถชเ หT*ฒฑr๋บฅ็”ฌ‘สฅชชV ๋๎D๐Y.PpฯWœ5ษฺลฑ๚’…XL&†G๘๓‹ฏำกอ)ะ๗|ฅy9HฒDS[> กpxสถ7ยlๆขูe”ๅ็’‹ลlF'ฏ๙~F]nข์6ฬ&^Ÿw?ษ๛;๖h./BH ม็< !%ฺR=c^ๆO‹็ๆฒLlF=ž@ˆAฏŸh‹‰ƒY‚ะDลT๛ˆ›=ํlจ๋ฤMู˜๔ฒฬ#kgS˜EX…ฝm<ผฅJ“ใ)?>Š.)!ษfม ๑โ‘ž;|Zฯ!ฤิฬ,ข๎}๐กuช$Uศœ๐W/Zภฺลc1›q๒ุKฏำุึกษ>บ็ฦk(+ศE–eZ:บ๘ๅฯเง\;อ&๓หŠ™U”ORBV‹ฝNช*๘๚‡‡9ุB{O/W,_L\ดฏ฿ฯฦํปy๏ร]šห‹R@p2BH ฺR}. งวsCI==./Ol$+ฦNyr ษv ƒY–†ฦAฺF์h้esc7žเิSfฝŽ_ฌ™M~|$aEeW[?ผ๕ฐ&วSa‚ƒXRLขี‚;โ๙รอผxไฬธƒ PL•ซช\‰ฬ’ ๎FฅฐM’”๕Ž๕[]hกŸ)5ษŠ…๓ธlู""ฬ†FFx•7ฉoiำd_uUฬ,ฬGง“i๋์ๆ—O>‹ื็Ÿ2ํ3 ฬ/+ฆผ0ŸดคฌŸQCN'ว›[ู} Š๖๎^าS“๙ฦ ืใภ็ฐiื^1eO ฮ„ด'ค>.JOเบขt,=c^ูv˜บQฒb์ฌฮIฅ,9šซ๙3bjิคyhŒญ}ln์ฦš:ำ8ฌF=?_=‹ธHBŠสŽ–^๕รjMŽง’คh’bmfฦ!žฉjไีฃg๖ๅVQi•%ฉbใซฟฎู‘สEKUีXqAˆ)…m’จpฌ฿qมฝฬ~๋G_ญศTž)5ษา๙sธ|๙bฌ CN'Oพ๚ว›Z4ูgw^{ณ‹ ั๋tดw๗๐ซ'Ÿรๅ9๗]่๕:ๆ—•PšŸCzJ2ถˆtบ๑ฉy`€a็(uอญ์=T™้’ำ’น็ฦkIˆฦ๐ม๎ys๓6อๅE)@ 8!คํ ฉAŸE \]˜ŽEฏฃkฬร/ถฆq่“‡๒ใฃX‘•Lir ๑V3fฝY‚ ข2๊ P?0สž๖~67v +็<ฆ(ณ‡Wอ"+6’ขฐญน‡฿~T“ใฉ,9†ฝจˆ›™1ง6๒Fm๛ูqฆ˜ชDฆ์ผ ๎Q๗๘แฅฒขVHฒtV„ใ%sgqีส%X- Ž๒ิซoQุฌษพปชห˜WVŒ^งงฃท—_?๕<ฮ1ื9k,หฬ--bVQ>ำ’“ฐ[#ะ๋๔€J dศ9JCK>๚นUi)‰๑{ำu$ฦลเ ุถw?ฏฝฟEsyBJ NF)@ ~ดaฟ:น[๖Xœ‘ศๅำฐ่utŒบ๙๙–รด ŸาQœอ๒ฌ$Jฃ‰ท™1้tHร #พƒclo้eksaๅ}'ฤD˜xhๅL2c์ร [šบฉYฃษ๑4+%–ฟ[THผีฬจ?ศใ๛x็๘ู]FQiึo๚ฦ๊ื.„kxคr๑:UีW ŸูJšณ“šรทnนž”„8ม ;๗W๑ย;5—!คเd„เ๗๖ซ:Y;Bสฒ$3‰ตนฉ˜t:ZG\ำUtํuBfฅฦฒ:;…ผ๘(b,&Lz๙„˜๒๘ฉS{๛ฯjLษv ?[QNบร†?fC]ฟ{L“ใi^Z?ธธุ#พ๚ธžM ]็บY”˜ช\\!ฉ๚๕ศDM๙ฦ*ดJRจยฑรว/ด{๏}Tdจz}pNwOœ[Zฤ —ฎยnตโt๑์๏QuฌN“}zฺ•\2g&&ฃžA~๗์K๔ ž•s็f3งคำาpDฺ0่ €J0bิๅฆฅฃ‹}Gj8T{ 36ฺมทoฝ”„x‚กปV๑[4—!คเd„เ‡๏ํS๕ฒฌ™๖บ!–อHbuN † !Uฑ้ฝ.๏>ฦE้ ,อL"7>’hณ ฃNF’ภR๔๘ฉํa[su œ•˜าขฌtyำขฌ๘Ba9ม?ึๆ แย้๑ฟฐ€˜#ฟ๛่8[›zฆJ๓ถ!K๋7ฎ[u๏ิ6Rนิก ฌŸฒbJˆจ ฮฑˆšdVQ7]พšHซQท‹็ภมm ๑ซW-cษู˜Fz†๘ร๓/ำี{f`(ศสdniYำงแˆดa4‰`(ฤ˜Ms{'‡jณฟบ†/๛๊แˆด๓o"51`(ฤGUGx๚w5—!คเd„เผปO5๊ด#คผม0หณ’X‘•ŒAงฃexŒŸพฯ—ฺ[g&qqz๙๑Q8,FŒ:U8ฬ วOM๏[šz8ะufaฯˆถ๑เฒRา"ญxCaชm็ฯ๛๋59že$๒๙D[Œ {fฯ1ถท๔N-ข๒DHงTl]ทถๅ|ฟพOˆ)Iณฉั๙ฎˆZWQแ0๕’ฤฆRปส ๒ธๅŠตDฺlŒนผ๐ฮF๖ัๆvWฌXย๒s1›Œ๔ ๓ง^กฝ๛ฬฒฆงqัฌฒ eวd4 IกP˜Qท›๖๎๖ฉแใร_}ƒŠH›•๏}fา’ …C||๘(Oฝ๖ถๆ๒"„”@ |ฮปˆR@ =!ๅ…Y‘ยาฬ$ :™ฆก1~๒†ฝฏ|ฬe3’X’™DVฌ‡ล„Q–PT๐…ย x|ิ๔9ูPืIM฿ศ™yฑ‰ฑ๓ฃeฅคุ#๐CผVฦ“ดนจ๐’ฬ$พ=?‡ลศ7ภ๎ฎeื9Z›๋oบ‘ KLeจชZฌ;7U9 ฮ UyกcืUT8๔>zฬ”ฌV+อหแึซ.%สfวๅq๓โป›๘จชZ“}}ูาEฌผx>“‰ก๋ลWiํ์>ญ็ศHKaแฬRr2ฆ…ษhœQ!\ฝ}|TUอพ๊ยงธ‹ซ5ยยwฬ๔ไdBแ0๛ซkxโ•75—!คเd„เ๏฿๙X5้ušio0ฌฐ2;…ล™‰่e™†มQ~ผ๑ฃเ)W/K,ฮLbyV2™ั6"อ“S*`˜>ท๊ža66tqผ๔๎ฺ”ษKJIถ[๐Cผ\ส3UMšOหณ’นw^.ณ‘!ŸGwีž๕5นพด+Qy"ค3ฎ฿บn้ศ๙~ฝŸu1ฅเTฅPฅŒ\้Xฟ๕ผ๏฿O3ีEิ$ลนY~ีืˆฒqy<ผฒa3ปึdŸฏนd!k.น‹ูฤภ๐ฝMmงg—ฯดคD.šUFnf:ฑัQ˜F@"ใ๒z่๊ํ็Pอq๖:B <-็ด˜M|Ž[˜žšL8ฌpฐๆฝ๔บๆ๒"„”@ œŒR@ฏท?V-ํฉฐชฒ2+™E‰่e‰บQxw tZŽoา๋X™ฬล้‰d8ฌุอF ฒ„ช‚7ฆืๅฅช{ˆ๕]4 –s&8๘‡ลล$ฺ,ธƒ!^8ฬ GZ49žVๅคpฯœ\ขฬ=~*wึ๐๑YZ‹๋TPœa™JE6V^ bช\UๅJdฮฬฮnฐˆธ๗ม‡ึIชTฉ……ๅ ณg๐๕ซฟ†#2ทืรk๏oeวพƒš์๗อใฒฅ‹ˆ0[แ๑Wคพฅํ”Ž™œวย™ede=^%K2a%Œ๋ฅณง๊บv๎ฏยœึxLF฿ฟ๓V2าRP…ชฺ:๔ยซšห‹R@p2BH ๐ฟHต๔šiฏชชฌสIๅข้๑่d‰cฃhร~|ก๐i=ล cMN*๓ฆล“mรn2 —%”‰Šฉ^——]Cผ_฿E๋ˆ๋”ฮUœอY\Lขอฬ˜?ฤณUMผrดU“ใ้าT๎š“Cคษภ€ฯ์<สฮAํŒฏ NL-ZชชฦŠำ&ฆ„ˆZงJR… ้Zis~V&w\5ขฃขp{ฝผฑy~ด_“ฟt._พซลยฐำษฏพล๑ฆ–ฏtฌฤธฮ,ฃ0{qัฬ&ฒ,‡๑๘ผt๕ p๘X{Uใ๒xฮH—^อแžaMฦrSi&หณ’[Šฬhใย`คr๑:UีW  ฑข„Ÿ˜Q-ฺำ็,•$*ึ7–ู—5Cv๚4๎บ๎Jb<>/๏nษฆ]{5ห‚๒ฎ[ป[„็ุyช๋พะg‘v.š5^•‡ลlB'ห„ร ^ฟŸม!Žิ5ฐk#ccg-ฆ๕wFN๚tTUฅฆก‰฿<‚ๆ๒"„”@ œŒR@เญฝชอhะฮƒญชreม4fงฦ!Gz‡yเฝณ7ฝ$6ย41•/Žิศ" z๔ฒDXSํN7๛:ูX฿ษ€ว…Ž9/-Ž\\Hl„‰_€?}\ฯฆ†.MŽงk‹านฅlv“ž^—๛แช{ตY0๓“ๅeฬITvท ด>ฒํHลฦปW=~!พ˜บ€Eิ=?~x้ทXQ˜3c‰„D}K+•?ฃษXfLOใฎ๋ฎ$.ฺื็gร๖]lุพ[“ฑฬ))ไฦหVcทZuนx๖อ๗8T{ŒีbaัœrŠsณIŠ%ยlA–eUม็๗ำ70Dmc3;๖bhฤyึc๚ท—™ŠJmc3ฟ~๊yอๅE)@ 8!คธอฝjคI;B*Vธฎ8™)ฑH@Uฯ0?ฺp๖ื;Iฐ™น47™)1คFZฑuศ’DXQ ้pz๘จฝŸw๋:๛;^”žภ๗c12โ ๐ฝวูึฃษ๑tcI7–fb5่้uy๙ืซฉ้ำฆzdอlJ’ขQƒlำA•VTeฆ{ึ^/WC•‹+$Uู]โ.p%+j…$KK๎ป๕Šsฒ$‰†ถv*๛ Z|ดฬHKแ7\=.ค~฿ฑ‡wทํิd~fๆs๓kˆดฺuปxแํ์ฏฎฟ0›™_^ยฬย<’โใˆฐ˜ั๋t(ŠŠ/เงp˜ฺฦf๖:LOน[๏;n&oFว›Z๙ี“ฯj./BH มษ!%ภo์U#อฺRP˜›J3)KŽเP๗?xเœตgZ”••ู)ฬJ‰!%2‹AN‚ ขโ๒iwบฺููวฆ†.\อN€‹3๙๖|ข-F†ฝ~ฝ็;Zz59žn)หไ๚โ " zz\^ูv„ใNอล!r้Š(ภพŽq๓กOษ6EQ*.15Rนิก ฌ—T)ใBQ๗=P‘ก๊๕ภ“๖ญ[ฎฃ$7I–hj๋เ?{ๅ ญew&™ž’ฤ=7^C|L4>€อป๖๒ึ–ํšฬSi~ท^y)Q6;.›—ฤช๊ฯูdbniณ‹๒INŒวjฑ`ะ๋QŸ?ภเศว›Zู}ฐŠŽžพsำwoฟ‰‚์L$$๊ZZyTƒ•xBH ม็ฒ- +๋ถฎ["๎*ฺ็Q“}รีฬ,ฬC–eZ;บx๔‰g๑š‹5%1ž{oบŽฤธ|๖๎็ต๗ทh2oY™|šห‰ŽŒฤํ๕๐๚ฆm์>Pลผฒbส ๒ฦE”u\Dฉ*‚A†œN๊[ฺ๘จชšฦถŽ)ำทnนž’์OUโEัึ;ŒR@p2BH ๐ืwซั“fฺ๋„ธkv๖ฉ\9ง&8Xž•LIR4 V3&ฝ ) N_†กQvท๖ณนฑ›ี9)ฌ›Mคษ@ฟว์จแ@ื &วำณsธผ`ฝŽŽQ7?฿r˜–a—ๆโฐtb๕l๒โ# +*;[๛xd‘ฟ๙9Eๅ‰NฉbJ›ฌซจp่}๚๕:™ฯฎ›๕9u•ฬ,*@ฏำัฺีอฏžxฯงน˜“โc๙ึอื“‹?d๛วxyรfMๆ/73;ฏฝ‚˜จ(^/GŽืa13-)›ีŠA?พฃl dุ9JCk{ซชฉoi›ฒ1u%^ๅใO …5•!คเd„เพืvซฑฺRž`ˆปg็P๐…+Wฮ)ล‰ัฌฬNฆ(ัqBLย N_€ฦม1\๓งลa7่s๙๘๗Gฉ๊าไx๚ๆ\.หKรฌืั๎t๓ะUด;š‹รfิ๓๓ีณษ‰‹$ค(lo้ๅ~X…?/ฤ”ถ๘2"j’;ฎนœ9%…่uzฺป{๘ฯงžcฬํั\์ ฑ1w๋๕$ววูฑ๏/พ๛พ&๓˜>u;†ฟ?€^ฏวhะŸจˆrŽัษ๎ƒ‡9ึ4๕/ฯop5ๅฏฤBJ NF)@ @{Bส ๑9น_บrๅ\Sžรชœ โฃˆ0จ˜๒‡a…ƒ$ัํ๒๒oVSซอ้พ5/K๓R1้tด9ำๆCtŽj๏%=สlไแU3ษŠ$V๘ฐน‡฿q๔หHU ่L[ื-w›ฉษ=<\๑eDิ$ท_5ๆ•กื้้่้ๅืy็˜๖ชใข|๛ถHIˆ' ฒ๋ภaž{ƒ&sนjั._ถ“qrบzBDบ\ดttฑทชš๊บอฤ๔™Jผฮ.~๕ไsšซฤBJ NF)@ พ๕๊.5ฮjึL{ฝม๗ฬอ%7.๊+Uฎœkๆฅลฑ<+™๘(ข-ฦb Iภ ๑ิม&^ชnัไx๚ฮ‚|V็ค`า้hqQฑ๙=c^อลaโŸVฮdFŒ`XaKS7•;kพาฑTgXฆR‘•BLM๎}๐กuช$UศU>๋•—2ฟฌƒ^Ogoฟy๚†ฺ[ภ?ฦลwnป”„‚ก{ๆู7฿ำT ลนYฬ..$oF1Q‘H๗ำP8ฬฐs”–Ž.ญๅภัcšหฯx%^zŽ๖๎~๕ไsธ<ฺ’BH มษ!%ภ7_ฅ&hHH๙B!๎›GV์๘TชmM_ฑrๅsIF"‹2ษ‹$มjF/หใ๒BU้s๛8ิ=ฤ‡อฝš[{ X•ŒAงฃeุEลๆƒ๔นดทฎNผีฬ?ฎ,'#ฺN0fSc7ฟฺU{Jวbjjpช"j’›/_รย™e๔zบ๚๚๙ํ3/28ฌฝด:์vพ๓๕IKL$ฑทชšง_GmฯอLgAy Yำงแˆดa4?u/ํไญ>d฿‘อŽืฟฎฤ๛ฯงžgิฅญJ3‹iQ'~ี+*p˜AŸš65vkfMฉ\Tศ๒ฌd :™ๆก1~บ้ ƒฟๆ๒’hณPฑฒœt‡`8ฬ†๚.~ณ็๔TWจ NI–ึoผ{ีใโt๖๘ึพZ‘ฉVO]s+฿ธ๑j’ใใ †B์>Xลsomะ๔8พแาU,š3^‰ื?ภ๏žั^%žR@p2BH p๗ห;ิd{„fฺR๎›Ÿฯ๔(+p˜ww๒๛Žk:฿Yฯšœ :m#.yJ“ขY0-žฬ;v“รค˜ †่qyฉ๊ๆ†.š†ฦฆT,ฐธ˜E‰่e‰บq!ๅ „4—“Œh.+%-าŠ7ๆอฺv_Fฯฉ@Šฒ~ำ=kล‹)p฿Šฌ{L‰จIฎXฑ„ๅ ๆb6้ๆO/ผB{wฏๆ๚หd4๒ƒ;o!=-EQ8Tsœz๑ต)ัถฤธX.žUFA๖ bฃฃ0่d™pX9!ขช7ฐ๋`^ŸŸ่ศHพs๛ค&Ž/ะพท๊ฯผ๑ฎฆว๓ตkVฐxฒo`?<๛2ฺZ[P)@ 8!คธ๋ฅjJคv„TXQ๘๖|า&*W>มŸฮPๅสูโ‹ X™5น๘o๋ 8มAเ(1FrcฃศŒถa7ะหaUลฏ˜ฺ฿9ศ†๚.:œ๎)หKJธ8=,qผ”m7ึ\Nฒb์hY))๖ผมฏีถ๑ไฦณu๚mŠขT1๕ๅธ๏Š Uฏฏ๎<็ปl้"V]ผณษHะ๕โซดvvkฎ฿ z=?Xw+™ำRQ…รว๊๙ใ๓ฏœำ6%ฦลฐ ผ”ยœฤGGc6™ะ้dBก0Ÿžชjุ๋[Uอ˜๛“{_คอส๗พ~3iI‰šY๋oqีสฅ,]0gผopˆ?>๗ ฝ}ฺxู’`fa>ๅ…๙หๆ—‹๛™@ |๚)„”@ ภ?o=ข๖Œyฐ™ šhoXQ๘ฮ‚R##๐†ยผQฦใ๛4ƒOฏปิ44ฦ;ว;(Jpœ๘~ทY–(Lp0-สŠอจว “ )*ž`ˆ๎1๛;ูิะE‡๓nเฒRL‹G'K๋w๒ภ{๛ „อๅ$7.’–”’lทเ †x้h+ฯj:อb๊ pถEิ$k_ฤ๊Kb1™แฯ/พNsGงๆ๚Oง“Yฟ๎6fLOCUTŽิี๓๛g_>'m‰vฐ ผ„ข์$ฦวb1™‘e™p8Œื๏ฃo`ˆชใ๕์9x็ุษ;อii=ฌ/สหณ|แผOUโฝJ{wฯิ~ษ’$ส r™SRฤ๔”$"mถef“Qวเำ๗J!คบF=jเ({๛้๕b3๊งt{Uๅ; ๒OTฎผZำฦS5ƒฟ^wiC]'…ŸR“ xu2๙๑QคFE`5่ั๋dยŠŠ;ขร้f_็›บ้uyฯI,?Y^ฦผi๑่$จ้s๒ภ{๛)ฺ๛พอโ‡KJHฒY๐Cผxค…็7Ÿ“ถจจฏeuึuk[ฤ๋ึUT8ŒA}…$๑ƒsqU‹p้โ‹ฑ˜อ ŽŒ๐ุหoะฺุฎฝb ึ฿u;ูำงกช*ี๕๎™ฯj"mV.ž]Na๖ ’โNˆ(EQ๐๚๔qดพ‘ํ๛~ฎˆšฤl2๑;o!}b=ฌC5ว๘๓[๋หrูาEฌผx>“‰กโkดtvMู๖ฮ,ฬg^Yำ’“ˆดู0๔ห$Iฺ*๎Z@๐ฉ๏_!คTUUa…!ฏŸฦม1๖ด๗ำ>โฦ>E+ฆTu|อฅd๛ธ(xนบ•gชš4ƒNLs›\w้๚ฎฯR“ xDtไฤE’A„AN–ฦลT0Dˆ›ผWืyึwธ๛ูŠrๆคล!G๛F๘แป๛ะโทmQขƒณธ˜$›W ฤsUอผTrNคจ<า)บ˜ZWQแะ๛๔๋u2๋‘‰:WํXพp._[v f CN'Oผ๒&uอญš์ำ๕wFN๚tTUฅฆก‰฿<ยY9o„ลฬลณห)อห!)>‹ูŒNึ๏0๊๗ำ;8ฤฑฦfvจขh๘oฯ`ะ๓ƒ;?™~XU[วŸ^xUำใ}อ% YsษEXฬf†‡y์ๅ7hj๋˜Rm”e™น%…”ๆ็’‘šŒfร q+ 1ๆv/‹‹vlO\@๐ BH เ …UฃN V๖จprฐkˆ–Vริซ˜๚๎‚|’์ใขเ…รอผpD๏็?ZZสย้ŸLs๛ ฑ›‚xว฿ˆ/0>•/Ajิธ˜’%)*ฎ@ง‡=mผW฿‰๋,ํtWฑฒœูฉใB๊H๏0ผท_“9)MŠๆ๏/)&มffฬโ้CผVำ6%ฺvกŠฉฉ"ข&Y2o6WฌX‚ีbaุ้ไษW฿โX“6S๒;o!/3•ฺฦf~ิ๓g๔|f3๓สŠ™Y”OR|,6K:UฏˆแXc {ฆซ๏‹๏\(ห2wืิ˜~xบXyั|.]z๑ธ๘œจฤk˜"•xzฝŽน%E”ไ2-9 ปีŠAฏ  3ๆrัึรกc๕ห๎พ๎สญโ‰K >A)@ ถท๔ชูฑ‘D[Œไq1TFผG9ุ=D๓ ‹A7%ฺซช*๗_THโ„(xถช‰WŽถj:Ÿžๆvดw„mอฝฤฑ๗mง?@Uฯ0%‰ัฬLŽ!ษnSฒD(ฌ0๊า๎tณฃฅ—ปฯ๘Žwญšษฬ”X$ ชg˜mะฆ*OŽแ_RDผีฬ˜?ศ“y๓ุิ™Žฅ*8ร2•Šlฌบn้ศ๙~Ÿบ๗ม‡ึIชT9Dิ$‹ๆฬไ๊UKฑZ"ๅฉืฆฆA›ีš๗฿q y3า8ิสฏž|๖Œœวd42ฟฌ˜๒ย]Utธg˜:๚ษމJวjwบ้๕Rœไ 4)š›ณ^‡,APQ๕hco{?›บN๛xฟX3›ฒคhTเ`ื ?y &s27-Ž๕aย้ ๒ง๋xฟa๊.$|พ‰ฉฉ,ขNŒ‘า"nธtvซงkŒgx—รว๊5ู฿฿นF ณg !Q฿ฺFๅcOŸ–ใ๊t2sK‹™U”OZR"vkzP ƒ ŒR฿ฺฦช๊ำถ wLŒ เฬV{-.šUฦ5ซ—c‹ฏฤ๛ห๋๏pด์ŠO“ัศผฒbJ๓sHKLภnตขื ล@0ฤจหE[WGŽืำ78D„ล™ฯ !%'#„”@ ๐Y!ใHฅ'ฐtF9S๙ŒบqกPTœอรc์ขqhฃ๎์Š),๑ฝฤYวEมŸ๗ีณกพSำ9๘tUัก๎!u ‘m;ฅcถ;๔บฝ'FS’M‚อŒIงC’ 8!›†\์h้eKS๗i ๏‘ตณ)IR๛;๙ู&m ฉำใ๙ยb"LŒxฃใli๊™๒ํVTZeIชุx๗ชวตุ๏๗๘แฅ:ิJสฆz[gpำๅซ‰ดฺuปx๎อ ฌ9ฆษ๑~฿ญ7Pœ“…$I4ดตS๙ุ_8•วdIšmญ„้ษ‰ุmใSบTuผ’fxt”ฆถvS“Sภš†ฦ8า3ฬ๑ัำฮ4zYๆ…๙ใขภเี๑Acทฆs๐ฯkfS:QUt sฃ}#Lฒž–cท;๔{|”'ลPเ jยคื!๑Iๅ[รเ4vณฃฅ๗”vฤ“€นtE `_วธ๙&sฒ(#‘๏.ศ'ฺbdุเ7{ŽฑฝฅW3ํืš˜บ็ว/•ตB’ฅ%Z้ใ๒‚.>G.^|็3&>ํึๆL์š—๗™Šจ@0ภ๐่-]Tีgdิ๕7Eิ$BH ม็ผ!%_LHM2+%–YษไลGg5aึ๋คOอnqOๅC’ฮฤหตŠอhเพ๙yDOˆ‚_๏ฎeงEม$zYโ‘ตs(Lˆ:!qZ†]$ู,gไ|ํN7๎`ˆข๙๑QD[Lu2’ะธ˜ช้แรๆ^๖ถ91eิษ<ฒv6๙๑Q„•=ํ|หaMๆeyV2๗ฮหลa62ไ๑๓่ฎฺ/SŒmŠขTlบgํ”x)ผ๏Š Uฏฏ๎ิj‡ๅdq๛U—แˆŒฤๅ๑๐๊ฦุu@›๖7\Myaฒ,ำฺัลฃO<ƒ?BŸ-ฬžมา"ฒฆงeทc4่้ฤnkอ]ฌ9ฦฺ๊ณห=7^CYA.ฒ,ำาัลฃ?C ิ์…[šŸรญW^zFลgคอสา"J๒r>Sฅช @‘ฑ1š;ฉช=Žsฬ…Eิ$BH มษ!%|9!5Iyr +ณSศฏ˜2๋uศปนWLนจ๊ฆap๔ดถ5ค(D[LŸฟ]หž6ํŠ“^ว?ฏ™M~|$aEew[?]ฃโญๆ3zvง8L~ค˜฿]QU!3่๑Sำ็dKS7๛;ฟะ1อฑไMฤฒณตGถัd^ึไคr๗œขฬ~Uรว็ร%Nลิ๙ ข&)ศสไ๋ื\Ntd$nฏ‡ื7mc๛วฺU๒ฎ๋ฏbfa>:L[g7ฟ|๒Yผ>๘™์๔i\4ซŒำำˆŽดc4ว+gC!ฦ\nฺบ{ูwไ่YŸฦx๗๕WQฉX}โY|~ฟfวYqnท_๕5ข์v\ฏlุฬ๎ƒงG๔ญV.šUJA๖ Rโ‰ฐ˜ัษŸ์~82:>5๏h]ร—ชˆ๚k„‚“BJ ๘jBj’Y)ฑ,ฮLค(มAฌี|b7ทขโ๒iqqดw„c}ฮ๑นiงH ฌ`3sฯœ\ขฬ=~*wj[D๔bอ,rใ" MHœ~ทX‹้ฌœฟ้&V(IŠ&;ึŽรd๋}šŒๅฮkฏ`vq!zŽถ๎n~๕ไsธ=ฯำRY0ณ”์๔iฤDEa2Ž‹จP(ฬ˜MGoQ_uชณ‹(ศžมืฏฺ'โ๓ญl฿wj—QคอสยYe็d‘{’ˆvŽาฺุฮ‘บFฦ\๎ฏ,ข&BJ NF)@ เิ„ิ$eษ1,ษLค(1š๘ฯSฃ๗ Swjปั{ƒ!ฆ;lŸ;k8ะฉ]Qi2๐๐๊YdวFRถ5๗0๊ โ0ฯj;:F„•าคh2ฃํDYŒe ๐ร๔น}T๗ณฉก‹ฺ>็Šๅรๆ^mป6…ิ•ำ๘๚ฬ,์&}.พใ(UC็อu.„ิ๘zl9_๚0'c:๋ฎฝ‚‡ฯห;[wฐyืGšŒๅŽk.gNI!zž๖ž๓ษ็sป?๓7ำ’“X8ซ”ผฬtbQ˜F@"ใ๒z่์้็Pอ1๖T! ณXnฟ๚kฬ+-Bฏำำัำห>๕<ฃ.—fวY„๘Œ> โ3ึลผฒbŠsณIˆ&ยlAงำกช พ@€ก‘QZ8|ฌืwส"j!คเd„Nšค0มมŠฌdŠ$ุ,X&ฆ๒…ย c ]ฃ^ชz†จ%๘™uBdลฺนcB๔ป}๛๖ฃาฐ(ˆฑ˜๘งU3™c'Vุาิ?ค`3๊ฯI{บฦ๋0yh๕Lฒb" †วๅฺqT“yนถ([สf`7้้u๙๘ฟVS;|\๗BH:3ฆงqืuWํภ๋๓๓๖]lพ[“ฑvีeฬ/+—8ฝฝๆฉฟพSใY8ณŒ‚ฌ bใQฒ$Vยธฝ^:บ๛จฎk`ืC_xฉ3ษญW^สฒ z=]}}๚//0์ี์8;I|nูมๆ_N|ฦลD3ฏดˆขœ,bcˆ0›ั๋u„ร @€!็ธˆชชญร๋๓Ÿ65‰R@p2BH งWHMRลสฌ”q1e5c6่ัOฌ1ๅ „่๕pคg˜๚'/!ฆFA ขธต,๋„(๘ทํี้ัฎ(ˆทš๙ว•3ษˆถ ‡ูิุขจD๔็ด]c^๔:‰œุHfฤุฑ› ่e EU๑ร๔บ|์ไ†.Z†วซb#Lำส™dNศตปytW&๓rCI7•fb5่้uy๙ืซฉ9ล ฟฉ„RงNFZ ฿ธแ๊q!ๅ๗๓Ž=ผปmง&cนๅŠต,(/Œฤ1 ใ"*;“8‡ณษ„,ห„รa<>/]ฝTซcoU๕”šwำืึpัฌRŒ]}๖้ึ๎ต›5=ปฎฟŠX‡ฏฯว{๎dใŽ=_่ณq1ั,,/!?+“ฤธ,&3:LX™Q#ฃิทดqธถ_ pฺEิ$BH มษ!%œ!5I^\+ฒ“)IŠ&มjฦbะก“$BŠŠ;ขร้กฆw˜c_LL๘”'วpSi&6ฃž——ฆmQdทPฑขœt‡ 8ฬฦ๚. ฒŒQ'O‰๖๕น}ศไว;Hถb7ะ๋dยŠŠ'ขwฬหฎAฏ๏ย Vฎ5t๓ซตšฬห-e™\_œA„a|œ=ฒํว๛็อu/„ิฉ3=%‰{nผ†๘˜h|›wํๅญ-5หง%N฿เ05 MdNK!!&ณษ„N' …๑๘|๔ r๘X{UOษฉpืฏ]ษข931 t๗๐๛g_ขw@ปUด_E|ฦวDณpf)Y™ฤวFc1™‘eEQร#ิทดqคถ0xฦDิ$BH มษ!%œY!5IN\$+ฒ’)IŒ&ษnมbะ!Kแ 1ี5๊แh๏ี=#”0ฒ๔๙+ zฬ›ว ็‘(H‹Šเ'หห™eล ๓n]Vฃฝ$Mฉvx่ๅ๑ฉ|ฉ‘VlF=LhBLuz8ึ๏dvj,)๖ˆrํ7{Ži2/ท—gqmัt,=c~ฑ๕ศi฿5๒\"„ิiธv“ธ็ฆkIŒมฐuฯ>^฿คอw๎.[ล%sfb4C„ย!LF#:Y&V๐๚}๔ sไx=;๗WM้5™ฎYฝœ%๓fc2่โฯฝLWŸvwb2โ3)>–ๅใ"*6ฺลlB'ห(ŠŠ/เงh˜บฆVฏ' Ÿq5‰R@p2BH gGHM2#ฦฮŠฌdJ“ฃIฑG`1่ัIVU=c^v๑Q๛!Eมn2|ๆ๓n‹าฯ+QmใวหJI‹Rok'ฦbBšขํ๐๘1้e๒ใฃH‰Œภ:13<1•ฯ “1้d|!…w๋:๘ใšฬหบYู\Y8‹^G็จ‡_l=Lำะุys !u๊$'ฤq๏อื‘‹?dG๛yuใš‹รaแท@ึ๔4dYFUAUUUม็๗ำ;0Dmc3;๖ิฤZLWฎXยฒ…s1๔ ๓ว็_กฃงWณใ์‹ˆฯิฤๆ—“—•A\ดใ“ฉyแ๑ PืJu]@๐ฌ‰จI„‚“BJ 8ปBj’I1U–C’Bฤ„ิ)bสๅแPื{๛ )๊ 1ี๋๒ฒ|F๒y% fฤุypY))๖ผก0oิถaš๒ํ๒๚‘e‰ขฉ‘Vฌฦ๑ช7I’€ฐขRำ7ย?n>ฤจ?จนผ='‡+๒งaึ๋่pบyxหaZG\็อu/„ิฉ“ห}ท\ORธฺพ๏ /ฟทI3ํทZ,,(/กผ0๔ิdLฦ๑=Uผ๑ฉyต อ์9t„ํ์dzูาEฌบxf“‘ก๋ลWiํ์ึ์8๛Ÿฤgjb๓หKศ›‘N|t๔ฤ:_aๅีะาNck;พ@Y>7?u!%'#„”@ pn„ิ$ำVVfฅ035†$[Vใ๘Sa<มcชบ‡ูำึ‡;"จ(ฌฮI=ฏDAn\$,)%ูnม ๑jmIV‹&ฺ๎๔8ุ5DQขƒY)ฑคEYฑ๕'ชปผม0uNvต๕ฑฉก›1 ‰ฉoฮอๅฒผ4ฬzํN7๔AN๗ys !u๊ฤวDs฿ญ7’G d็*^x{ใ”oทลlbni1ณŠ๒INˆรf‰@ฏื๘`(ฤพ#5lฑ›ฎ^ํMu[ณ๘"ึ\ฒ‹ษฤภ๐ฝ๔:Mํšg‰q1|๋–๋IŽรฒc฿A๖VU3ฟฌ˜้ฤ9˜Lใ;*Š‚ื?>5ฏฑญฆถNมภ9A)@ 8!ค€s+ค&IŒ`UN 3“cI‰ฏ˜าM์่ๆ †้๓Rี3ฤ,ฯJๆาqQะๆt๓ะ‡่pz4 Qpq ‰6 ž`ˆWถ‘lทh*†vง›๊.อMeษŒคฯ,ศ +Œ๚ƒดŽธ?{๏วu๊ฟปณฝ` ,z๏ฝ›%ช’bษ‘-ษE๑M์ุq๛In๚Mrปพ7ืNs|ุฒ-ห*–ฌb‰”HŠTฅ(ฑ ขwA5› IDAT`ภb{›฿ @$%+†9๏_|agฮ์๙fฯฬซ๏|ฏyyed–H2ตๆฏ้‹›šธตกฃ$1๎๓ตG™ Eฏ˜๛^ฉ๓'ฯ้เ‹GI9•b‘}nวšฏ^ฏcKWM ”bต˜ัI้t†t:$Ih4เ๓๘ึฃO213งสyนi๋&n฿v5“Ÿ฿ฯw๒,Cใ“ชณ|W._|เใหqฆเ]\4ธœ9๏ี๙Jง‰ลxšœblrfMˆจ„‚๗#„”@ ฐ6„ิ %9nช+ฆป82‡ซAทœ1•ญOไฤษdฒ…ภ๕Z-ใ0s๗fC1ี~m…N๛uํฺL„)ž๊ฃฬaUuผ9แลŽ๓;)ฐšศr:ƒคั iฒ&d†ƒ์ŸœgืเฬYuVผ\|yK37ืฃ_Rน๋žp์Šน๏…:œ9vพ๔ฉ๛(+,DNฅ8p๔<๛โšงN'ฑฉณฎๆFสŠ ฐY-่$™L†ค,ณ่”eJ ๒1่๕ฬ๛็?elzF•๓ฒmำ>zใuXอf|฿๚yNŽŒฉ6ฮ\N_y่A ๒rP”4&๙PQˆลใx| ŽO0>=ทฆDิ BH ม๛BJ X[Bj…’ 7ิฑก4ŸR‡›A‡N›ํ่–ษdะ-ืม˜ฦ๘ฃ๏โ วU๛wป๘ฝkZ)ฐ™%dž86Fฅำฆบุ๋?97็ฏoงุn&ก(Œ/E0๊ดฺฬuZM6c*—๑…xsยห๎แYไ5(ฆ~gk3kณBjิโ/vf!šธb๎{!คฮŸ›•฿๚๔'(/*"ฅคxง็8?๘้ฯึฬ๘ดZ-ฺ[ุะBYQ!๖e”“๘A†ฦ&ุด—บŠ2nฝv+f“๚ทน]ปก›ปo†ีla)ไ?'†FTy-5ๅฅ\{ี:6ดท`ะgk)f2 ( ัxœ๙E'GวŸ™%•Zป™งBH ม๛BJ X›Bj…B›™k‹ุXๆฆ$gYLIฺีE‰”ยั9^89ล o@•฿บา<พzu nซ‰เฒชRก:0ต€7[~‘S<3สqฏŸํตลดๆโถ™0-ืช‘•4x’_˜}ฃs์CIฏP๊5ญlซ.B/i๖๙๓—ณK^1๗ฝR็ีbๆท?๓I*Š‹I) {๛x๘ฉ็ึฤุ:›ุAEq!9vzŽL’ฒŒ?bdrŠร}'Y\๒“RRด7ึsว๕ื`6™X๔๛๙žŠทนm้๎เž[ทcณX„B๐™่Rี54TWฒพญ™บส ๒œLF#šๅ…/)หŒOฯ286ม๐„:ๆH)@ x?BH k[Hญk6pkC)W•ๆำŸƒqYjd€h2…'ใธวฯพั9zๆ–T๕o,ห็wฏn!ฯb$—y์ุ(ตนvีลัม™Eผแฟ]E63แdŠGŽ๐“๑์ rฑ‹›๋Jh.po1bิIh€ค’ฦK2ดdืะ oMฌ"สฟmืUขำjZ ๒g/ReทภŸ‡R็ูdไw>s?ฅล(Jšร}|๗ษg.๋˜:›ุะึBuy)9ถฌˆZ‘มp˜ัฉŽž8‰ฯฤj1ฐ่ะ\[อGnธ6[w)เแงžc`t\•๓rUG+ฟz๛อุญVแ>ทƒฃ'T1๖ฦš*ฎjoกถฒgŽฃํ\ชFC:arnŽgwํ[^ีR@๐~„ิ!คVp™ีอิๆูัj4d22@:๑”ยb$ฮqฏŸWFๆ8:๋Sล5mญ(เห[špYŒ๘cIํฅ!/Guqtxึ—Rืถ-o?L๑ศ‘a~ฺ7q๚หbY>k‹it;p™ ซr1+ฆ๔{ผ:๊แอ ๏eฝž?ธฎkช ัi5 ,๙ำ—ฉข๛ู"„ิ๙c4่๙ฯ>@UY ้tšฃ'๘ฮใO_–ฑด7ึฑพญ…š๒2v}VDษฉP˜ฑฉŽใY๐ญŠจมตๅนzฌf3Kหu—๚UZwฉปฅ‰Oy+9VมH˜ว๖{Oฌ้17TWฒนซš๒ฒฌˆ2่ัhดค”ฑxฝNั`@Q๕๕sเ่1Uอ‰R@๐~„ิ%ค่๚vฎฎ*Dฏี“Š‚อ G/iIง3ฤS ั8ป†gืผ˜บฎบ/nj"ืl`iYH5ชPH๓แ ว๙ฝk[q[ณ๕ฐพh˜็๚?xKษี•\[UH“Aฎูธฺ™/ฉ(,F“œ๐๚yuฬร“—'c๊ทuฐตยคีะ?ไOv$žRฎ˜๛^ฉ๓Gง“๘สCR]^J:ฆง๗ุS—t M5Ul๊jงถbED้ )%E0YQณ…๗‰จ‚แ%ลสRwฉฃฉž๎บ‡อN(แษป8pดwMŽตฉถšMmT—•’๋ฐcXฮˆJ))"ัs ‹๔ ฑฎต™Š’ขU๑นHบึ!คเ}!%จOHษถถ,‹‚ม…ฏyุXžO™รJŽ1+ฆ2™ฌ˜šฤ้Ÿฐgx–ร3kSLX[ฬ็ฏjภi6เ‹&๘Qฯ(อ๙ีลั1ฯHดzX฿}w~qaไ๋ช นถชฦ|นfร๒ABQ๐E๔y์šแศ%‹zC›หณqvยเv\“ลืฯ!ค.ภƒคFรWํAj+สษd2โ฿}๒’œปถฒœญิV”Ÿ.2R)‚แ0Ss^๗ฤณฐ€ลl๚…ว Gc”ธ๙ุ-7žRw้g๔ ซr^ฺj๙ิมaทŽFyj็n:ผถN{c๋Z›—3ข‰Šข‰ล˜๕ฮำsrท๗”eพ๒ะƒิT”‘Ig860ศจjN„‚xŽBJ ิ'ควl,w#i ฯเ›o๖a3่i/สฅปุEEฎ ปQ^ซY‹ั}^?ฏy/[ฦอฯใๆ๚~}C“žลh‚GŽา์VŸ๊›๗ใ ว๙ส)๕ฐใ^ๅญใ5ภ5U…lฏ+ฆึeวนœ1uชX์๓xipšใ%3-ะ็๕๓;r%=7!ua๘๊ฏ=H]e™L†พก๕‘ว/๊๙ชJKุNCu%.‡cyk—†TJ!2ํ๑r์ไS&ƒแฌŽ‹'ศฯu๒๑oยfษึ]๚ั3/าsrP•sา\Wรงๅ#ไๆไ‰Eyๆๅฝผ๖๎แ51ถฮๆึต6S]V‚รnCฏหฮŸข(„cQฆ็ผ๔ ๓ึแโ‰๗บz~๕sŸขnY|๖๓๚ป‡T5'BH ม< !%๊Rฑฝ‹ e๙hใ^?฿|๓ลv3ํึ่vะ^”KMฎ ปษ€^ซ!ษn๓E๔ฯx}ฬ{ูkญpGcญฏ#วจg>็ฑccชฬ๊_เ ว๙ญอูzX๑$฿>0ภžแูณ>†^าฒญฆˆ๋ซ‹จฮต‘c2`XžฟxJม‰ำ3๋cืะ,'.nWลฟผฉ‹๕ฅู8๋๕๘๙ร๏^Q๗ฝR†฿}่ช*ษแฤ๐(๒ƒว.สyส‹ ูาICuyนฮีbื๏‰ŒyNŒŒ215‹ม ๛PวN$ev๗q vซ•`8ฬฃฯํเศ‰“ชœ“ฦš*>๓ฑโr8ˆฤb<ฟ็U๖พ}y๏฿ฮฆฎ๊hฅฒด˜[ถฦืฉ"qjฮKOzŽŸ&ขV๘สCPฟg}C#ผzเ jๆ#“žA!คเL„ิ'ค็Mฌ/อC›[โ_฿๎งะf>ํod%Mmžฎb5.๛ib#ฉ(๘bI‚ผ22{ูปบี\ฮงปkฑ๕xรq?6ฆส ฉมล Hœ/oiฦe6เ%๙ททOฒot๎Cหจ“ธนฎ„-nชฯ‹๑”ย\(Fฯœ—g๖….ส๕ีอt—dใฌgn‰?y๐Šบ๏…บ0๖g๎งฑฆ€“#ใำ๗ฝ ว/v็ณu]'อuีธœL#ZญEI‰ล˜š๓prdœฑ้๔ห >,rJมb2Vฑ็_โะ๑ชœ“บสr~ํปp9Dใ1^๛ป|๛ฒŒฅณฉmT”’•-6ŠD™๕ฮsฐ๗{๛H$~ฯ฿๙์4VW‘!C๐{฿~G5๓!„”@ |0BH ๊RงŠ‚#ณ>พฮึฎ‘’H)TๅฺุX๎ฆาiลi2dท‚‰Tถซะb=ร—OLำZษ5ุ:<แ8OฅูํT] ๛BฬGโ|i๓{ฺe?ฏyฮ๙˜ฝŽ[๊KุX๎ฮfผ๕่ด” ฤไžpœร3‹์œfยน ื๓7ทฌฃณุภัY๚าก+๊พB๊ย๐[ŸอตีhะprtŒo>|a„Ta~[บ;hฉซ!?ื‰ษhD’ดคR ัxŒน๙E๚G˜˜Cฃ9ฟs)้ Ž๎บ›P$ย/พฬ;=วU9'5ๅฅฺว๏&?ืI,‘`็koฑ๓ี7/ †Fร๚ถfบšฉ*+!วfEฏำYตฒต๒๐๑~9vYๅ;ฟ้OาT[ตg{: š๙Pาz‡F„‚3ื !ค@}B๊onYGWฑ‹ pxf‘|w|๋/.ฺ›ช]v6”ๅQ•kรฑ,ฆ +ฆ–โ ๆƒผ1๎ๅี1ฯ%ญ๔‰Žj๎kฏยขืแ วxฒwL•Bjฬf>็776f ดว’ำ›}D๔9Lnฌ-bkEๅN+๖ๅฎŠฉt†จœb.ใะ๔"/ อ0ธ0b๊oo]OgQ๎jœ—_Q๗ฝR†/=x-u5h4ว'๘ฟ฿}ไผŽ—๏สesW;-u5ๆป0MhตZE!ใ]๔qbx”ฑฉเยNi4ผ๋ŽๅBเžฑ›ทSๅœT–๓฿~๕cธ]Nโ‰$/ฟฑŸ๖พ~ัฯ+IZ6ดทาูิ@EIัฒˆสnŸ”S กH„ษY=ผำs9•:๛8๛ิrœกaplฒe| Š’ฆwxT)@ 8sํBJ ิ'คึ๕ด/‹‚ƒำ‹<|hˆ<‹๑ฌ>—j\vบJ\หลณ ่ตY1•Tฒbjh!ฤ[^๖ฮ‘J_ฏๆฎ>Z‰Yฏc6ใฉใ๊R ‘8ฟฑฑงษภb4ม7฿ไ”B฿ศ˜R@pๆา+„”@ จKH้ดถ ด8P2p`rž๗Œโ4ฮ้xแ„Lนำสฆr7ตyv\f#F้ฝŒ)<ษˆ/ฬ‘Y^๓^1๕น ๕ูTŽI'1Œ๐ฬ‰IUvู› EYŠ%O๋๘o๔qhz๑ขณศnๆึ๚RบK\”9ฌX๔:ดšlอ’p2+ฆ๖Oฮณs`š`Bqฆๅ๏o[Ÿณt†ท'๘๋W„:_ฎD!๕๋๗}ŒฮๆดZ-cS3|ใ{?")๒Xณšอl์lฃปฅ‘"w>VณI’Hงำฤ“ |~FวŸž!–H\‚+ั๐ภท‘ป†:ำ+…๙.พpว)v็“Hสผ๎ažฑ๋‚_ฏืฑฑฃฮๆ†S2ขtd2 งd‚แ“ณsผำำว‘ค/@ฆํฉq6:9อŽW฿ไBnูผ˜$ๅ'Fว…‚3W^!ค@]Bส(i๙ปึำไฮŠ‚ท&ๆyฒw ว9 ฉ"ษeหช˜ส51๊ดh8]Lฝ9แe๏๐, ๅย‰ฉฯolเ๖†2L:‰‰@„็NLจrห\8†?žไ3ห็#qพฺqŽฮ๚.๚น+œVnช+a]Iลv3ๆๅŒฉ”’&”™ Dxcห๎แYBg!ฆŒ:‰ฟปu=M๎”t†7'ๆ๙ปฝ=Wิ}/„ิ…แsฟ›ฎ–&$Iห๘๔,฿|๘Qโฟ@ ™Œ6uถำีาHIก›ูršˆ๒๙ƒœใp_?Zญƒ^wฉ‹นฃทฎvฆ{แ•ืูญขยูง’๏สๅ‹|œ’7IYๆอC=<๖ณ็ฟ๔l๊lงญฑŽ๒ขBlV :IdV3ขฦงg9ืฯกใtK็~๕W่niDซอฦู {_Sอ|$’2cBH ม™+ฏR@ .!eึ๋๘ป[ืัŸoŒ{yบo‚ฃ‚?œLQแดฐฎ$Ÿ†\fIสถ้Vาโ2รพฆๆู=4K<ฅœ๗9ฟดน‰[๊K0Jใ0/œœขQ…R๓ั8x’:kW;~ต^Žอ-]ฒ1T็ฺธฅพ”ฎVำib*˜[ ๓ๆธ—]รณฤ~Ag+‹^ว฿.วYj9ฮa฿ฑ+๊พB๊ย๐ู{๎d}[ :Ibbv–z๘วDb๏ฏ_ฆืุ้AGc=ๅ%…ซ"*“ษ“ซ"ช็ฤ Yฦj1]โงb Ÿศญไ9ฤโq^|๕ ^~}ฟ*็$ื‘รo}๊>J S)๖้แั็vœ๓๑Œ›บฺ้jn คภีb>MDBaFงฆ9าืฯแพ“ๅšบ๗.ึต6ฃ“$ฦgfy~ฯซฉ–ุ…G)@ ๘9KฏR@ .!e3๊๙››ืQŸŸC*ๆตQฯŸœฤfะ_ะ๓„2e ๋J๒hr;ษณœ.ฆVไฦ[๓์ž!&Ÿป˜๚ํ-อTWŒ^’[ ๓สศ,UN›๊โh1– —๙dg56ƒŽนpŒ๕j/ว=K>–๚ถืำU์ขภfฦค“ะj@Ngล“ -†ุ?9ฯฎก’ํf7๊๙›[ึQ——ณWG=|ต+๊พB๊ย๐™}” ํ-่$“ss๓๗#yฏำฃN’–ทๆ5QVTpZVM")ณ206ฮัฤโ‰K/ขVŠัp฿Gn!?ืI,‘`็koฑ๓ี7U9'96_๔'(+*$ฅค8ะsœ๔g๚8ณ‰ ํญtท4R\อlAง“ศd )หB!ฦฆf8ะำK๏ภ๐%ณ็vฟŠZถ์ลIฦ'…‚3ื^!ค@]Bสi2๐WทtS๋สAVา์cวภ4VรลูึJศุฬlฉpำ˜ŸCžลˆQ'eท๒-หqv;ุั9ยขNั _นบ…jŠัKZF|!L.Ph3ฉ.Ž๑$ม„ฬ}ํUX๔:<แ๐๊1Nx—mLอnช-กฝ(ที„Iwzถˆ/ฤ๋ใ๖ ฯV์ƒโ์ผ~Šบ๏…บ0ะจDHล LL !%g „”@  .!•g1๒ต›บฉvู‘•4{†gู=<ƒ๙"ืY %d๒ญ&ถVธit;ฒbJ’ะj5ซSใKa๖Oฮณwd–@์ลิ๏]ส๕ีE่ดZ†ƒ๔yุ/pฦืฅ ”” &d๎mญฤขื1Š๑๗๛zX^๖ฑตๆrs} - ฌฆ๗คโr}ฐแล{– ืg2™ŒณoผูwE๗BH]๎ฟ๓66wu ื้˜๑z๙ืGž ขธˆmT–‘cท&ขกฃ“ำ๊๋'Šฌ ตXฬ}wŒ•K<‘dฯ[xnฯซชœณษศ๏|ๆ~*J‹Q”4‡๛๚๙๎“ฯาฯY-fถtwะRWCiQAถะผ6ปญ2)ห๘C!F&ฆ8ุ{‚ใƒร—5ฮž~y/•dHEcq'ง…‚3W^!ค@]Bชภfโ/ทwS•kCV^še฿่&tIฮJศธญ&6–ๅำ\เ\อ˜าj •ฮJศŒ.…98ฝภหƒ3gีูํฎkใšชBtZ  Aฦ—ย่ดZีลQDNJศ|ฌฅณ^วl(ส฿๎ํah1ดfฦุY์โ–๚šWคโ)bสK2ธdฯศ,C‹ม๗ลู?ฟuโŠบ๏…บ0๗‘[ธz]'ฝžฅ@ษ9%nvzžS ^Nอะ{ryŸ ‰จๅ‡b4{๛Mๆนˆ'“์.ฯ์Rง?0่๕๎CPUVB:ๆ่‰พ๓๘ำ?๗๏ญ3Wฏ๋คญกŽBwV“yตพWR–Y Ÿไเ๑K–๕‹โlฦ;ฯS/ฝข!‰ฦšBJ ท๖ !%๊Rลv3ฑฝ‹Jง„ขฐs`†7'ผคK+pV2ฆ6”ๆัZเ$9๋fฅNQ8!3ˆp`jำฟPLษถถTธ‘ด๚็ƒxยฑ า&RK)„“2w5W`ึILณBjฤZscT๎ๆ†š"Žำ ื'Ri–b ฦ–ยิๆูษท˜Vใ์฿๎ฟข๎{!ค. ฟํ&ฎธƒ^ข((iฝNhSห"jršพกๆๆืœˆ:•{oป‰ข<I™}๒๔K{T9'’คๅ+=HME™t†ž“ƒ|๛ว?y฿฿9s์l์lฃฃฑž‚<ณ Jก๙คŒ/`xbŠG{›ธ์qvอ†nŒ=ณ๓ <ตsทjๆ#1<5#„”@ œR@€บ„T™รยธฑ‹ ‡•xJแล)L. —.OFQ(!“c4ฐฅยMKก“‚ๅ:EงŠฉ้`”“๓ผ2<หB๔ํเ์†N6Uธ‘4ะ็ 0แc”$ีลQBQ'SูTŽI'1ˆ๐ืฏ๔0๎ฏู1_[Uศี•48p™$mvk•’Fงี “ด$R ฯ๗O๒ํWิ}/„ิ๙S_UมwFIFC๖ฑ2ณ,ข"Lฬฬัำ?ศยšQ™LVzนณB๊ตw๓“ปT;7_งจซ('“ษะ;8ฬท~๔ฤ๊หs:ธชฃ5›•๏ยb2ฃำIคำiโษไr}ฏ)๖9ฦ๐๘ไšธžr#ืo\ั gnaQUsŠD™žBJ ฮ@)@ @]Bชาiใฯn่ lYH=ื?ษแ™ลหพล-”ฑ๕lญ( ฅะ‰jยฌ“–kL…’2ำ(๏L-๐สศž๐{mแb{ส๒ัวฝ~๚ผ~๕5—ำi"ษw4–aาIL"|mฯQฆ‘5?๖kซ ูVSD}^นfC6ใNฃAd2ฦ๙ญ›[บb๎{!คฮšŠ2ถtwPWQNAž ๒–แL&C0a|z–ฃฬz็1›ŒชธฆL๎นu;%๙$e™7ๅ๑^Rํ๎CะPUI† '†F๙—>Fžำมๆ๎šjช(r็c1™$-้t†D2‰/dh|‚ท๖221ตฆฎ็๎›ถฑm๓LžE?ูฑ ตผว„ยQFf„‚3BJ P—ชqู๙“m”ๆXˆฅžํ› วณ„คัฌ๏„Œอ gs…›ถ•Œ)ฝiนฦT8™b2แ๐ฬ"ป†f๑„c|ํฆnึ•ๆกzๆ–84ณH•ำฆ>ม‘ษ‘SึPŠQ’๗‡๙ฺ๎ฃฬ„ขชฟVฃแบ๊Bnฌ)ฆ!?+ฆ4หq%+iฆƒQŽ{ผ<4CŸืฏ๚๛^ฉOei1[บ;จฏช$ฯ้ภhะ/วˆ&ปๅ3)๓๒๛้ลจฒฦ้ sห”ธ‘S):|”?ฟSต๑ŸนŸฦšJF&ฆ› ฅถwž ‹ษ„Vซ%I“Lส,๚ ŒM๐ฮัใŒNMฏษ๋๙่ ืฒ}๋&LF๓พ%žฑ‹๔)Aื2มp„ั™9!คเ „ิ%ค๊๒r๘“mํ-ฤไOŸ ฟ*ึ ก„ŒEฏcSน›๖ข\Šl&Lz ญFƒฒ,ฆf‚Qอ,าQ”Ks€ฃณ>^๓ะ^˜ซสXŠศ)nญ/Aฟ,คrื‘ำฒมิภ5ู IDAT€Aา๒ษฮj>V…I'eหg2ค3O)xย1zๆ–ุ54ณ&:žณ€B๊ฌ)+*`sWMตีห"*++•ด‚ข(่uzดZ ๓พ%ใ๑ŸbณšU>vห” งRผ}๔?z๖Eีฦ๗o}๚ดิึ ีjI$“ค”fใ{Q๑d‚…%?ƒฃผ}๔3sk๚znฟjnพf3fฃ‘…%?Oผธ‹tZQล\Baฦf=BH ม!%จKH5บั๕ํูฬDๅO๔Ž1ผZณใ %dŒ:‰อๅn:Šr)ฒ›1Ÿ’1‘S่ตZฬz %แะฬ"/ ฮฐนญสXŠ+ 7ีฃ—$ฦ–B๙ฎ#,DโชปŽฦ|ผญbป%IEAงีขำjฒbJNแ‰ฤW3ึbแ๖_. „๚eป๓ูฒฎ“ๆฺj๒r˜ FดZ-Šข‰ล˜๑ฮ“LสิU•ฏŠ‚๏ไY,*ูฆwzฬF#ทoป‹ษŒฯ๏็{O=งบํzห๑ภ7@yq)%ลปว๚๘ำฯซ๊J l์lฃฑฆŠŠโขำj{Eb1Nฑศ1ฆ=^U]๖-นใ†kVใ์ษป‘Sฒ*ฦพ1แ๑ !%g „”@  .!ี^”ห๏_FกอD(‘โัža&Qี|ืก„ŒNซaKE]ล. lfrŒบำj -†8:๋ใ๘ผŸjงMUb*ษp]uzIห๐b?{๙0xRu๗D[a.บSโ์่{†gนฑถ˜ญ•”9,ุ z๔’–T:CTN1Œrpz‘]ร3Lึ~L !๕~\N[ืuาR[Mก;/+ขดZ%M,วณเcljšคœ"ื‘Cศfฃ‘p-Vณ_ ภรO=‡AฏS]ฬ+JšปnฺFeI1)Eแะ๑|๏'ฯชb์ฅ…l๊jงฑบท+ฃั€ค•XูษO$y๕Cผy๐ณ๓ ช\งทmฺภGoผซูฬR ภ;v!ห๊Rพ@IฯผR@pBH ๊Rล.~ฺVVก„ฬŒ0Œช๎;%d4ธฆฒ6•a^~อJ:MTV˜ F9:ทฤqฯ•*SืVขำj\๒g/"”U7?ล.~๏šV l๏ลู3}8Mnk(ecน›2‡๋rฆ›’ษI*L"šYd็เ4๐ฺฎ(„ิ{X-fฎปjญ๕ตๆ็V๔:Oเ]XdbึC<™ภiทฏ~nฅ]7]ีla)ไO?$iU๓)%อ]ฏงฒดEIsคฏŸ|๒™5=ๆฒขB6wตำXS•ญํe4db: $-™ L{<|;฿'žPŸ_]ะอ7o[ณ'w์"™Tว๕,๚Ly„‚3BJ P—ZWšวWฏnมm5Lศเ๐0sก˜jฟ๛ค’ๆ ฉqูะญ+ฅั€คษ Žจฌเ ว82๋ฃืใงยa]ำbJซีpue:ญ†… ฒ๓Q9ฅบyYW’วWฏy/ฮ>4ฤฯ๚OoŸo1r{c๋J๒ฒbส ;ญht0ย;S ฌŠเ”rBHอbasW;]-ๆปฐ˜ฬ๏ฝN$๐,๚˜œ™#)หุฌ–๗}~jึC4็cทˆอbม ๒รg^`๕X8+Rฉ4wnฟŽชฒา้4GO ๐วŸ^“cญ,-fSW; Uธœฺู^’ค%ฅ(ฤโ ๆ}่๕zŠ๒๓ะjตLฬฮ๒O˜HLฝkล–๎๎นu;6‹…@(ฤ“;vOจc;๔โR€ฉy!คเL„ิ%คฎ*ห็+Wทg1ˆห|๏ะ*‹fฏ`ั๋ธทญ’บผ”L†ฉ@„DJก4'+8tฺ์–ฐlญข8วๆ–่๕,QšcY“bJ'iูZแFาj่Ÿ๒ว;’H)ช›— ฅy|ๅ๊V๒ญู8๛ฯwู9๘มํเKs,TWยบ’zรuT——’Nง้้ไ=๖ิšcUY ;hจช ฯ้ฤd4 ัd‹ฬGใqๆ}Kฬxฝ„#1์V Wuดข“tLฮอ๑/?xŒ`8‚Zนชฃ•๛๎ธ9gแOํุM4ฎŽตoaษฯ๔ขR@pBH ๊R[*๖–f\#x’|wฅ˜zทaุ :๎iซคึ•ƒฌคู;:วพ‘9บK\ดๅRlท`3่ะ-gmฤไsหb๊ธืO‰ผฆฤ”AงesyVH๐๘ฃ‘•ด๊ๆeSน›฿ฺูLrœฟ์ž…Ÿฉฬตqs] ลฎีnŠ:ญYIJศŒ๛#ผ1๎aฯศแ51๕_QH๔zถtwะัTOYQ!V‹$‘NgH$“ูขื#c ŒŽS_U๑YQงฒ2ํ๑r฿ท`ทZ †ร<๚ีt?;•”ข๐‘mืRSQF&แุภ่“kblตe\ีัJ]eEvkžมํš—ฮfDy}ฬx็ั๋t8s์ŒMอ`1›ุิูŽ^งcฺใๅ_๘8Kม jืŠuญอ|โฃทcต ‡y๚ฅ=„ฃุ๊ฎ>๏[bfม'„”@ œR@€บ„ิตU…|qs.ณฅX’๏ผ3ฐ&ทC-zIหงบjจสต#+ ป†gyฆo‚B›IฃกนะI{a๎)Sาˆห)<‘8ฝsK๔yฺึ†˜2้%6–ป‘4pใ็w$ญยตvke_าŒหlภK๒ooŸd฿ู่ต‡ฏฮตqK})]%. ญ&LหSr:C0!3โ ๑๖ฤษ'๏ผ5+ "a{%’ฒ๚$yJIs๛u[ฉซฌ “ษp|h˜{ไ‰ห:ฆ๚ชŠeUNnNฮชˆJงำDใ1fฝ xั๋๕8s์ง EQุา‰Aฏcฺ3ฯฟ่ —ช]+:›xเฮษฑูE"<๒B*ษ๘๒..1ป(„”@ œ‰R@€บ„ิถš"~sc#Nณ_,ษw JชWHฅา>ฟฑ*งคขฐsp†NNแถšVFาhh*pะZเคiลnะ#"ฆๆฃ z=Y1ๅถ˜.ซ˜ฒtฌ/หG ๔zแŽwU9/ืV๒ฅอMไ.‹ฯู฿ฯ๋cžuŒฦ|๋Š้(สฅภfฦค“ะฎˆฉx’_ˆท&ๆู54C๒2d‘WR’คeC{+ฺZ(+*ภfต “ฒ ’rŸ?ศเ๘ƒฃใไๅ:ฯZDญ”ez†xเฎqุ์„"žx๑ebq๕m#Vาnฝf3๕U•dศะ74ยฟ๐๑ห2–๚ช 6uตS[Q†3วŽษp๊ึผฌˆš๑.`2NQ+Dc1–!ฎูะ…Aฏgv~o่Iผ‹>ีฎํu็ˆซฐ‹ฉ|ac#ฅ9b)…g๛&xkbž“—~NษdhฬwะU์ขยiลfิฃืjศd ก(ฬGโ๔y๔{8L†K"ฆœfล. +คLฅB๊ถ†ฌ๘ฬ1fล็?พqœƒำ‹ไุ๋K๓ุ^[L“Ižล€A’ะh ฉค๑ลœœ๒๊่o\d1uฅ ฉŽฆzึท6SSQ†รพ"ข@N-‹จษiF&ง0DDญpไฤI๎ปfr"ฑฯ๎ทFEม/็๚hฎซFƒ†ฑqพ๑ฝ]ิ๓ต7ึฑฎต™š๒2œ96๔:}ถXนข‰ล˜๑ฮ3ฟธ„คำ’็tž๕qEม็ฐกฝ“ัภผo‰xงŒฯฬชvhจฎไณ๗‰k9ฮ^ุ๛:ลล53>ƒ@EIu•ๅไนฐ˜M่$jVb พก0฿ต@ ฌ"„”@ 19•Yษึ•4แ„ฬL(สปS‹์c&ธvถŸRมงบjฐ๕xรqภIUl5yh5พฐฑbป…˜œโฉใœYภfะŸ๕1R้4Mn'ํEนTๅฺฒSห5ฆ’Šยb4ม o€๙6ƒ๎ขŠ)—ลHGQ.เะ๔"พ๋ฐ*็ๅฃMๅ|v]-๖e๑๙^?ฮแ™ [fkEืVาไvเ21HZเ=1ี็๕๓ฺ˜็œท 2ฎ!ี\[อฆฎvjสKqุํ๔:@CJI …›žexbƒ^AEิ วNrฯญq9Dใ1ž฿๓๓>uึ*บ๎ช๕ดิี ัhŸเฟ๛ศE9O{cWuดQUZ‚รnล ฯŠจTJ!‹ฒเ๓‰ฦt:I:—ุฦ ัีาˆูhbai‰|โFงฆUปVิWU๐ะ=wโr:‰ฦcผธ๗ ๆ.๏ฤt:ƒษhคฆข”š๒2 ๒r1MH’D:FNษ$’2IYๆ‘็v๐•ฯฟ@ ฌ"„”@ /ฮd\#&„คีRาDไ3ม(Gf}ผ22ว๘R๘ฒ๕žึJ๎๏ฌมnิแ ว๙ึ'Iฅี+ค$†/ljคุn&’L๑ฤฑ1Žy–ฐ่u๚XJ&CหNgฑ‹๊\v“รฒ˜J( พh’…ฝES๙Vm…Nาภม้rืUฮหฏดT๐`W-vฃo8ฮื_๋ฅgn้ขœฺ๋ชBฎซ.ค!฿หl@/iษœ!wฯrhๆยfCจ]HีWUฐฅปƒšŠ2rs์๔ูlrJ&Ž09็กx ฃแโˆจŽs๗Mศs:‰ลใผฐ๏uๆๆีYซ่š ดีืกัhž˜ไฟ๛๒YนญกŽอ]ํT”ใฐNQ)B‘พ@€h<Nส’s%“ฮเ…่ljภl2ฑ่๗๓Ÿ<ห๐๘คjืŠšŠ2~ํปศฯอ%ณ๓ต7™š๓r_ำ9‰ฦฑXLดึีR[Y†;7ฃั€Vฃ%I#ห2I9E,‘  ‘ฮd๘฿฿}Dtู‚3BJ ศvู๋,vq]U!ญ…NVfฝ„Vฃ!ษ•fCQz็์ใไ|เฒ๕พ๖*๎๋จฦfะ1Š๑๏T-ค๔’–ฯol ศf&œL๑่ั‚uา93•NSๅดฑก,ŸJง ‡ู€Aาf[งฃIƒ๔ฬ๚ฐ๕NLi ภjขฅ +ค™œ็k{Žชr^๎mหŠO›Aว\8ฦื_ํฅืsqทa]SUศMตลิๆูqš t™ฬJ]ฐlฦิKƒ3๔z.ŒSซช.+esw;๕Uไ9ซRCNฅGขLyผ M Iyฎ‹~Mรฃ|ไ†kษฯuK$ุ๙ฺ[LฯyT๗[ืuััXFซadbŠo|๏Gค”๓฿ฝฎต‰๎–&ชสJ–ทSf3@SJvฮb‰’V‹Vซ=๏๓e2มํ๕Xอf|?๕ฃใช]+ชJK๘ฏ nW6ฮvฝ๑6ฃS3HฺKgค"ั89v+ญ๕ตซ๕พŒ†ำET<™$Oโ…Hฅtหk™R@๐ฮBH AVHญป1฿มถš"ฺŠœ-XNS19[—่ธืฯซฃŽฮ^๚m)tึpo[%ฝŽูPŒ?p’ดŠหM:‰฿ธช›‰PBๆ‡GF[ ฏn฿:)…Z—๕e๙T9m8Lูโ็ูถRฏ(ภษ๙FtbJฃัP`3ัRเ@ษภ๓๕+๊RŸ่จๆพ๖*,zžpŒx๕'ผ_ฤ๊ดZถีq}u!ีนv&=Iปšๅๆ ว96ทฤฎก๚ฯS ซMHU–ณฉป†ชJ๒r—3ขE!2ํ๑229คqป\—์šFวนํบซO*ญUดนซƒฮๆดZ-ฃ“ำ|ใแ!ŸcำญVห๚ถf:›จ,->ฃฎWvฮๆ}K$e๙‚‰จSY๔่lชวjถฐ ๒ƒงŸ็ฤ๐จjืŠ๒โ"~พQ—K<‘dฯ[›X>“H4NฎรNGSUe%8ํ๖ีˆJZ!™LK$I$“„#QEแฬิ-!คเž…‚ำ…ิ Uน6ถีัU์ข$ว‚อ Cาพืษm1š•{Ff/Xฑ็ณแำต|ฌฅณ^วL(สฟฟ}5’›u:~cc=nซ‰`Bๆ{‡˜ ว.เ>Œ1ีU’Gห†รd@ฏ}ฏ^ัR,มภB“  ’–ฒœsSZญ†B›‰&ท%แญ‰yvo*็ๅฎ๎m}O|พ.]‹uฃคe{] [+ จฮต‘c2ฌึ‹ง<แ=ณK์ža๐วฅ!URเf๋บNšjซp9˜ FดZ ฉๅยืำs^ฦฆfHง3ไปœ—ซีj้nidcgeE…ุญึUY’”ณ5ข|Kฤ ๔:’tq3{ฒBช›ลJ โัgwpด@ตkEฑ;Ÿฯ฿/E๙y$’2ฏพsˆc'1~ˆgK")SVT@}U%•%EหR1{%ญR’I™`(L8;ซc !%๏G)@ เ ฉrอnจ)fSน›r‡%๛b|ส๖/<ษเBwฆุ;2Kโ"uพ๛๕ซ๘Hc&ฤT ยทœDซb!•cิ๓฿6ิใฒ๑ว“|๛ภก„|Qฯ‘ST:ญl*หJงู€qe.•4X’_ˆฃs>L:้ฌ3ฆt’–"›™๚R้4ฏy๘_ฏ๖ชr^~m}=w6—ฏŠฯฟyๅ(ฃ—ฑจŽQฯตล\]Y@นรบzฅาbrŠนPŒƒ3‹์šaย9ซcฎU!ๅvๅฒนซ–บ ๓๓0ณQŠ’&ใYXddrEQศuไ\๖X™˜žๅฺ๋NฃcชŒ๛๕m-ฌokA'ILฮฮ๑O฿1แh๔—๗:Z้jn<-#*“aตภาฑxƒโ‹จ—ด5ึ‘cตŒ„y์๙—8t„jืŠ‚<ฟ๙ภว)v็“”e^๗‡๚๚1 ์)Eกขธ˜†๊JJ ุ,๔ห[SJš”’"‘H GˆDch>D*!คเ!%œZมขืฑฝฎ˜ซJ๓ฉ>c๛—œNˆ'[ ๓ฮิป‡g‰$Stฌ_ุุศํฅ%‰‰@„oฝ๎"m๙ธ8M>ทกž\ณฅX’oฝ}’จœบ$็Žศ)*V6–ๅS›—อ˜2๊ดh85c*D|Iฃก4ว๒ ง—ดอิๆe…ิพั9๗kวU9/gŠฯฟzๅ่Y‹ž‹/7ี•ฐตาMiŽ›A‡n9c**ง˜ D88ฝศ๎กYfBฟX$ฌ5!ๅดนzCืชˆ2›Œูbษ้4ฑDฯ‚๑™Yโ๑$.gฮš‰•‰™9ฎูะuš(81<ขสธ๏jibcG+:Iวิœ‡มcร,b๕z›:ikจฃขคปี‚NาไTŠ`8‚gม‡œ’/IFิ™๘Z๋kษฑูE"<๑โหผำฃฮ฿#€\'_|๐W))p“”e<ิร;=ฝXฬฆ๓>ถVฃฅดจ€ฆฺjŠ๒๓ฐšอซ๓•RRศrŠx2I0&Ÿำ6K!คเ!%|8!uช|ุVSฤๆr7uงศ 9!”™ Dุ?1ฯพั9ฃ‰ 2ึ/mnโ–๚Œ’ฤธ?ฬทœ\bช|ษฐ๙์บ:œfพX’‚x๊าv \ษ˜ZW’G}~น&#I‹F๒)bjh!(ฑฐ˜2่$Šํfj\vd%อ+#ณ฿7๚T9/gŠฯฏํ>ยt0บfฦ็0้๙Hc9ส๒)sXฐ๊uHฺl๓H2ลd สม้v L{oญ)ปียึuด7ึS˜Ÿ‡ลdB’ด(้4๑Dฯ‚ษ™9ฒLŽอบๆberึรึuง‰‚ใƒCชŒ๛ฮฆ6vถฃื้˜๖x๙—>†?x๚VUฃAฯฦŽ6:›)-tc;CDBaๆๆI)) z%Q+๘AZjซqุํ„ฃžฺน‡ทซณฆ@ฎ#‡/=xฅ…ศฉ๛๔๐ึแl๓9ำ 7PQRD]e9…๙.ฬ&:IG&“ห•ฎyK ๑D๒ผ จ !%๏G)@ เ„ิฉlฉpsCM1uyv๒,FŒ:)†]INสฬฃผ;ณ๗qr]๗a๏๗ฮggfgg{_๔B€€HŠฝIฆ ญjR=rไ’(ฒ_ž_โฤqlวq^œYv$[qlห‘"Y–dI‘eหN‰^ป‹ล๖:;ฝž?fwY@ษ,v/|พ๑ร™;็œ๖|๑+žผ0๗ถ7๕Ÿฟa3w๕ฆqษ2ณE์…แซฺ๖๚rำ๔๒‰=Dฝn2…/<‡j˜๋2–’ชำ๕ณ;gS2Bฬ๗j1•ฏiŒe‹ -ึ‹hงCฏyœ2อaฑša๐ุ่,_zฮž)2ฏŸฟ๕ุ1ๆŠี 7ฮTะว=}อ์i‰ำpหศ’„nZ”T้B] ?<ฑk.ง“™…Eพ๒o“ษีป9z=๎•”พอ47ึำนœNy-5/W(1ฟ”AUU<ฯU้๖ำศŠ๔wu ‡)W+|ั'xๆศQพ+"ก ์ใฅต)…n่>~Šง%xs๗†iZxฝzฺZ้jkก1€ฯ๋YkZข้[DE IDATšฆSUr…"Šช]–s)„”@ \ŠR@ภRซ์m‰s[wšd˜ธ฿‹ื)#K`ฌDmL*Ÿอ2xa–‹oฑฯฏด…ปำธd–‹|ํฅ[ฏ}:ไใใป{{\,–k|ๅะฺ: ฉUŠŠF:์ck’DdE2ฎค๒™…•ดฬำ๓9‰tฐ.ฆผ.™ๆฐŸŽhอ0xtd–?~žB๊ีโณฤฟ?p”ลrmรŽท-เฎfฎki ๒ใ_‰˜า “ขข1™/๓ฤฮ’ฏi+ำ๕RAฏgpฮํ์ฺOsช๑ี"JUXฮๅ™˜ย4 >฿†ฟVfๆุปc+ญฉ—Eมั3Cุฑด–พnบn'n—ซ.คืwจTซ์พuๅ|% ๚8๕(Uำศ๋"ชฆ(๕›uQซไ‹%๚:ฺˆE"”ซU~๔๘S!ตสฮt7wฆุ–Š’ x๑นdR=จขฬซœšฯ๒ฤ…9ฮ-ๆ฿ิฑๅ;ทrkwN‡ƒัLฏลด๑ฃผ5เม]„V„ิ—žC฿ **A7ถฏŠ)๗Z๔›j˜k*cู็๓Mฑ5!ฅŸŸแ+‡ฮู๒ผผR|Ž-๙wŽฒ|™าNฏ$ฑ ๗๔6ณป9N*่ล๗1u1[โน‰ฅXSฏบ๚๚ถ}ƒm้ฟู!ื;vช*ห๙<็.\d๘โฝํm~[\+ณ ‹\ทu๓Š(ะ9r๒ GNžมaรศอM]|n.๓Kห;;D[บ‰ึฆ—ลa=k5"j Uำ๑n€ˆจืR(•้ikก!ฅRซ๒ใ'žแฑ็๖]แ๗z๙ง ฃ9n=}–GŸ=D4ฉ฿+Wj„Cถ๕๗าำJ,ฦํvฝJDีT•ZM%W, ๋ๆ9—BH มฅ!%\~!ตJ"ฬmMloŠญDmผ,ฆjšมbEแฬ|Ž'ฦๆ8>ป†Ž๙kทlใๆฮN‡ƒแฅ}rl#Šฑ ูEศใdพTRๆ{7ฆ๋[lJึ#ฆฒŒCzน^ุุr‘‘L‘;’ด†(†ม‡ฆ๘๊a{ถY—๏ส-]Mธไบ๘G^’๒ถ‘้iqw_3ปา 4ผx]N่ฆEAัอ88ฑp๛nฺzU7ˆห๙ยmAฟopตๆขj,็๓œg๘โษ†Mษ„ญฎ•นฅ%vnX/>หกใงl™J฿ีษญ๛ฎรใvฃj:Šชโ๓xV๊@ี#ขฒ๙"ณ‹K†Žืใp"jํนUฎะู’&‹Qญีx่้็xไ้็m๛ฎ๐ธ|แSะัฺŒiš;3ฤCO=G,zฯ—+5ขav ๔ััฺL4ยใv!I ร@ีTชŠŠขช”ส รเJ†๕ !%—"„”@ pๅ„ิ+ฅหm]M์jn 9\/ภ์”๋๕*jบAฆข0ด”gpt–#ำ™Ÿzฌ}๋vn๊hDvH -๘๎้‹(บ}…TOCˆm๏$่v2Wฌ๒•CCNHญm๐V"ฆ๖ถฤู!๐โ‘ๅz)ำขข๊๘\2ูAU7๘ัน)์{ ฉ_ปy7wฝ,>ํฃ/QR4อc แฎž4;Vล”S^ซ VPด“๏U Z–u›e1จj*ห๙ฃSœง!ถˆZe!ณฬถ^:Zา˜ฆษั3C<๗าqœฒš-Huำ~บ:p8ิCึZjrพภ์ยšฎ๐๙7ฌˆzYศTiK7‘lˆRU<{ˆ?๑Œm฿.ง“/|๚AบฺZ0M“็†๙ัเSฤฃ‘W}ฎRUH%โlํ๋ฆฝ9M$ฤํr!I`˜&šฆฃjลr…rตŠi^๗งR@๐:o^!คเส ฉUšC~nํNฑท%AKุOะใยๅฐE7ศTTF2žพ8ฯ3ใ ผ3๚฿พƒwด%‘็๓|๋๘v~’$"์ึv.'ณล*rhkƒฯจจh4๘<์oOฒ%!ฌ‹)‡H`˜ว็–๙ž<ลrUฑyyฅ๘<ฟTเื~‰ชฆ๖:šŠrwo3[ฃ$ƒ+b n—$้ชnkŠz[พX˜bhlœh(h[ตสโr–อ=]kขเ๘ู๓FoG;–eqzd”๏=ฟŸพŽv๚ปฺinL๐๛qญœ+0ั šขR,•)W*HŽ๕‰BJ .E)@ เ๊ ฉU|.'w๕คูš ป!Hฤ๋ฦต๒วฒfšjs%^˜Zโภศ eU็ท๎ลžึเิ|Ž??2Lุ๋ฒํฺoOลxฯๆ6|N™ฉB™?94„รfํนŠŠ†ฯๅไ=›ZyG[rM.Z+ขขช1™+๓โL†#ณถSฏŸg๒๋‡Žl˜b๓—ƒ}ญ nํnบ๎ๆซบA๙฿๘๖nนyเšYหlพ@w{+ฝํmX–ลฉแQ๐†R’$ัำFoGฉD>ฏwญธผiškR*W,๒ฤ๓G่lkม๋q๎ผิ•TผฆdEีx๚ศQพ๛ะ[_k_๘๔ƒ๔wv`a1rq‚Sรฃl่ฃ)'เ๓แtสX่†Žฆ้ิT•|ฑDฅZC^็R!คเuษBH ม๚ ฉUœทu7qC{’žxˆ˜ืƒว้@ิ•ขูS๙2‡&นพ%มถฆpb.หW‘xmป๖ปา ฬ@+^งฬdพ.ค์X yฆP!ไq๑›w์$๎๗`Qฏ+%KาZ1ํ’ช1Sจpd:รC็ง7tืบ็.๖ฎˆฯำ 9ี฿แZ๛‹ม4อซe๏็ใwoป~๋ๆม›๚ฎ™u,Kด77ัท" ฮŒ\เัgโqo,Q๎r:้lmฆฏณƒdC ฟื‹ผRหOQU2นŠชั’jฤใv“ษๅ8|Tฟm(คTU#‹ะ˜Dี4ž}้8฿ปGl}ญ}“ฐฉป‡Cขช(†ฑูถฺpUDe๓jŠบa"„‚KBJ X!๕J๖ท%นฃ'M_—งCB7MJชฮLกยK3c*_0๓๙ปwณปน.คŽฯe๙7BH]~7~๗ถwn}อฌcMQH6ฤ่๎เุ87๘4>ฏg]วๅ๕x่lmฆปญ•Tขฏวƒ์p`˜&Šข’ษๅ9?6ฮมc'˜œเ๖w\ฯ}ท฿Lภ็c9Ÿ็ิะัHศ–BJ7 ยมญฉบกs๘๘)พƒnํญ์ถ…ฮ6ZR8ๅบhฒ,‹ชขิETญFฎXBำ๔ [๋K)@ ธ!ค€)คVูัใๆฮšb4ผฮตข฿บi2ถ\โไ|–#SJชf+1e˜ทtฅธฝ;Kv0ถ\ไO_8ว†BjพT%ๆ๓๐/฿น•ฦ —ขข๑๕cXฎ(NŠŠฦถTŒ้A~—Œ,I–EY5˜.”96ณฬcฃณLn1๕๎นŽ้Žอ.๓ผtอ๗๋%คnฺฝcpำŠผนะ4h8ฬๆ.$$†/Ž๓รวžฤ๏[ŸTbฏวCw[+]m-4ฦcx=’ำ2ฉ) ™lžs.rุ่Iฆ็^๕[ฎฟŽ๗u+ŸŸlกภะ่E~nทหŽื7Ÿถtบapไไi๊od›๑o๊๎d๏๖-tทท ‡qป]ศyญขชฉฬ/-S*—1LkรBJ .E)@ `c ฉUzใa๎์I๓๎|ฏ่ไf˜&5อ`ฑขpv!วแษ%–ซŠ-ฤ”f˜ู“ๆึ๎&œฃ™_}aฏำiปkhก\#๎๓๐ซ๏B2เฅ h|ํฅjšมuอq&๓eฦs%ถฆb์J7 ๚ธe’„น"ฆf Žฯ-๓่๐ฬบŠฉ฿ฟw›bXภKำ~๓ภัk๎พ_/!u๓u;๛ป:ฎฅu$เ๗ฑตทI’Ÿเ๛ ๘|Wq ^‡พŽ6z:ฺˆว"ฏŠˆช) ‹หY†.Œs๐่ f—^๗87ํูลw฿Nะ๏'W(0:1…ๅฒฅฒL ฏวM{Kร09zๆ๑l๘qoํ๋a฿ฮmtดค‰†Bx.$ษaXX8ๅzแ๒L.วา๒บ+ฃ!%—"„”@ `!๕โ็_|ฯ>zใ!$๊Eณ%ภนR˜ทฆd* ็—๒œ\bกTะbJ5L๎ํkๆ)œ‰๓Kว ็๑บ์'คห5~ฟrำV๙šฦŸฟ8ŒDฝ“เ+™ฬ—น-ฒmELฅC~๎WGLอ—ชษp`t–๑l้๊qป๖ฒ-ล^œZโท;vอ๗๋%คnป{ฐงฃํZZG|^/๛{‘&ฆ๘#ธ RๅJ ฏวอ๖>๚:‰GWD”์@7 jŠยB&หนั1Ÿ8ล์ยาO=;v๏เƒ๗Aะ _,2>=‹ไpป์(คL<-iLำไ๘ู๓ูทvCŽีแธn๋fvoูD{sแ`ทห…$ีัEี4t@ำuย’C"“อ‘+1mฒ—BJ ^็oN!คภ>Bสใ”๙๗๎aS2ŒaมtพLYีi๛ y\ธ ่หU•‘Lง3LไสO๒(บม}›ฺธฑ=‰์8ทXเฯœวgC!•ฉ($พpำโ~นšสxaฟI<บ฿™ฬ—ห–ุaw:Nsธ.ฆœบiQัtJUŽฯfylt†‘L๑๊l%‰๔ฎ=lME1,8<นศ๏<~šป๏ืKHพoฯ`w[ห5ณŽšฆแ๗๙ุฑฉ‡รมุไ4๛ศใWด†TนRรใrฑ}S}]ํ$bQผn‡ร4จึj,.็8;rCวO1ฟ”yCวฝ~วV>๎ป ไKEfๆั ร–Bส4M.]m-Xฆล‰กaพ๚ญ๏nจ1บ].๖ํฦึพnฺ›ำ„\N0L0PU•|ฑLพXย๏๓าฺ”B–d๓ฒ๙†iฺโ|!%—"„”@ `!ๅw9๙ฝ{ฏฃ?F7-žน8ฯŸโฮžf๖ต&h๊bJv`Y ™&นชสpฆภฉน,ฃหE<จฮFUำนK๛“ศœYศ๓G๊วnd* ฉ —ฯ฿ฐ™ฟ‡\UๅO‘x้Œ๊w'๓eฆ zใแzฤTุGะํ\I7ฒจj:sล*'ๆฒ<~a–แฅย•$สใฝ{ุม0-N.๒O\s๗z ฉ;๗๏์lmพfึฑฆ(|>vmภแp0>5ร๗y๏่ฒทตฉฮvโั(ทI’0M“ชRc!“ๅฬศž้8™\Mบญ›๙่{๎!R(•˜_ZFQU\6”ไฆiโrน่nmมฒ,N ๐'๋;ใ]ๆ๕ฒืvถ๔’N&๘+" tรDืujชJกTฆRฉ 9(ชJ( ต)…S–ษ dry C)@ ฐ+BH ๖Ra‹฿ฝ็:zใatำไฉฑyเ้S๘\N๎์Iณท5NOCˆˆืหQฏญก™&…šฦxฎฤ‰น,รKydว๚ืจh:ฺม๕mIภ้…๙โศ†Œๆ๚‡ศVšB~~๙›h๐นษVUพ|๐mั-!:†fš,–kฤ|nzใแzฤ”ห‰์0-จi:sฅ'WฤิะbŠฬล็’๙ฝ{๖0 c˜ฯŽ/๐๛Ožผๆ๎๛๕R๗ฐoฐญน้šYวrฅJะ๏c๗ึอศฒƒ‰้Yพ๗๐ใx.cบpนRร๏๓ฒ} —พฮv"nWฝXนiRฉี˜_สpntŒ็Žž`9๗ึ๎]›xเฝ๏" R(—˜]XBืuœN› )งLw[gF.๐ๅฏ{]ว‹„ูป} ๛{I%โ|>œฮzM(ะัดบˆสKTชตWี‡RUp0@s*‰Sv’/•ศds่†a‹๓!„”@ \ŠR@€}„Tฬ็ๆท๏MOCอ0yblŽ๚ฬ้W}ฦ้ppkWŠฺ้M„ˆy=xœ$@5-ŠŠฦtพฬฑู,็—๒˜–…cฅk฿U฿ศช:ัลž–8pr.หืฺ2e/WSi๙๙ลฤ|n–ซ*Y๚a’7_Kgนชเuสt7„hV"ฆ๊ลฯkšมBนฦ‰น,O\˜ใฬB๎ฒฮ%่v๒ป๗ผ‰๗๔ลy๓Sงฎน๛~ฝ„ิฝ7ํlmJ]3๋X(–์ูถง,39;วwz ฯeหซ"jืๆ~z:ฺˆ…รx๎zjžaPฉี˜[\โ๔๐(/œ8ฆ#ข^หŽM}<๘พw †(UสLฬฬcYฆ-…”eZศฒƒ๎๖V†.\ไ๊[๋2–T"ฮ๕ทฐนท›ฦx ฟื‡,หX–‰ฆฏˆ(E%[(PSิืํ˜งj‘`€ฆd—ำIฑ\fq9+„”@ ุ!ค๛ฉ„฿รo฿ฝ›ฮXอ0xlt–/=w๖'~~[’ป›่O„i๐{๐ศ2‡„n˜U™Bฝp๖K3หฆyี  ๏๎aWบ€ใณห๕‰ฑ •V๘FษืTZ#>ทฏŸจือrEแKฯŸeGSŒศH]สVUd‡D_"LŠ˜rส๕TพšฆณXQ8=Ÿๅภศ์eSฏ‹฿ฝ๛:zV"๑ž›ใฟ<}๚šป๏ืKHฝ๛ๆ›“ืฬ:f๓Bม๛vlล);™š›็ป=†ห๕ึ๏ใrฅF0เg็ฆ>บ[iˆD^ีmญ\ญฒYๆไะ0‡Oœ&›ฟoฝ๓กiZhบ†ช้ิ…\กˆขjฏ+ขVั4H(@*‘ภํrRชT™[\5คภฦ!%ุGHฅ‚>~๋ฎ]tFƒจ†ม#ร3ทƒ็ม๏ํi‰s[W›’โ/^งŒ,ฑาัMgฆPๅ๘2‡'ัM๋ช‰ฉ‚ข๑ฉ๋zููรŽฮd๘ฮฉq6iใฺนดG๕Dผ.2…/>{†mI|—Aฐ-WdIb กeฅˆ+ป+.”kœ]ศq`d–S๓ูท๕[ พบ๘์nก&ƒf๙โณgฎน๛~ฝ„ิ{nฝi0•ˆ_3๋ธดœ% ฒ็v\N'ำ๓ |๗กวp:฿}\ฎิˆ„ƒl๋๋yED” ึ"ขๆ—2œๆเั“หๅห:—-ฝ|โ๛ˆ†ร”ซFฦ'qสฮŸ*J64–EoG;’$1<>มๅ7ธ๚๗ดทฒg๛๚:๊=w=ฝา2ัดบˆชึjไ %4]C๋ซ๋:‘Pˆฦx ทหEนZcf~Atู#„”@ `!ี๒๓›w๎ค#D1 :?อŸzร฿฿ใๆฮ›b4ผ๘\2ฉžVั JUNฮๅxaj‰’ช]q1Uจฉ|foS1Lเล้%~xfู!ู๎**ฑ doa‹ฅฒย}๖4ทv5!_ฦ”ศลr งรม@ฒ1XํฎhAM7X*ื8ฝใษฑ9Žฮ,ฟฅ฿Hผ๖]ปึ"๑Œฮ๒G?%ฯฎฌ—z๏m๏lŒ7\3๋8ฟ”! rร๎ธœNf๙๎รฝฉ๛ธ\ฉั ณฅท›ž๖6ขแn— Iช‹จrญส์"งG.๐์‹วจTkWd.›zบ๘ไ๗‹D(Wซœวใv!ห๖R†i2ะูไŸไ‹๙ L๓สฝ๎6๕tฑw๛zฺZ‰†C+้•†iขjŠขR]‰ˆ2 ๓M‰>]ื‰†ร$bQBช#ไ7n฿Ak8@U7๘ัูIลแท~ผh[ปS์Nวi๛ื๊ญฆ-Wฮ/x~b‘…R๕ฒ‹ฉ‚ข๑น๋๛ูม0-N.๒๐๙i ฉพD˜๏๊&ไqฑPช๑GฯŸๅถฎ+Mmก\รแ€พx„ฮX๐+ฤิ๊9<ท˜gpt๖ ‹ฉๆฐŸ฿ผใญGโู…๕Rธ๋ถมX$|อฌใไฬัpˆ›ฏฟลb†๏<|€ŸvฏŠจ›๚้lm&z9"JืuJี ณ K=3ฤ‹'ฯPฎVฏส\๚:๙๔KC4JฅVๅฬ๐>฿ซบฝูหดะMƒM8ฦงf๘รฏ}EU/ห๑‰=ถฐk๓ํอMDBA\N’†aฎีˆ*–ห”+ีทZg&ัp†hฏขjŒOฯb!"คภฎ!%ุGHu7„๘ทท๏ 9ไงช|ฬ8๕า่>n*่ใถ๎&ฎoMะ๖๔ธp;$,@ัM–ซ #™/อdฯ– ธ/O฿’ช๑น๋H†1L‹gวxdxฦ–){UMง?แ„x๗ํƒัp่šYว‹S3Dร!nฟฏอา2฿y่ผŽ((Wj$ใ1ถ๖๕ะตๅvีEทn่”+Uf9vfˆร'NQSิซ:—๎๖V>๓ม๗‘ˆลจึjœ—ฬ=i๖ถ$่‡ˆxธ^!ฆŠŠฦลl‰sY†—๒ศoqใQำ >ทฟŸž†0ša๒ไุFfถ่Z`K*ส‡ทuโw9™+U๙ณ#รุ–\—๑ฬ–ชH@"LW,Dฤ๛ฒ\T ƒๅชสะbžgวxf|แU…_‰๗ƒ3|ํฅ‘k๎พ_/!๕ัw5 ๘ฏ™uBjk*สฏฒฆ ’ช๓ญใc|็ิล+๖{N‡ฤ-]MุHoทo€ฎ†z7ทวFgy|tŸหiปkH5Lถฅข|pk>—“ูb…ฏฝ4สพึฤบŽkฆXซ]ื๕บqษ,ซ.ฆฒ5•‘ฅ"O]œใ™‹๕๊๕HผํคC+‰ทQX/!๕ภ}๗ ๚ฝkfฯŽ\  sฯอ7เ๓xXสๆ๘‹๏H0ภพiKงkฉyšฎS,•™š_เลSgy๑ิ™+Rh๛ญะ–N๑๓๙๑5Uๅฤนaย’ ำˆ ร@ี4ถ๔๖เv9™ž_ไ+฿๘6™\ }ฟ)g๏๖ญl๎้ข1€฿๋E–e,หDำuTMGQTฒ…<5E{S๓*>‡ฦD^w]HMอฮc˜BH ]BJ ฐฺัใพyA/EE็วF๙™‰ซ๒๛’D_"L๏ม#ห8บaRRuฆ Žอfxiz4฿Ptอ0๙…tFƒจ†ม#ร3 ^˜ปl5ชฎ&šaฒ#ใ-๘œ23ล ฿8z=-๑ 1พ้b0ูšŠั$บRc  ฆ›dk ฃ™"ฮ’ญชkโณข]นHผ๕fฝ„ิวs๏ ืในfึ๑ิ๙"auหM๘ผ^J• s‹K4D#kQ–ต"ขสeฆ็8r๊ /:‹nj.อฉ$Ÿ๛่I%จฉ*'ฯ  lูhAื๋ัK[๛zึบ้7ฟรBf๙ง~ฏตฉ‘};ทำืูNc<†ืใAvิ›]hš†บ’š—-Qีซ#ขV๑ธ4%โx=jŠยิ<†!„”@ ุ!ค๛ฉอ _๏J2เฅจh|ํฅQ~tn๒ชŽแบ–8ทu5ฑ9!๎๗เu9‘%0,‹ฒj0Sจpr>หกษE4ใง‹)ด๘…}ฏ๊ๆ6xaŽ๐e๎ๆwU6ฆษฎtœ๗nnร็”™*”๙ู๋nุPใœ.TะL“ญฉ(ฑQ_]LI€bิ๋„อ—ชดGƒDผ.Jชฮ_ŸใoN^ผๆ๎๛๕RŸx฿ปWฃ…ฎŽŸ"ัใฝw‚ๅฦฒL ำDvศ€ต51;ฯฑณ๕ฎyMDญ’N&๘ค)GQตต”=; )MืQTm}=๕๎‡Kพ๚อ๏2ปธ๔บŸ๏้hcฯถอ๔uดF๐x8$ฆeึE”ฆQฉ)ไ %4]ฟช"jทหEบ1QBJ lR@€}„ิž–8ฟzำVEใฯ ๓ะ๙้uหถTŒ[บRlKลHฝ๘\2Iยด,*šมBฉสษนGฆ—(*ฺ๋Šฉšn๐/nุL๋J7ทฟšโษฑ9ข^ทํฎ!รฒธฎ9ฮ}ญx2S๙2฿9=ฮŽTlCŽwบPA7M’zใแตˆ)Iช‹BY’p8$jšม<:zESCื‹๕RŸบพAง,_kธธผLตฆ๒ฮฝปH'“8–Uฏ๗ฃ้…R™‹S3?wžOม47๖ฃถ1ภ/>๘!าษชฆqb%BสŽิk;ฉl๋๏ญw?ฬ,๓฿ฟ๕=ฆ็_ฬ`sO{ทoกปญ•h8„วํฦแ0Lณ~ Eฅช(ไ๒E ำ\ตŠ้$Jฎ ฉ้๙… +7_‹R@p)BH ๖R๛’‹7๗{ศีT์…aŒฬฌ๋˜บBั“fGSŒtศOภ-#K†5Mgฉขpv1ฯ “K,Ujkbสด,rU•_ฟm-แz๑์žเ้ฑy๖Kgฒ,‹=- =ะ‚G–™ศ—๙ม™ ถ6F7๔ธง e4รค/a &ๆ]ฉ&IH+็iC=5T5-สІื%ใ‘e$ 4ำขXS].๒ยิFfm)ฆ„๚‡ษdsศฒƒŽ–fา‰KDTฎPโยไลR™ปท)”J|๋Gs๔ฬ9]แ`€‰Ÿฃต)…nิ#ค~{FH-็๒ไ E๎บ้ธ]ฎW›wบa ฏtฬ+”ห”+U6z*ฉ์pะาิธ!5ทธ„ข !%vE)@ ภ>B๊๎f>{}Qฏ›LEแŸ=รแฉฅ =fฏSๆŽž4{[โ๔%ยDVŠg[Vฝ๘j๑lE7๘_ว.๐๔ลyšร๖พณ3ลm]Mธd–‹<>:KOCศv๓x~r‘_~ว&V"๑Œฬ๕นูา%๎๗\"ฆฦseM.๒่ศ eี>bJฉŸ&3 Htทตะ”L๐๙p:e, TM%[(rabŠ#'ฯpfไป6๐ภ{฿E8คX.๓ํ?ย‘“glwํ~>ษŸฃ-„n+Bส~‚<_,‘อ็นn๋ใฑตˆ'ำดะ }ญXyฎXขZซญHฦ์pะ’ชG|ี…นฅ Šชฺb์BH มฅ!%ุGHฝซฟ…ฯ์้#โuฑTV๘โณง92ฑษFBโๆฮ7u4า๓ี‹g;V6J–e1]จr`dš‘ๅ†iฎ?ปpKWŠ[ปšp:Œf |ป‰C”*eพ๓๗8t”ํฎ}ฟืห็?๕อitรเิะ0~ป)หขPช ้D‚dผ€ฯ‡,;ึžฑีšBฅZcนGQดuํ˜๗Vp8ดฎ )Ue~)CMQl1v!คเR„์#คณฉO]ืCศใbฑ\ใๆ4Gg–mท๛Zั“f{SŒ„฿ณ๖ฏ๗๚Šุ˜)T8:›แ่ฬ2šaฎuๆ่ึฤอ)œรKž›˜ง=b?!๕โL†ฯํ๋'๊uณ\Q๘ร็ฮฒPช’x)*1Ÿ‡;’lJFH๘ฝx2‡„f˜u1•/spb‘'ฦๆXฎlอขR/“+qส2m้้ฦ$~Ÿง,ื›h*น•ˆจCวOq~l’๏oํ๋แ๗฿G$ขTฉ๐ท<ฮs/ทต๏๕ธ๙Ÿ|€ŽึfLำไไะ~฿ฦฎiง๋๙b ‡$‘N%H6ฤ๐z<ศ–eญ<_%4]g~)S?ื6Qซ8$ญ้zสžข*ฬ/-Sต’852z๛‡๎ฝ๓ @๐๒๓Q)@ €ฟ๕คตTู๘ิฟฅํ๊!ไqฒPช๑OŸโฤ\ึถ๋๑]=|dGฝx6–…iCชง๒•Uƒูb…“sYN.ฺBLู“ๆฆŽFd‡ฤะbรSKดฺ0๐๘2ŸOฤ๋"SQ๘โณgศืT"^๗ฺgVลิ;ฺ“lIFˆ๊bJ^Iๅ+)ใน2/N/๑ุ่,™ x !ู|E[บ‰ฆdŸื‹์ฑฌบˆสๆ _œเลSg_WDญฒนท›Oฑp˜rตย}‚งตต๏r9๙ยงคซญeร )]7ึ ทค’4D"xฏง\Q5Ue9—g๘โ/œ8อ่ฤิ?xผ๎N>๕ณ๏!‰PฎV๙ัใO๑ฤก#ถป๖eูมฏ|๚ctททb™'ฯเ๓z6ิu RญโrนhJฦ‰†Bxn ร4ฉ) ™,รcใไ‹%๎น๙ยม Šช257nถ}gผJHi*‹™,ๅjuCŽ3๐ใqป๑z~O{+Ÿ๙ะ๛‰GฃTk5z๊Yyๆ -ŸKฟ๒™ัืัŽeYœน€หๅ\ซsท†ฎ8Nใ1"ก .ง IชKชrญสยา2C.21;iึ#  ฅ2ก@€ฟgˆ†ริ…ูล%TMรฎผVHer9Šๅสบหแp๔๛๐yฆeแ$’v6ลhz\ธ ่&ูชยpฆภั™eฦs%.็บฮ็พMญ์iIเNฮgอ‰พข๎’]ธ˜+๑ั]kฉก๐ิi|ฎ7Wนจhx]27ถ7ึ#ฆ^!ฆ ำคฌ๊Lๅ+ผ4“แ๑ัYฆ W๚ว คJๅ ท‹–ฆT=5ฯใมแxนฦP&—g่ยEŸ8ลฤฬ[ฮึf>๛แ๛IฤขT…GŸ9ศ฿?๙ฌ-ŸK_๘๔ƒ๔wv`aqvt ‡$!หWฟธฆ้่†฿๋!ู#เZ)Fฎ้ๅJ…ูล%ฮ3>=ปึMo•ชขโr:๙ไ๗‹DPT•ูล%Uลฮดง›๊BJำXฮๅษK๋& eูAะ๊ˆ(ง,c&ชฆขจีšยb6ห—็_‹.{@๐„เ—pะบซ7อŽฆฉ Ÿห‰ำ!กฏlœg ีต๓dพผnใ'{๚xฯๆ6|N™ฉB™0x‚‹ู’mื๕บ*บyIญ"ร4้KDุัฃ#$์uแrิ7_ši’ฏฉŒfŠœœฯ2’)เ–ืงƒิ๛6ทฑป9Žœ˜ห2‘+t;mw^& e>ผญฟซ.คห3ง๑ฝลฎ\EEรใ”ู฿–`Wบฦ oญF˜aZTดzDโฑูežaๆ*ŠฉkUH้บNพT&๐ำœ&‹^"ขณYฮ_็เฑ“Lฯ/ผํ฿์hN๓ูOฒ!FMQy์นCh๐i[>—>ษ่๎`่ยELำฤๅบzQ˜หน<บnะ˜h )'เ๗แ”๋ฯMื)–หLฬฬ12>มไ์<๎Ÿ โ ำBื๕ตTJES™_ฬุข+Oธm+BJีt–syrลโURk"สํฦ๋๕เvน ำDำ4UฃRSศๅ hบŽํโฟล7„‚ื>ื…ธ็ฯฑบbA๎๊mfWบTจพqฎื0ชw}›.”96ปฬc#๋#ฆ้๕ฬ@+^งฬdพฬ๏<~|]ูๅ•]WSร’๔k)บAo<ฬึT”พx˜จฯฝ๖Yอ0)(น2ว็–^*ผกณหษ๛ทดณ+ภ๑ูeๆJUผฒฺซฯซ|`k๛Jjh…/>wฯœGQัp:$nhodG:F:ไฟDLอซผ8“แภศ,SWแบพึ„ิโ™\žŽๆ4]ฤcผžWคๆ) ‹หYฮ]ธศแใง.‹ˆZฅต)ล?่hŒวจฉ*ƒฯฟภ{า–ฯฅ‰ŸcSO'Ccั4็สG:ๆ‹%jŠJsc‚ฦDŸoฅะƒ๙RuEฮ0v#ฏ!5ทธฤR†žถVบ;IฤขxW"ข ำ ZSศdsœใะ๑“ฬ.,]๖y57&๙ฯ}Tขšช๒ไก๙ฃƒถ|.๒ว?ย–n$$†/ŽSU|^๏•๙1หขPฎ ้:้D|ญะผ,หX–‰ขึEิ๘๔ '†ฮ“ษ๘฿๘XTM็๗฿G"Eัด •๎ o\^QCJีtr…™\‡รqๅ~ิฒe™P0€ฯใมํvฝ*"Jี4jŠŠขจ”*etร|ร!%ฏ๓\BJ .RซดGีำฬฮ๔kปพYฏฺ8?:2ร๘UH๛g๏ุฤ=}อธe™‹นฟuเ๓%๛n.ุูล‡^™๖๔›ซUTT4ƒ>nhOาŸจ‹)ฏSฦแะ_Q@๛ุ\†ฃำหจ†yE  pkW„ิ‹ำr5{ ฉLEyUj่<‡๛2o๘ŠŠ†[vp}k=•ฏ)ไ#เvฎl๒^Ž˜:>ปฬใฃณWคVš…ิโ๓™ez่๋jฏ‹(ทI’0M“๊JDิ™‘ /ต„ใภป๏ผ•ถhบi’Hฅษๆ๋ทอ[Bขซฝฟื‡i™ค29โฉิІฮ›ฆ…K–hŒDฮQฒ,cYZ5ฌผฌiไ E,~M๏+„”@ ผฬบ.„”@ ผบZข+์็ๆvvF้๛(nฎJEว…|p^โSืnaฯ๊v—ฬh2หง"ฉR๎˜๔ั๋ธ๛ฬJœgฟก@๒œfTvwGhkXฮ[jท, …2Gb)ฬ$ศ”๕Sฒ$q฿ภ*ถด5`9ฐwj‘xAซหP๓œnœี๚ู็Oโv]๘J/ล%ณน5ยๆึFบ#~หb๊๔ุšK๒๘XŒกลฬผzRฑล8๑dšuซ{้_ีKSค*3ชส%ญLl1มเศ{#~+ขฮฅน!ยo}เ=tถถ`˜&ฯพxˆ๙ัฯ๊r]๚๘๏bฦuศฒฬ๘ิ ษL†p0๘†%Gฑ\Fqปioiฆ!ยฃจศีVีRYc1‘dxbŠมแQ4xC"j วqธ๏Ž[ioiฦ0L้ ™|n„!IญQ>?ฆe‘ฬdHคา+"ค*"Jฆฑ!Œฯใมซช(Šฒ\qจ:eM_Q๖๋|†BJ ^f]BJ ^ปZข5่ๅ๖u]์์jฎด๒QัQ6Lb๙Gbic(žYฑใฃ๋ธ~unYf$‘ๅ?=Yอจ๋~nH๛?>w๗ ด^ไ4ฅฺถญฝ‘ฎฐฟา&IX”M‹Dกฬ‰ล ฯOว‰สoXLนe‰๛๚ุิมฒž›Zd!_ฆมซึธ “ึuข, ฉ!—|ั>฿ใ’Yืak[‘ภYโทl˜,สO๓ศศ,'€˜ช![Œ“Lg่๏๋emoM aผชŠ$UDTฑ\b!‘โ่ษ๖>vQ*ขฮฅ!โw>x?]mญฆษCG๘๊~Z—๋าฏฟ็ถoZ,หœšž%žL ‡ฮ[rhš†ชชดE›ˆ„‚จŠŠ$Igศฤ$ใำณ่บผ‚ีˆ–es฿ทาูล0M’้,้\ŽzE’$:ขอ~,ห&™ฃRE IDATฮOฅpปฯ_›ฆ…%ำ ใ๓z๑( nลฝ\qXฎถๅiบ~^"j !คเeึu!คเ๕ ฉ%Zƒ^nํ๏ไ๒ฮfบ#‚๊้ŠŽrตขใp,ลใcs_xใb๊฿]?ภต}mธe‰“๑,๚๐ tณnฏ๛น!ํ+]‰“ำ \ฒฬๅMหํ–!Uมํ’q‡ฒi‘,jœŒgynj‘XฎtbJuษ;ะวฦ–0–ํ๐ฬdๅข~O‹fYgต†~๖๙!T๗ลo=T\2๋ฃaถต75vถํP2-๒%Ž-คytdŽม…ื/aj]Hลใคฒ9ึ๖vำฟช‡ฆHชR5ฌผาšwdh˜็ฝคข! ๐ปฟ๖^บ0-“}‡๑ๅ๏ธ.ืฅ๗vlˆห%393G,ž 1~]๏aY6ฆeโvนi‹6PJ๕฿, ฅ๓๑CใLอฮc;ึ9หฒน๗Ž[่lmมด,R™ ฉl )Y’hmn" `6‰ิ๙ )ำดpป]4E*Qช[AQ”ำญyบNIำชQฅ๓QK!%/E)@ เ…ิmA7ฎigwwtYLYัฑXิ8:Ÿ:๏็%รžm\ำ‚K–8ฑ˜ๅ?์eำช๋พา~ก+qlวA’$6D#์่hค+ ไQ–s‘4ำ&UึŽg94—b<•วฏผ>ใqปธo`๋ฃaLแ้‰fณEฺƒพบำq–[Cว’9>ทw๛าeaษ’ฤ๚h˜MtEUท,แTซ*S)ž‹q$๖ฺิjUHลใไ๒๚zบ่๏ํก!Ri๏’คŠˆ*–สฬ-ฦๅ้‡j"ค:เ๗๑{z/ฝ˜–ลฃƒ|๑;?ฌหu้ร๏บ››qป\Lฮอ1;ฟHSCไ5ฝึ0MLหย๏๕าาุ@0@ฉฮรด(‹ฬ.ฤ99>มไ์ ใ>๋x ‹{๏ผ™๎ถ6,"•ษ’ฬdฉW$ ตน‰p(ˆmฤSiโฉ4ส๋RgŠ(ฏg)#JA’dlB7Ltร —//•Xฉg%!คเeึu!คเ ฉ%Z^n\ำฮ•=-t…„0๚7๗ฌขฟ9Œi<9>ฯLถ@w8PWcb;Hpร๊๖ๅึะฯํยง\๚,,วqุิฺภึ๖Fz#‚žŠ˜ฒซb*^(sl>อSงๆya6๑๊็ZcBjID๕๗๕ฒบง‹†PZษฐ1ซU5s๓‹e๏กฃ5Nํ๓z๘ฝฎ,หๆลม|แ฿ฏหu้C๗ผ][7ใvน™Šล˜ž›งนฑแWพ&•ษb&mั&ฺZš ๘|ธ]•9c˜&นBษู9†OM2=ท€z‘ฒๅtเ;nกงฃหถHgs$า๊วqhmnข!ยqS)โษŠ๒๊•ญฆiก*nย!|^/ชข *n ’eZบก“ษ.ˆไBJ ^ŠR@ภส ฉ%ผ*ทฎ๋ไŠ๎(=‘j5ฮREวbตขใใ๓šKพๆ๗๔Mูำ‚ .ค๙w žื๑?ผv 7,…ด'ฒ|v๏I|สลฉฤัL‹5M!ถถ7ฒฎ9LƒO]–O†e“ำ &ำฦ’ŒฤsHฏาITผk`k›ย–อ/ฦcLฆ ฌn ึี˜่–ว-Ÿี๚O๛NโWj+œ}]4ฬถถFV5—ซ–ฤTขจq|1อใฃฑ_)ฆjEH-‰จuซWัืIc8ดœ3dZ&…b‰นล8‡ŽŸd‘Ar…ฺ%อฃ*|๒ร๏gUw'ถmsppˆ๓ญ๏ีๅบ๔มwลpปLฯฯ393Gดฉ๑e6›/ iญ-ด47.‹(วqะ ƒl>ฯไlŒcรฃฤ๘}ท…ทฌ๋{๛-ฌ๊์ภฒ-2น<๑K1ถRุถMKS#M‘HEH%S,ฆRจฟBH™ฆ…ช*ๅ๑ * Š] +wlLำDำuฒ๙"๙BW]์ฯ!คเฅ!%ฌผZ"์Qธ}};;›—œ—*:ดฅŠŽ…4Ožš็…™Wฏ่xเ–์์Š"GๆS๛‡ิ๕uใ๋ธฎฏา>ฯ๒น}C]|ไu“?ปบข๔7‡i๒ฉx.$IZSณู"‡็S -d0l๙eXB…{ทฌbuSรฒy|lŽSฉ<๋šรu5&eำ" บyหชV\ฒฤะbEHjqท@ึ4‡ธฌณ‰† a‚rF>Xผ 1ด˜แััน—S—ZHลใหeึ๔tณบป‹†pจฺ:Tyˆฮ—Šฤโ<~’ฝ‡ŽR,—k๖พqป]มG>ภ๊ž.lๆ๐‰a้฿ฉหu้oฟ“+ทoEqป™™_เิ๔,-อg)ว![(b˜&ัfZฃM๘<^\.Žcฃ้้\މ™9Ÿ8I2]‘๓ฮ‡bYใพofUw'Žm“ษXLฅจW,ห"ฺุHดฑ‡…dŠx"…ชพTH-UD5V3ขwฅ"ชา๚zZDer ฅา?v!คเฅ!%\8!ตDƒWๅฆต\ั}ลŠŽ‹ๅลูWฎ˜๚‹[/ใฒฮf$เP,ลY} ฉรึsฤวUน$ว’ำ Zƒ>ฎ๊‰ฒ>กู๏ม๋v!หฆeS0Lf2Eฦผ8“Dท์ณะ#^•wm้ฅฏ1„aY<2:วx2ฯฆ–H]I^7i๒ซgต†~~0มZRKฉถอฺๆ0;;›้m๒ชจฒ„CU5N,dx๒ิ<ฯO-.ฟ๎R ฉ‰™Y๚บ:YำE$ชถQiอ+–˜™_ไศะ0ฯฎ่iม%มฑ๙4g๐%—ื‚nูlˆ†ูัD_cฅbส]อำญฅVพ ฯL,๐๔ฤย%R๐ตo๏ู=ฐ้๑U]„ƒมๅ หฒศ‹Lฮล8zr”็Fำบบw>๕ัะฟชวq862ส?~๕[uน.ฝ๛ฎ[นv็TEav!ฮ่ฤ$ถใเ๗y้jkฅ1ฦฃชห"Jำtโฉ4#SฅT*_rตDพXโ]ทฤฺว!W(‹'๊VHฆIs$Bkด ‰…d’…xGล4-ผ•H(ˆ฿๋EQ”j |ED™ี๓2ู<…b Iพธื@)@ x)BH OH-แW฿ม5ฝญฌjจ๎๘ๆ’qœำฮƒ ž:งขใฟพ“mํ8ภ 3 >ศ‹u}ฯอฤ๚ง}รDผต!>ršAPUุีฬ@[#ํ!3ฤTษจd‰ฅ80“ มง๒ฮอฝฌjขYœa$‘ใฒช@ฌ%H€•ึะฃ๓iพp >„ิšiฑ>ak{#อกŠ๘ญfธ้–Eฒค3ฯ๒ฤุrูE}@\H$๗DBมว+KืEfๆx๑ุ ฌ;ตฤ'?๒~ึ๗ญยมแ๘ศ8•oิๅy{ว-\ท๋2<ชB*“er.F{4J$ฤฃจศฒŒe[”ส‹‰$'OM28<†n5#ข–ศKผ๓ึYทช‡\กาzฑeฬJก๋ a:ขQ$Ib!‘d!‘$เ๗ำโ๓xฮQT[๓ช"*—งP,"ษ๒%9v!คเฅ!%\|!ต„OqsKW๖ดฐ๚WTt<=ฑภณ ๕ปhkภLวyเัƒu}ธeปบขHT2ฑพฐ„ฐทถฤGN3pหWtทฐญฃ‘ฎฐŸ€๊ฦ%หXถSmน,3•.ฐ.&๊๗R6-~24อษx–+บฃu5&‹ล2kC\Ui =K๑ๅGk3C๊UะL‹พฦ ปปฃ๔5i๐V‚๋+ญ|6ษ’vcWุQวู<ฎ&๙B™๙EdัALำช๋๙{zึฌ`h์๓KR—็qฯm7qำีปQ –eaูึ้–/หขX.ฑH121ษ๘๔ บn"ืจเ)–สผํฆู๋ฐบ‡|กฤ์ย๒%’2oxN๋: แ]ญญHฒD6Wภq์สŽyชŠRอณ,ร4)k™|ฅ"๊RŸณR@๐R„.Zย๋vqsWvทฐถZักV3ฆ–*:FYV5้Ž๘ฑุ;ตศ_ฟo˜'วcิ๋Jืw์dk[E|˜I๐อ#ใuU‰cฺ๖้ฌขฆ>u9,ุดmE๑dž‘Dh๚jœ&3.๋lZ—3qพst๕ฆ™๏Eรค'dggำ7ฌiฟจˆณฟ#;[–฿็ฅ!ฤใ๑ ธ]ธ].$I^ฎŽ*keๆใI๒ลbอK6!คเฅ!%ิฎZย-Kนก›\Oะฃ,WIูถƒnูdส:ฃษฟ<5ฯ/ฦ็1ํฺorห2ํŽlj`ูฯM-๒รใSu[‰“ื ไ๚ญด‡|ุŽCAทP]žjศฎaูไ5ƒ™l‘แD–‚fา๐ ิุ_๓ว’9ฎ^ีสๆึ–ฯO.๒“กi\uบ+ื+1—+2™ส฿๘ˆR+wn๏น‡ํ›ึ#ห2งฆg๙ฬƒ_ล0ฬš9พฮึvmฬฦตซimnฤ็๑โrนpM7H็rLLฯbZ—mˆฯ๋%‘N๓…>Z—cbšoูนƒ›7, ฉุ้|MgHY–…ฯ๋ฅ1ฦซชธ๎ๅ]๓tร\1‰D:อ|~๋e๔7‡pะ, Y’–ย™ัชbj,™็๑ฑ9~yjพฆ+ฆผn๕๖lh cูOO,๐ำ“3u[‰S4L๘๚ฺƒ>๒บษำ ธe‰ ัอ~^ท Y–0-›‚a2›-rh.ลX*GGะGO$P็1’ศr๊v6VวๅูษE~6<ณ\™๗f!–+1‘ส !ต‚|์พwฐc๓F\.™‰™9๎‹_ฃฌ้—ธVuupลถ๚๛zˆ66,W?ูŽฎ$3Yฦ&ง8p๔8'ฦNqำีปy๋ืแ๗๚Hฆำ<๘ึeปTชŒฎฺฑ•หถlยํr‘/kVHูถ฿๋%แ๕จ(n7n— วก’ฅ่†AฉT&ฺิˆโv“ฮๆˆงRหู~ตŠใ8!คเ%!%ิ‡Šผ๙-;่k aXว2” “ตอ!ฝr๏นผ*>&f็๘Ÿ_๚:ลR๙’ฯ๚ีซุ9ฐ‰U=4FยxTuYDišN<•fxb’‡ŸžY~ž+w๑ถ›ฎ'เ๓‘สd๘าw„ปN+7maืึอ์ฺบทห]ูe/6TCBสถm>แPฏวƒโvใ’]€ƒaZฆฆ้คณ9rล"^J_W'ชขษ็Iค2ฆYำใเุใ‹BH มน!%ิ‡j ๚๘ฯท์`UCอฒxxx–ื๖ตr]_๋šร4๚TT— Iชdฅห:ฃ‰{งใ<::‡VCหGผ*y๋eฌmcX6OŽวxbอ‰ล อ~ฯ%S'YnZำqZŽฯ๓ฤx์M7็ eฦBHญ$บ็mหโc*ใ}้ไ …‹~›๛ืฐ{Vww ๑(*ฒ,cูฅฒฦB"ษะุ)๖df~แ%ฏฟnืeผใึ=|~Rู,_๋V”;์ุผ+ทT„TฉศฬR œm>B!TUฉŠจŠ([QฅฒF&—งฌiธ\.4]ว๏๕าูŽช(ไ EๆI,หช้qฐm›ฟ๙โื…‚sBJ จ!ี๖๓้›wะ  Y?šแณ{‡*‹9pm_W๗ถฐฉตฆช˜‚สno™ฒมฉtžg'xtdŽr ˆฉfฟ‡?ฟๅ2V7…0,›วF็xfrกn๏!หq๘ิ[6ำ๐’ี F9 ห:+หด$ฉr๎AUมงธ๐).\ฒŒe;”M‹Dฑฬะb–ฃ๓)ผ๊ESC๑ ทฎ๋dmSEb<ฦSงๆ฿ts>^(3*„ิŠ๒มwลU๑1=?ฯ?|๙›คsน‹๖๙;6m`ืึอ๔vถ …PI’0-“bฉฬB"ษเศ๛ ฒHพโ๛\s๙v๎นํ&‚~?้l–ฏ|'ิsว๊ึ ๋ธjว6Tล]mู[X ๔Rเุ6~Ÿ†pZiอsนd ำฤ0 สšF*›ฃฌ้gUง้บ฿็ฅปฝ ช/•˜-โิ๘^ณ–e๓™/ !%็"„”@ PBชท!ภŸธ๎H€ฒi๑ใกi>ฟ๏ไK~๎สž๖ฌiฏfฉ•Pm@ทฒe‰t_žš็๑ฑฅK8๔๒ภอ—ฑบ1ˆnY|dŽ็ง๋๚>๚ไ5›‰tr†3‰บฝ‡dIโ“ืlขษ๏!]ึ™Hะ-ล๕ซ โQ จ.ผŠฟ…ฒToVฺ.‡ใYF’Y\’DgศAฯใ๘b†ป6tำืฤฐ,™ใน:…/Gฒจ1,„ิŠr[o็šหทก* ณ ‹ใWฟE<•พ Ÿๅ๕xธjวVถฌ_KW[+Aฟy'6รดศ‹ฬฮ/r๔ไฯ:Bฉฌฝๆ๗ตu3๏น๋6Bู|žฏ๐!Lหฌqูฐบ๋v_^ฉ(*–^ถM๑‚โ8~ยม^Oeื<—\‘๏บab˜fต"*‹ฆฟ2ฏห4MBมญMMx=*%Mgj6V๓Rฆi๒ท_†R@pBH ๕!ค๚›C‡=่ ๙)&฿œไห/Žพ๊๋vwGูณบญš|ี$0l‡ฌf0žฬฑ&ฮ##sUL๕DูM้ฉV|dhšƒsษบฝ‡—ฬ๏^ฝ‰&ŸJบค3•) Y6๎ื˜ีโ8๖T๒ฅŠฟ๊FYสSฑ+;(žJๅNdqh๚.ศy .ฆน{cฯYYe๛ฆใoบ9Ÿ*้œ\L !ต‚ผ๛ฮ[นvืTEan1ฮฺทek๙ูฝm36ฌฃญฅ™€ฯ‡ๅฎฬำ$—ฯ39ใศะ๛;ฏฐ๋ห6oไฝw฿N8$[ศ๓=Œn่u;.ซzนแสxU•Bฑฤ๔ERŽใ๒๛ ‡‚xTทห\QKญy%M#อฝbEิน˜ฆI$ขน1‚ฯใAำ &f็จ๕็0๘Ÿ_๙ฆR@pBH ๕!คึGร๛ถั๒Q4L๕่_;4๖š_ฟป;สต}mln๕{๑œ!ฆršมd:ฯฉ8ฬ’ฟbชฏ1ศŸธ๎p€’i๑รใSOีํ=ไuป๘ํซ6า่SI•tฆ3• ฉื†lู!BƒWลงธ๑*๒i1eูไ4ƒฉL‘กxวจ฿ณข็qd>ล=[V•U๖ยlโM7็ำeก!คV’wvื_ฑช‹'๘ื•นล•‘™ญอM์ฺบ™อkhmnย๏๓โvนซU6™\ŽษูŽ๒โเะ๚ฌํื๓ท฿I8$W(๐ญŸœRน\ทใฒบป‹›ฎพฏง"คfๆ/|ๆRภ็#ฒ$ขฮฉˆา ƒRนL:›C7ฬืตƒกeY„‚Z๐zฝ่†ฮฤฬv?ฯhบฮ๚๊ท„‚sBJ จ!ตฉ5ยŸ\ฟ•๖ผn๒อรใ|๓ศฉื>;:šุณฆ-ญ Dณ*ฆršมtฆภณ“‹<6:Gบ|แช^ฎโ๋ฤbฆn๏ก€๊ๆWl มง’.WŸi;œ๏fVฆๅเW]D^|Š …๊’‘$ รฒษkณน"ร๑y ู๏YWo„}3q>ฐ}อrVูNLq8–zำอ๙lูเ๘BJฉไท์aฯUป๐ช*๓‰$๔/฿yรํam-์บ… k๚hmnฤ็๑โrนฐmอะษไ๒œšže฿แc]‘๓ุบกŸผใ."ม๙bo?๔(…bฑnวฅงฃ[ฏฝ ŸวKกTษบฟ๐$$~แ`UQP7ฒ์ยq์ำ"JำHฅณๆ๋QKX–Mะ๏ฃฅz/ิ‹*—5๋฿BJ ฮ!„”@ ิ‡hkเฏ฿J[ะKN3๙๚ก1พslโบฺนym›[hYSฒ„น\…Sเ๙ฉ8OŒอ/j+~>ขไ†ญt†}t“o=ลH"Wท๗Pุฃ๐๑+ึำเUษ”*]ถใผแ์`ำr๐ธeZ^ชีUSฎ๊X “ูl‘รฑcษํA฿ @ๅฤซŸBj%น๛ฆ๋—+q)>อ๏25;ฏ๗๊๋๎d๗ึ-๔๗๕ะาุˆวฃ"K2ถcฃ้:ฉLŽัษ)=ฮะุฉ=-๋ึ๒มwEC8LพXไป?F6Ÿฏq้lkๅŽ๋ฎม็๕R(Uvู[ั‡ $‚Uล๏๕เQ=ธ\2ถ] +ื “RนL2“ล4ญ๓QKุี๚–ไรฮ@‘ IDATคฆ๋Lฮลฐํฺ/–Jใฟ|G)@ 8๗wˆR@PBj{G๖ฺ-ดฝไ4ƒฏใ๛ƒ“o๘}ฺธym'[ฺNWLน$0m‡œn0•.ฐ&มฃฃsฤ +ืถฒนตwภrลื7s*Uฟ}>•ณk=ฏBบคs*ฝฒ็bZช[ฆู๏! ธ๑ธ]x2ฒ$a;Eรb.Wไh,อ๑ล ก๓SŽฮ๒;WozำTฎฝyเXLฉ•ไฎ=ืrห[ฎฤ็๑ฐ˜L๓ฯ฿๚งff_ื{lXำวฮMฌํํก1ยฃž!ข4ลTŠ‘SS์;rŒSำณไ<6๕ฏแื๙Vรa ฅ"฿๙คฒูบ—ถๆf๎บ๑Z^ลR‰ฉุส์J'ก`ชโ๕จxT—\5ฯ0ะชญyฉl๎ ‹จ%วม๋Qi‹6/ ฉฉนV ฉ|ฑศgฟ๑]!คเ฿%BH A}ฉห;›๙ิต›i xษj_|a„Ÿ˜^ฑ๗hkเ†ีํlmoค5เลซธ‘ซb*ฏLgŠผ0“เกแ’+P1ตตฝ‘?บn`นโ๋k‡F™ฮิo[LKภหGv๖๖(คซไำrpษั€ฟโฎไL!ฆJ†ลbกฬฑ…4'24๛=ฏKLth†?ผnหYYeร‰์›nฮt“ฃฑคR+ศํื]อํีJœx*ลพ}ฦฆf^ำkทฌ[ห๎m[่๋๎$ โUU$Iฦฒ-Jๅ2 ‰Ccงุwไณ๓vืวk๚๘ะ=oฃ1กP*๑ฃวž$žช฿ถีๆ†๎พ๙>ลr‰ฉน7&คdI"๐ใ๕x๐จj5ฐUฉˆชŠจbนL*“ลฒ์Qห8ชขะฺR 5ื˜ŠอcYต-คr๙Ÿ๛ึ๗„‚sBJ จ!ตป;ส'ฏูL4เ!S6๘็รlxfล?gcK„›ึvฐตฝ‘ถช˜rU3ฆ zฅ=l฿tœGFgYศŸลิŽŽ&ํu[h T*พพ๔ย(ฑ|ฉn๏ก๖]ถ–G![6Kๆ*%ำreh๖yจ >ล…Oqแ’+ญ2%ำ"YิZฬpt>Eฤซพช˜า-›‡Gf^’U6^ว•kฏDั092'„ิJrห[ฎไฮ‚฿๋#‘N๓เฟ€‘‰ฉ_๙šห6od็ภ&z;;ˆ„‚จŠ‚$I˜–IฑTf!‘dpdŒGW|วพWb๊U|๘]wำ‰P,—๘๑ใO]ดฯพDB!y๋~Jๅ2“็ูF้’e~^งRฅจธ.,หฎŠ(bน’eู+,ขฮภํrัีึ‚ืใฅฌkฬฤ0-ซฆว “ห๑๙o@)@ 8!ค€๚RW๕ถ๐๛Woขษ๏!]ึ๙“<6:wม>oC4ยอ ด5าฌˆ)ท\ ิ^ส-:Pmๅ›อพสฆ]]อม[ถ, ถ/&qฒช.]a?ุฑ–ว]Rฉ‹—‡%KŠ_uแuป๐)nWeW+อดHuFYาxฎWSษ’ฦ๓S‹ั๕ด}ไ4“9<ฦdบ๐ฆ›๓%รโ๐\Bฉไฦซv๓ึฏ#เ๓‘ฬd๘โw~ศษ๑—ๆ)Š›[ท0ฐพŸUํ„‚ท€i™J%ๆa๏แฃd๓๗[ปช‡๛vš(•หไฟ$ถBป^ ~?๗q3A€RนฬTlวถyญw.Y&่๗แ๑xชUQ .น,ฏ:บaP,iค2,น`"j๙x\2mmx=สบฦ์"†iึ๔ค2Y๙;?BJ ฮA)@  >„ิต}m๖Ui๒ฉคK:๐ žŸฟเŸ฿ๆ–ถต7ั๔โWธd หถ)่&3U1๕๘ุ๋jนปชท…฿ปzอUม๖O{O’ีŒบฝ‡zผo๛‚ช›LYg,•ฟRฏHุฃโฏVK๙ซb @3mาeแx–ัdY‚ฮฌืNe _ฬœ•U๖ีƒcฬd‹oบ9ฏ™g…ZIฎ฿}9oฟๅ>?ฉL†/}๏วœ_wŸืร•ท2ฐพŸฮถ‚~?JU^ฆEพXdf~c'Gy๎เสฺฅิkzบ๘่}๏ ฺุ@Iำ๘ูSฯ2›ฏq๑z<ผ็ฎ”ด23ฑ ำD~•]9]ฒL0เฏfDUDิRž—ahzฅ5/ษ]ะŠจ—;ฎฎ๖V|ี ฉน๙E๔R‰t†ฟ๛#!คเ„๊CHฐบO\นFŸJฒค๓๗ฯ็้‰…‹๖๙kšBผถƒMด…|๘ืrnั’˜:8—ไแแูืT1u]_ฟu†`๛ว็‡(fCkšBผgk~ลMVซTHI—่XBžJ_@qใW(ี‡OรถษT3ฎFYlฺƒ>Ž/f˜ษ๘รkทœ•U๖FZ3kฒyq&.„ิ ๒–;–[ราู,_๙O86-ขสšNYืษๅ X–ลJ๔ur–า4ๆใ่Fm1c1™ไK฿ฉR@pBH ๕!คn^มวwฏงมง’,jณวynr๑ขG_c[๚;ูHGุฟ,ฆ,กh˜ฤr%^˜M๒๓‘Yฆ3ฏjณgM;ฟyลiม๖ฟž=ŽQใมดฟŠuอa๎X…_q“ั N]เ ฉื‚e;= ^Ÿโฦใ–QซS†e“ำMฆ3N,fศ”uEผfœีJ๙ฯ†W$ฤพึ0,›„ZQฎฺฑ•{ซญa™\Ž?ก`€อkhmnZQŽใ ™\Žษู๛Žใะ๑“5s=ํ|{hijคฌ้<๚์^NMฯิํธศ’ฬ๛฿q'‘`ˆ’Vfn!Nฉ\ฦํv/ŒiZธd™†Hฟื‹ช*จสูญyeญ๒_พXผค™Mฒ$ัำัถœ![Œฃ้ต-คๆใ พ๒ร‡„‚sBJ จ!uบNอฎ๕Dผ ‰ขฦgžd฿๔ฅห5้k rำšvt6ั๖Ÿำสg1Ÿ/qp.ษฃ#ณ/Š}K'ฟพ{ Š`๛gŽcื๑๏ค-๎ู‹Oq“ีtฦ’๙‹]8๐Š˜–ƒ_u๕{๑).ฒณŸฐGaฑPๆožไ…™ฤ%?ฎU AnZมๅMด‡|T7.Y>ซb๊ะ\’วF็Mž๚พ}}นŽˆW!^ะ๘g๋๚ฺาฺภ7๗โsปศhใษ\อฉ%Lหมใ–i x๑ซnTWEL™ –ี ข~^ท‹ิ› •๒•ฐ‡S‹BHญ w\ wํนUQ‡สwL ฑัtT&หศฤŽูฐ๓Zกณต…฿x๏ฝดE›ะtƒ_์=ภ๐ฉ‰บำฒ๙ะ;฿Jc$BกT$ถ P*ก(nB!|^>ฏUQ‘$ฉ* 4]งฌiไ ElปvชWeIขปฝ ŸืKYืYˆ'(iต]ล9=7ฯ7zD)@ 8!คธ้Ÿ~ภe๓’LคV๑๎M=|่ฒต„ชB๊ฟ?uŒƒsตณygศฯ-๋:ุูฅ3์[ฎ˜ฒ(&sน‡cIฉˆฉทn์ๆร—Ÿlใ—วpฟJศn-ณตฝ‘ป7๖เuปศh:ใ—(ิต= :จn™fฟ‡€โฦใvแqหศ’„ใ€,’Dูฐ๘๚ก1ฮ% y”7ีœท‡}BHญื๔ฑs`[ึญฅฉ!‚T5ฑถmS,—‰งา Oฒ๏ศ1&fj?‹ฉ-ฺฬ'wํ-อhบมS๛_dhlผnวG7L>ฎปiŠD(–KLฬฤdhŽD–CหeI^ฎ`+k:Z5#ชซVฯRšฎฑORฌa!U*k<ฝะ??ง>๐@Z|ใ‚ำ!%U๖<๘Dƒา?#K|ธ๏ž-ฝผ๛ZB7๓๙2฿SG9Kีร\ะวํ๋;ูััLwฤO`YL9” ‹๙|™รฑ$–ํpบ.B7 ี๓๑\ค]š.;:šธkC๗i!UC-{ฏ„i9ธd‰hภƒฟ*ฆ–ฦ ภq e๖Mวู? YาTb๊๙ษ!ค[ึญๅŠm[XีIC(Tg;‹ษ๛c‘Af๋ๆผZ››๘อ๗Ggk0๘ๅƒซq*i:ฝ๗ํD0-ซRๅvใU=gดๆ้”สšฎ“/–jช"๊\ฮnูำYH&)–joใ…RYc๘ิฤใ?๕์ว๗_?pJ|ห‚—"„”@ œรž๊s[๒ต&ฆฝต๛ทญ&จบ‰ๅK?ฟ8สเBํฑต#ไใฆต์์jฆ; xF+_ษ0ั-›GA‘%ๆ๒%฿'โWu{฿์์jๆŽ๕]x\.2ๅj…”TวnZH๖(Dผ*ํA๏้*—ชHL5†โž›\dฑP~Sˆ)!คฮใ‹ฃ—mศฮอ๔tด QI’ฐl Yชd“้†ฮOž๘%=๙Lcscฟ๕wำีึ‚n˜<๛โ!Žžฉห๑*หtถต๐๎;oล๋๑Tฏƒ$I˜ฆEYื—eTกXฌ‹?‰Jจนฯ๋E3t) ฅRอŸQ@๐:ึt!คเๅฉ51๕ํซy๗@ีอ\ฎฤ_โC‹™šฟŽํ!7ฎigww ]a?Aีโ’+๙2U้QิM>ปwˆSฉ|ŠŽQn_ื‰๊ชŸ ฉs1ญŠ,ผขงฏโยqlวม%WฦK3-Eัd–}ำqฆา‚u,ฆ„zํ(Š›+ถ 0ฐ~-ฝํ„‚A”๊.mฆeR(•ศๅ‹D๐z<JE~๐ศ/xr฿ uw_4Fยฮ฿Cgk+†i๒มรฎซs(ห๘>ถm่gsZšฯjฅ,”JhบAYำศJ8ิฯ๓ภi!ๅAำ โฉ4๙b๑’Wฉฌ18:ถ๗—ฯ์ฝ_ˆ(@ xkบR@๐ซนํมŸ๏ภv>p)ใƒ;ึ๒ฎ-•]ๆrEหGId๋ๆ:Fn๎๏ไสž(a?zVkุlฎฤ™ฯO-’ำŒบSW๕ดpKŠหEถFCอ_ ฆํฐ>&์Q(๊&ฑ|‰ฏZฉfsU2พtห&UาId9K1žศแQ๊ฏRฉWว็๕pีŽm ฌ_Kgk ฟฅฺZk˜๙B้๙Ž%™ษ๐ทAS$BกTโว?ลใฯํซป๛" ๒;ฟv?mm˜–ษCG9x|จ.ŽฝP, Xฟ–U=4FยxชปๆIReญMฆ3,&ST3็๋๏แ่้hฏ)ร ‘สห็นT nฉฌqth๘่“/๚=Z.ฏsMBJ ^ท|ก=ฒ,?ภ%Sนผyท™l‘๒ฤaฦฮุตฎn๖ผ wฎ๏ๆญปi TZรภฒสฆลbกฬั๙๛งค๊(ณ่-ซZนqMŠK&[g-{gโ8ะ฿"ไQXศ—y|,FkะKณ฿CGศGฤซขTร็ &[68•ฮs$–โd๑4<๓|อP ภ๏~่~zฺ1-“Gyแุ๑š>ๆBฑL8`†uฌํํ!VE”„eูศฒ„$ษ˜–ษ‹ƒ'P ^Zทฟ{ซBJ7L้4™\~น์b!D”@ ผq„‚ืษฅSตnyท้Lฟ|0้|^ว฿ฝzwฌ๏Bqษุvฅ5ฬ-KX”M‹DฑฬเB%ณจฤิu}mฐบฝ"ค๊ดe*bp}4BศSษ*{dx–ๆ0ฒ,aชหEgฤGฃืƒวฝ$ฆršมtฆภมน$'38Tย‡k!ค^J[ด‰][ทฐน ญอ๘ฝๅ8บก“ษๅ™œฑ๗๐QŸ8ปmMOฝ๏D)•ห์ฉg๘ูSฯึ๘|‡฿KoGฆeqเ่ Žึไฑ.‰จ›6ฐบป‹†pช,หงBฉD2•กฉ1B8@7 NŽO`;ตŽ…Tg;>OEH%3า™’|qึ›RYใภเ‰…็ฝ_ˆ(@ xc!%็ษm๓ุŽ๓€,ฑ๊b|o\ฑž;ืWvq›ฬ๘‹ว2)ึํ๕๛ฤ•–Cภำe๙|‰ถ oน5ฬฎVLล‹eN,fxfขถลิ ซน~unนพ…”ใภบhธžŸ+๑ศ่,ข‘ๅv=ำr(š&>ท›ฎฐ&ฟฏU Iถlrบมlถฤ ณq^œญ์ฆXซc&„ิiบฺZูฝm Vฏขฅน ŸืƒKฎฬCอะษd๓ŒOฯฐ๏๐1_aวนพฎN>๖๎wาาิ@Iำxไ้็๙ษฟฌป9เ๓z๘ฝฎ,หๆลม์;|ดฆŽฑP,ำ 1ฐพŸ5ฝ4†CจŠŠ$iVvา‹-ฦ9x$#S|๘]w/‡ดNNašชZฟ๙oง…”A*›#™ฮ _เ๊Lร0yศฑ…}ษ็๊ฯ฿‚เ#„”@ ผA.–˜๚ญ+7r๛๚N<.้<๙ัƒฬๅJu{~๛ชห!เงาy๛SGูาึศ5ฝญ๔4yTนาฮW6-โใ i๖Nวkr—ทืดsm_nYชfHีง’‘XยฏTย๓›cSK๙œ๊ำrศ๋ช[ฆ' ู๏ล๋vแ’ภr บษLถศแน{ง1kPL !kzปู5ฐ™พข x<*ฒ$c;6šฎ“Lg™˜ไ…c'89>๑+฿ซงฃ฿-M”5GŸห{ฒ๎ๆ€GU๘ฟŸพ๎Nlๆะ๑“wัึDYืyโน|‘'๊oธ]มG>ภ๊ž.lๆ๐‰až}๑ะ%=ฆ%5ฐพŸพ๎."กภฒˆฒ,‹|ฉศิ<รใ“Lฬฮ.๏€P,kึ–3ฑ&g็(k:๎3~ฆฎ^่๎hล็๑bZ&้lŽลd—kๅ…”ฆ้ฦไ\์มท฿|รoˆo9@pึt!ค`ๅุ๓เ ฒญหๆ$™ศJพ๗'ฏูฬMk+กูใษŸ~ไEEญnฏีงฎยžjๆาh2หONฬ0ะvZ|ฬๅKธ$่oณถ)Dศซขศาฒ˜Ju†โ๖N/2—ฝ๔b๊ถu\ีSR9อ`ฌN+คT—L_ch9<™ษึGรฏ๚:ำrˆหธd‰พ† ํ!?ี…K’ฐ‡ฒaฑXฌTนํ›Ž“(^๚๖ห…ิ–ukนb๛ซบ:hฮฒ,‹’Vf!‘โฤ่8๛ 2ปฐ๘บปฃ%สoผ๏^ฺฃอhบม“{๐‡ซป9 ห2Ÿ๚่Xำc;99ฬำ^’c)ห47Fุฑiซบ:+Q’$aš&๙b‘™๙Gฦ˜Ž-,๏€x&ลR™w฿uซ:+™X3ฑy ฅR] ฉฎ๖^฿B*ตบฟhšnœšž๛ฮ๗žyโ>๐@Z|ป‚ ดฆ !%+ฯ…Sxํ–ๅะ์ัd–?{๘Eาeฝnฏั_7ภuีฬฅแx–Ÿ ฯฐๅe*qb๙Ž[#ฌn ๖ชจ.วqะL‹dI็d<ห3 ฬ็/˜บc}W๔ดเ’ [6๊v—=หE_cp9<L‚ีMมื๚%1e;kšBt†7๎3rมE“๑ ฯMลYธ„c๖‹’$‰หทlไ๒-›่ํl?Cj€iU๒†)Ž ฒ๏ศ ๑d๊ผ>ง-ฺฤoพ๏>:Zข่†มS๛^ไ=R—๋ำง>๖A๚{{p‡ฃรฃr ๕๓ ล2ญอMlะฯชฎ"ก Šป2f†i’/™]Xไ่ษfb‹จ๊+หฅ|๑g๏พใใ:๋DN™>าŒzณ%Y๎*.)NO์!$ค„ะbฒ–ฅ„ฝห.q~„ป๗ {—ป\n–5,BIHœุ๊Ž‹mYฝKฃ้ํฬœrI‰Yž‘ž๗?๐bญ™93ฃัœฯ>ฯ๗คธ๏ึ[h˜ฺ‚8<>A<‘œี€3ง๏g$j*ห๑บ่†A(%š %B” ยฆ‹ %‚pแฬf˜zsภyไ้}ฤดlม>7sCื4Tขศ'&ข<}j๘๗ฉiรฑ†eาZUBฃ฿‹ฯiห…)@ำM‚)“(ป'Š$็‚ผ Q]Q†ืใฦ4M&Cกะyญ๘Jฅ5:{๛ž๛๕žw‹%‚0‡Ÿ้"H ‚ \xท?ูจrป,๑เนฦงnhใฺฉ€s2ๅoณTV/ุ็ไ๏6ญ™ูโv|"ยoปFhฎ๐ัŸŽฅฐ,‹U>–”z๑9ํุฆNฌ2†I(ฅq|"ย‘ }แฤœEŽทฏZฬฅueH@8ก?œ(ศR^ปE>๗ฬ๐cใjŠ]็u›๑4‰ฌAฃ฿Cๆ‚MฟfแT†ฮษ(‡GCtc8ินYน1_ƒ”้ไŠumดฎXFme9ท{f+WV7ˆ' ŽŽsธณ‹‡Hkณณาฒิ๏ใ#๏น—ฺส๐์Wไป?ฒ ?Ÿ>เฌ\าˆ…ล๑ฎ^v์ฺsA๏/ฅiิTTะผฌijt<”ฆVD%่ฅณท‘1gq…ผh<มฝท2ณq<$n’$*หJ)๖zฮ;HM‡จ็^๙ะWm๏฿VAๆ๘3])A„นs>a๊ำืpU๋็oŸ‹f˜๛\|ๆฦต3[ŽŒ…yพgŒีgพˆl8–ฤด`YY+ส‹๑อlๅ› SiS๛†๔…ธm6Lฑz1๋ksA*˜ส0Mไ๋R์ฐQW์žž2กบศ5+ท=Kก้&ีล.šJN‰Yำ$šฮาŽsp4Dg ‚rO˜็[*).ๆฒ5อดญXFUy— UUฐ,ศ๊Yข๑รฃt?ษCGั cV๏฿_TฤGw‹ชชะ ]‡๙๖OUฟ{ปXูิภ‰๎>ž{u๗นŸTZฃบขœถ•หY\]I‘ืsฺึผh<มภศ(GO๕04:†ห้8๋๛ˆฤณ๕&–7ิca† EฃH…XฬษฉŠ?พโ",ำ" 3 6ศLžwขA๒เ3])A„นทq๛“6SzLBzว™ฬ#›ึrE}.เ๐7Oพ†n๎gx๛M๋ธlQ9ph,ฤห}ใฌ*?๛]ƒั†™[1ตฌฌ˜—ดญ|แt†๎`Œ]๔Gx.P˜บณนžต5ฅL&5Fbษ‚|]N;5E๎™แ๙]ม•^็ฌ‡ฆ›คu"ปZŸ‹ง‡*#ำ"ฆeŠ$80โD ‚eYศเไyพฉช๒2.okf๕ฒ&*หJp;](Š‚eYdฒ"ฑ8}C#์9x„ƒ':/ุฑy<|๔๗ฯ\อํตCG๙ๆO~Qฟพ๛Yฝt '{๛๘ํ+ปf๕๖Sišส ฺV.cQuE๖ฉฯฆLV'30:NวฑŒOฯ)DM‹ล“ผใ–3+พ‚แมHด †–—๘)).ฦฒ,&Ba&‚มฉซ๑็๐‰ฮร/ํ=๔พฏ}แำA.*คA.ข›rฃ,หํภ ์฿~v*เศภ‘๑0๋ื ๚ุแ–๕3+Š:FC์œ`Yi๑9฿`4A:kฐฆฆ”ฆา"J\ถI)ั IDATvSยดฉmaมป'่ ฯ~˜บปฅ5ี%X@ ‘f4ž*ศืฅิๅ ส๋šž฿JPแq\๛า ‹DVวฅ*,๒น)u;pชJ๎ b†I,“e8šb๐$๛†ƒฆ9ซณม =H-ชฎไ๒5ญฌXา@Ei .งEฮ ืฒยั=Cผv่(GOu_๐c๓ธ\|๔๏šนšพ#วุŸ?+ศ฿ƒผ็>š—5!I}<๓๒ซณrป้L†ลีUฌljคพฆš"ฏUQ‹ฌฎ‹'่ๅHg7#ใ็ขฆล)nฟ้zV65"!ŠF „ {LRฉฏ˜2ฟ ‹‰`ˆ‰ษ๖ทุฦ8ข^ุื๑ฑว?ศA„ผ ‚” B8“0๕น›ืฯฬ(:4โo~ณท ๙ ›/a]M)p`$ศแ KJผ็}ปƒัรคนาฯฒฒbS[๙$ ฒFnลTg JวHn^‘ห6;๓Š๎im ญชงง r†T™;คฆ‡็F”น๔>uร"žษbWd๛<”yœ8UEรฒHdt†ฃ):Fƒ์ 5f'LjZZฟˆKšYึฐ˜rฟ‡รŽ,ษ˜–‰–ษ G9ีืฯรว่์ํŸณcs:|มhจซม0L=ฮื๔ำ‚|๚๐ป฿I๋๒eH’DWOฟ*็๓9“ัY\› Q‹ชซ๐ž6ืKŸYลvฌซ‡ั‰ภฌ„จi‰dš[7^“ lHDb1ฦฯ๑JŠ๙ขคธˆ๒’’?คDˆAศo"H ‚ ไ‘›r#ฒ˜ k฿{ใŠข#A๎ฉ}}ฌnน”ถฉE{‡&9:ฆฏๆ๖๛ Fhบษส +ห‹)q9ฐ+ฏฯ+Šค3tใž<๏Aฺ’$qokอ•~L`4šd"ฉไU๖*ฤas*•ึุ{๔๘๘ž‡>๕ต/|fป๘v!‚ŸDAศC›ฟ๔6ำฒฺe‰†้ํ+Š๖O๒™ง๗์๑ษ’ฤฃ[/ฅe*เผ6 3ฅฎุ=๋๗5Iึ VU๘XYแฃิ•›WนS‘t–pœืtŸc˜R$‰wถ5า\้รฐ`8’d2™F.ภ"UๅuQ๎vL ฯ2‘Hใsฺๆ๔1่†E ™F–$–”xฉ.rใฑ+(’„aYคณคฦั๑\˜šLj็ฆ %HตฎXส†5ญ4ิีโ+๒โฐ$ร0HฆำLL9ึหk‡Ž02ธh๏E‘yx{fฎๆv๐D'_๛ไgิ๏ป‹ตซW ห2=C<๒ซg1>ซิUUะฒ๙๗ฒด~1–eqธ๓_ฮ ๒3๊ก{๏d}๓JdYฆop˜ง_EVฯžม{ึ พฆ†•M ิUWโuนงฎt8ข๔ s่ฤIม ขฆi™,7lธt&ฐ%’)†ฦฦ :HนNj++ค\'Oค=้ฟเ๛I|{A( "H ‚ €-ฬถ/mนไฑ–*ฟozEั็~[ธrจ _r)ซ*Š1L‹W๚'‰&ฉ๐\๘“ณH‚xFงตสฯŠrฅn;EA–ฆฎ๐–ฮะŠำ1ไิdU–ฯเxd๎iidๅิ๑๔…„ำิ RPWไฆฤํ@ŽŽ‡‰jYงยT4ฅ/œ Šส๏ Š๙คJ>.kkฆmล2*หK๑8]S[ผ^z=02Fวฑผv๘(†aๆ๕{่c๏+›8ัว๚ๆw ๒s๖}wฦๅkZP•ัQ~๛๒.’้ำƒิโ๊jV-[BuE— U™ž•!‰า30Dว๑“Dc‰‹ขฆ้†ษeญซูฐถUQIฆำ ŽŽ…คRi Y’[๓๒%_ดl"D ‚ 0คA ิฦํ;ฒ™yX…ฯฺc/u;๘ฏ7ฏงฉดˆฌa๒\๗šnโฝˆ[ร" &“kชKXUแฃย๋ฤ95c*k˜ฤด,‘๛†'้šŒ๖ณ^ปสญ ,--&k˜tNFIft์ja)รดh,ษลศ]อศ๋ญ‡šnึ Š์vj‹]”L ญ—ศmมŒkY# :ฆVบฆ…</fชฎ(ใฒถV/]BeY)nงsj‹—I&›โี?<ย๎ƒ‡9tโTมผ‡ฝ๗ณzู$$N๖๖๑ๅํ฿)ศฯื๗q+ึถaSUวฦ๘ํ+ปI$“duƒe ‹YฑคแดQ–e’ฮdˆLmอ๔๑D๒ข†จ7^ฏ[ฝ‚+ืญมnSIฆา `Jฅ5:{๛ž{๎ล}๕ั๖^๑-@ก๐‰ %‚Pเ6nฒQ5ไvYโมByฬ'Ÿปy=KJผd ƒgN`ZnลŸU4I0‘Lณถบtj+Ÿ—ช ห๚T˜๊$่ qd<„M–๑9lีาภ’า"ฒ†ม๑‰i8ง+๖]์ืฦ/~ง}ๆjŽฒ$ฤpvฐHdu\ชBฯM™;ทาm๚u‹gt†ขIŒLฒo(ˆหฆ\” ี/_xีšึ็–/i ฒฌงร"็†ดk™ แXŒž!๖:สฑS๗y๔g๏น—–eK‘$‰S}<ถโWอn฿ส•๋ึ`SU†วว๙Ÿ’ีห–ฐz้jซ*p9(rnF”–อŽฤ8ีืฯก“]ฤโ‰ผQำ, ZV,ๅšKึbทูHคา ŽŽฬk!B” ย%‚” ยHM‡จ๖u|์๑ฯ?ฒAaAJažบ๙๑'7สฒN†ฉ†/lZรขb)เว(u;๒zขษ@$มh>u}ีE.โŸ๎ฃถุ]ฯ็@$มH,ลวฏ^ืa˜Yy`˜i •5Hfuยฉ &๙๛wื˜š!ๅŸ Rป&fŽiพyฅoœ฿ž๔“๗ดc.๏๗ƒ|~ฃ๓6Hฝ๏ฮธ|M ชข28:ฦฟว๗ˆฦy๗8ซ+สธr].D••๘q9_ฟฺaZำศ๊:ท EV˜๙ทืํ*ุืฅบผœญ7\ƒวๅ"•ฮอบAJำ2ู๗๘ฟ{๐?…AคA€›ํฉ^Y’ฺŸz่–ํ ํุo๙๚Scา.ษ๘ๆ๊>ืึ”๒WืตPแqำฒ๐P/ ~oม>‡?;>ภ฿ะFตืE2ซ๓b๏อ•~$ NปŠ*K่ๆt˜า๓2L™ฆEcฉฟำAึ0ุ5 ุ9?WHํ๐รC="Hอฒwฝ} Wญ_‹ฆ246มฟ~๛y1+ซถช‚+ืญaๅ’*JKp:ศฒฤ๔ีก0งz8ูว่D€ตซWฒ๕บซq9B!?†้(ุืฅขด”6]‹วๅ&•N346Žašsvš–ษ๖Ž๘‰Wv|x{{{X|๋A@)A6) ภด่[ˆajใ๖~ูฬ<ฌ˜<<a๊ฒบ2>qM3'Q-ห๖ฐคคจ`Ÿฟ_žไฏฏoู‚ธg0€SUฐ+2ฅn^ปŠfรe“งฏ๎6ต•O'‘ั™ศ“0eYะXโล๏ด“1 ^ํŸภ็ฒฯห๗กIพ฿ั-‚ิ,ป๏m›นๆาตุm6†ว|๕;?d"บhgqMึถฑrIๅ%~;ฒ$cš&)Mc"ขซ€๎!2ู “แ-ห–r๋ฦkp;]รaถ๘็8์…gK}>nฟ้zผn)-อะ่)ขA„ท"‚” ฏฉi&t`šฯ๕ษ๊ล6Wa๊Šล|๊ี”น„ำพฐ—eฅ…ค~}r่ด-ˆGฦr'เN›€,I”ธ์ธT—Mมฉ*(ฒ„iYคu“tึ žษHค1/b˜zcา ƒ”ฬำ u`$ศw๖w‰ 5ห๎ูz3ื]ถ‡ฦ่ฤ$_๎ Lฮ๙ใX\Sอ•๋s!ชิ๏รaทฃศ2†i’JkŒ&950H๏ภ๐LˆšŠฤXฑค6]‡วๅ"‰๐ปญpทฏ๚ŠผผใๆMy<ค5กฑqtรธ`๗—Jkt๖๖=๗๋=;๏!JA๘CDAเwƒิyM ๅQ-K_(NZ7ฐ‘ฒ$แsุqU\๊t˜’0-ะtƒิ‡ฉ7ฉ}ใ”yๆg:6แ฿_;)‚ิ,{๛ฆ๋ธ้๊+p:์LC<ƒŸะ?นœN๎|#โbาšฦศD€L6{ท›Jk>ัy๘…}{๓์@Aฮ‚R‚ œyšfZ|CWฬ๖…ฆ6ozฆ๕pร๙ฮ–uOƒิษ@”วwŸAj–zร5rํ•ธก0๖ร'่ž๕๛YXฯ†5-,kจว๏+š Qฆi’Lงะ?HฯภฆuvรปำZ†_1๗ฝํผn‘xŒ๏์I ำ(ุืล้pp๗–›().&ญฅ L’ึ2Hาน}–ˆ%‚ ฬคA8๛ ๕†๘ฆn~ษฒ,ทsŽa๊ถU‹x๐’e;lL$า|`oAฉ—๚ฦ๘ุUซ)า>Iๆ‚ิYn๑™S.›‚ฆโถฉSรฯsaJำ ™, ฌaฮz˜2-h*๕โsุIfu^้งยใœ—๏แฎ`Œ๓๊qคf๛ณ๔ฺ+ูz5ธœN&รaG?Z4;–7ึsๅบ6š๊แ/.ยiท#I2†aHฅpขงแัณQำ2Yฏอo฿LฑวK4็{ฟ๘ Y=[ฐฏ‹f็žญ7Q๊๓‘าrณด’ฉฒ|vsฑDˆAf“R‚ œ{ฐL"†ฬcฆllวถ ๊jB็ฆั\ฯ{ื5Qไฐ1O๓ƒC…คvLœ6ค} ’ c˜(็8sFFขศaรm=LฉŠŒiZh†IF7Hduฦใ้Y SฆKKs+คโW๚ฦฉ๔ฮฯ ีŠ๓ฟwAj–tีถ้ZNมp˜ํ?9ฝ็}ป+–4pลฺVš๊QR\ŒรnC’dtC'‘J161ษฑฎFฦ8฿ญu†aโฐyเ๖ญ{ฝDq~๘ซงIkZมพ.6ีฦ=[oขฬ๏'ญiŒƒฤ)”3ิžJk์=z||ฯCŸ๚ฺ>ณ]|kAfƒR‚ œ_šถ ริฟ=u'๐˜,ัp&žึX„ืฎ2O๑ฃCฝฌฎ๐์๑๏ ฬ iงณ๔‡ใ่ฆล๙ฮ@–ฆย”วฎL]™Oล6ฆfVLes3ฆ2๚๙‡)ำ„ฅeE๘œ6bšฮ+cTy]๓๒=N๐/ฏAj–mผโ2~ใ๕3Wง๛ฦO~ม‰๎sพฝ–ๅKนคeK๋Sโ+ยnณาi+ขŽw๗า;8|ฦqๅ~–[ (2๏พใV|"b‰?z๒’ฉTมพ.ชขrฯึ›(/)!ฅฅ รฤ EyหŸ3 ƒ‡EˆA.คA˜ 5s2ณ€ริๆฏ?ฝอดฌ๖?ฆ๎_ณ„๛ฺ๑ุUFbน ี\YธAj๏๐$z๙ .;‘t†พpรดfiGe1uU>—}*Lษ–Yำœน*_ ‘F;0•[!5คฒผา?Aี<]!5I๒ฯ/Aj–]wูzqหF<.7กฉซำ;ี}ึทำบb—ถฎฆi๑"|E^์6ิU๓r!jhlœฮž~z††PHT9วฏศผ๗oรWTD<™เ?๓,๑Dข`_EVธg๋MT”–ึ2ŒMNO$QU๕Œฆeฒ๛Ž๛C๗๙๑-AAธDA`vƒิN๎๛dIj๊ก[ถ/ผ็๓ญริ{ึ5qOK.›สH,ษ๔๔ ฉ#Aไ๒ๅ๘v"้,ฝกุน—eAฑำ†KU๐8l3aสด k˜dŒฉ0•ิHgณ S–Hฐฤ๏ล๏ฒีฒ์ PๆžŸCอGข)้ฅร"Hอฒซ/Yห]›oฤ๋vŽF๙๖ฯ~ลแ“]g๓-ห—rลฺVีžขt žJ2<6ม๑ฎ^FGQd๙‚‡$ษผ๛๖ญ๘‹‹‰'“<๑๔sDbฑยย/Iณ๕fชสJIg2 ŽŒ‘ึ2ุlฟค4-“ํ๙๑ฏ์๘๐๖๖๖๕TAๆ๘๏“R‚ &HM[จajใ๖~ูฬ<ฌ˜<,ษœ6 ๊มK–๑Žๆz\ชยP4ษOŽ๖ั\ภA๊เXhๆช‘t–žะ…=qต€"ป ทMมcWqmุงร”™ส—ฬL$าgฆLำB–%^J\นฐvp4H‘ร6/฿ŸcฑใEคf†ตญ{๋อง]ฎใ๘ษ?๚sญ+–ฒamu5๘ŠŠขtโษ$รใ้์bhlญˆzำd$ธใVJŠ‹Iค’์™็ F"๛บศฒฬ]›oคบผ -“ฅgpˆlVวn๗[„(Aaฎ‰ %‚ภ… R3'"Lอ„ฉ‡.[ฮํซใT# ~zl  ‡šฯ\50šฮา𛕖^ป:ตZJมcทaWd,๋๕Sgฆtำยฎศ,๖yฆfae8>มฉ*๓๒}9‘H๓ฯAj–]ฺบš๛oB‘ว3suบGมฟพyPkย IDAT๋šWาดธ_‘›š $บกO$p๔T#cุm๊\~EๆทR๊๓‘Hฅ๘ลณ/… ๖uq:œผmใ5ิT”“ษf้์ภ0 v;ฉดFะ่๗EˆAๆšR‚ ฬMzƒ็MำlŸ๋แ‹ํa๊CWฎ๐ฝmๅ"ŠB$มฯŽ๖๔ ฉ๏[ฟ”ข9RำLำขศiรcSqูTผ๖๐s€Œa’1L™,“ษ ษŒ{รTึฐpช2u>ฯฬีปC1ไู„•g‚IGwAj–ญ[ฝ๒wฎN๗ฺกฃงY–ธคe5๋Vฏคกฎ†bฏw&6้†A,‘dptŒฝ aทซแH$x๛J~’้ฟฺ๑cษ‚}]Šฝ^nผjuUdฒY๖Qฐฏ‹ชจถ้:๊ช*ษ๊:ป:}ใป?yปQ‚ ยล$‚” -HM{Yz๘ฉmทXHฯy2ซ7ฺฅฝ7{๐ู๎Q–๘ฝ{,ฝแ8๗ฏY‚ืฎัฒtO^œ 5อ0-Š6ผSWไ๓ุีV>^_1•สๆ†Ÿ'ฆย”ฆจฒฬาฒ"N;มคฦ‘๑๐ผ!ีฒ|ทDšeญ+–๒w6uuบ$?y๊Yv๎๏`๊U\ฑฎ•EีUงญˆส๊:ัx‚กัqž่ddb—#้[๗ฟ}3ๅ%~RšฦS/๎dptฌ`_—ด–แทยโ๊๊็uC฿ๆฐ{ล_~AแbAJ‹ค0-พก+f๛Žm[ิ‰ย๑@ค๑ห/๛โๅue๏Z\ ซค" ๎mkฤmS‰jo…ิ›ฆ…วฎRๆvเRUœ6ิŠฉŒiข้&้ฌฮxB#šฮ ศ+ส}๘œ6&“{‡&ฉ๔:็ๅ๛.‘ั๙3๛Ešeซ—5๑พ;o›~๐x'.ง“๚ฺjŠ<l๊tˆสฮlอ;|ฒ‹‘๑ œ{ˆ๗ถ…ŠR?i-ร3ฏ์ขohธ0฿๋ษ4แh๔ล?}๗;พiQA!Oˆ %‚@~ฉi 5L๘“WV๘ฟti]ู†B Sรฑ$๗ด4เสณ 5m:L•ปธl 6Eฦฎผพ•/5H๋ฃฑ %^Š6&i^๊gI‰w^พ฿RYƒฯ>ฝOฉYถชฉ‘๗฿};ฅพb รDหdPUิp้QรนญyCใใ๙ฑ"๊๗ธ๗ึอT–•ึ2<๛๊z ๊ตH$ำ‚ก—รษไ#‘‚ BžAJ Rำraส๐ŽmิU 1L%Rนบ>oƒิดำVLูr๘loš1ๅRTYb<‘ๆฉฮaZช๓๒}ฆ้&ŸyjฏRณศfSy๛ฆ๋น๑ชหฑlไพbZXVnET4ž wp˜c]=ŒŒpปy|4๏z3Uๅฅค3ž฿ต—S}๑:$’iฦBกX"๙~ขA„|&‚” ๙ค,“ˆ!๓ุฒŠฒวพv๛ฅ"Lๅฉ@Rใ๖ี‹qฉ Q-Cw0N>_œN7-ผv•R—๗ิ|)ป"#H ้ฟ:9DฉำN‘sอ‘ส&๗คfƒfใ’ึี\ึฺLC]5E๏ฬ๛_ื ‚‘รฃt?ษฤdปถZpฯญ7S]^†–ษ๒ย๎ฝœ์ํห๋‡<ข๑ฤ฿ํ Ÿู.ฒ ‚ ๙N)A๒7HM[Yๆ‹|jSc5^ืcŠ,…ึk๓๔ถฟ็๓WีWิๅk˜ ฆ4พj1NUษ๋RoฆnปB…ว‰หฆโRs๙ฆฮว ฅ4z‚qbZงช`Wๅy๓พ2L‹ฟ}๒5คฮƒรngรšึฎ^I]UEชช’”ป๊ใ๐๘8ฟ|๎EB‘Xa„จ)pฯ–›จฉ('“อ๒โž๏๎ษหวšษ๊ ŽOˆ%‚ คAศ ี\้็ฏohฅสใŠ$ฒ๚cล[๛ย{rajหŠฺ:_> ?"Z†ทญ\„C)ฌ 5M7,ชLu‘‹ Y’ศํถฒศ˜‘T†pŒมpงMกบศU๐๏'ห‚OzR็ภaทsี๚5ดฌXสโ๊*ผn7ŠขY@QdY!“อ๐›wฒ็เ*หJ ๊M ๎ูr#ต•dฒY^ืมัฮฎผ{œฉค |๙หŸซGฤ_rAกะˆ %‚@ฉถ๊๊บVชผNbšฮทt๕=qt ฉ‡nูพะ^ซ?๑๊Gฏ\\uล๙ณ"žัูฒขถ`ƒไ†|๋ฆษ†E8m †iข›6YF’ kZDำบƒ1๚ร ๔ฎwR]‘โž}์^=pˆมแณบmฏอวฎ™ูK{ๅลื๖ใv: ๋ย‚-ื_MS",ำโเ‰N^ูw`ึ๏F„(Aa!AJR[–ื๑ะeห๑9m_~ๅ({็qฒe}9ฃ8ฺwlธ ฎึtกย”CUธขพE‚˜ฆำŠsc˜~—ล>ช,“ศd9ˆขศg^ึtรB‘%*งfL9Uปช LmๅKduย ๚#‰ฉซ๗]0ตะ‚Tฉ฿ว5—ฌeีา%นญy'ฒ,cZf.D…#œ์้g๗มรgขฆนN>๖wัPW;3{้…ื๖ใrุ ๊๗มฒ`หuWฑด~1–eqธ๓/ฝถึn?‘L3 $โ‰ฟฺ>ณ]A"คAศ ๕ถ•‹ุv้2Š6&i้ฅฃ์ž<ฟ.“ˆ!๓˜)[ˆajIi๑ทฎชฏจ›0ๅฒ)\พธˆerƒฝ iZ”ธิปsณฐ2Y:ฯ2HM›SๅฉSUF–$Œฉ05I2ŽcSeJ]g๕ฬB Rฅ%\นฎๆๅKฉ(๕Ÿถ"*ั„ยt๖๔๓๊ƒ ŒŒื}9์v>๑เ4Lmu;p๔/์ู‡รn+จ฿ห‚อื^ษฒ†z,หโศฉ.^ณ๏ผo7“ีŸ!JAAJศ ๕Žๆzปฎ‰"‡๑xš๑า:F‚ณsโต€ริๆฏ?ฝญม๏๙๙†)]ๅาEๅน ฅe้ `ฒ ํ ฆศ5ณ๕๐ไdU>๗ฝ‡บa!KPแuโฑูpูoZ15MัŠa“J=sปŠfพฉšŠr6ฌme๕ฒ%”—”เr:Pร0gBิษ๎>vuf`dtV๎ำฆช|bปYฒธำ49xผ“็w๏ลnS ๊๗ม0L6_w+ฐฐ8vช‡็wฟv^ท™Jj๑๑P๐/๛฿ลuAA)A„ฉ0‘฿A๊๎–XD‘Ce,žๆ_8ฤแฑูmG–I™๖งฺุย{sajหŠฺ:฿9l-*rุธคฎ ˆjY๚ 0HYTxœTyฏฉ@U9aXบa!หLอ˜z=Lฉฒ„nš$2:#ฑ]ม( Qแvฮส1๓5HีT–ณaM+ซ–.กฒฌงร"+ฆAZำ˜ G8ัีหซ146>ซ๗-ห2Ÿภ{ff/:ูษ๓ป๗ก*rA>duƒ-ื]ลŠ% œ่๎ๅนW๗œำmฅ’Z<e$xt{{๛‚Š‚ ‚๐VDA ƒิ}mทf ›สX<ล{แ0Gว/ฬyiั'KR๛Sฒ}กฝไว/u Uิปg๓s>—u5ฅภT ล‘คย;J“ ฏ EสGg †mรnXHR.Lyํ6ช‚ห&ฃศ2†i’ศ G“Sa *=ฎ ฆๆ[ชญฌเสumฌhj ข4ขdIžบjžF ๆXWปbd"pมŽ๑“xฯi[v์ฺ{N[?/&-“eหuWณji#'zzyv็๎ณบ ขAแญ‰ %‚@ฉwฏmโžึ6•‘XŠ/=ˆศฝฯ…ฆ6n฿แ฿PS๔อๅพži˜๒O) ˆฆ3๔†โgtuบ|SใuQ๊qฮl=์œŒbป+[tร *NผงชโTsWๅ3-‹Dฦ`$–ค'รฐฌ ฆๆKชซชไŠumฌZฺHน฿รaฯ…(ห$ญiŒ‚œ่้c็ฦม ~Œo{7ห฿ฐีmวฎื .ะฆด [ฎปŠๆeMHHt๖๖๑ฬ+ปฮ่gษ4‘hโK"D ‚ ย[AJR๏[ฟ”ปš๋qูT†cIพธใ ง&็ๆJn&t`šฯ๕‰๛ลv6aชฬํ ญบ ˆL)ฅƒT]‘›ทcf๋แฉษู]!๕fบaa‘ NปŠหฆโฒๅ†Ÿ›–E2k0Kq*ร4M*f9LzZ\Sอ•๋Xัุ@™฿—[%หฆA*ญ11ไhW{ftbrฮŽ๑ใ>pฺVทgw๎)ธ •Lฅูrีด,[Š$Iœ๊๋็™W^ๅญพ6'’iยั่wรมะงฟ๚h{ฏ๘ห*‚ oM)A๒?Hmปtwฌฎวฅ* E“|แนzๆJnฯ›ฆูพริe•ž/7W๚฿‡Ÿ—{œดV๙1H*Co8~^รภ/ห‚ล~~gn†VTหา=›“YNบaM=นซ๒นl .›2ต•ฯ"™ีง่ ลษ&ๅณ4cชPƒTC] Wฌmcyc=ๅ%~v{.D)-อฤdˆฃงบูีq˜๑ษเœฟ—>๚พwถีํ้—w\ %’lฝฺV,C’%บ๛y๊ฅพ๏อ"D ‚ ยนAJRผ|ทญ\„SUŒ$๘‡็:่'.ึรY a๊ษฦตๅฅsmuษ]ง…))7{ฉฅสaA8ฅัŠ_ญn’iAฃ฿ƒฯiŸูzุšฐ6ฝ•ฏz˜rช ช’ S้ฌฮ่T˜าM“2ื๙…ฉB R‹jงBิbสน%Iาi+ขŽœ๊f็ƒร‘‹๖^๚ศ{๏;mซ“/๎,ธกๆัx‚-ื]อšUห‘e™ž!ž~้U ำ˜๙7‰dš@0๔r<}ฏQ‚ ‚p๖DA ƒิ‡6ฌไึ•u8…H‚๚ E“๕1YX?อสึร;ถm]P'boS’$Qๅuฒบา‡aZ„ำz‚q์j)ำbIiลฬึรžะล[้%~—ทMลฅ*8mนซ๒™Sa*M_8Nฦ0)s9ฮ)LJZZฟˆหืดฐผฑžRŸป63ฌ<™N3:เXWฏ์๋ ]๔๗า‡฿}/ญหงถบ๕๐ซ/aS•‚๚}Gclฝึฎ^,ห๔๓๔Kฏข๚Lˆ '“<๙Gv ‚ ยน}฿AJ!ƒิGฎ\ลๆๅต8…พpœ๖฿`4–สa๑ ]1b˜j)๑๎ึ† U^ซ*Š1L‹P*CO(†ฃภNภ ำขi*HMo=์ _YX2>——ชไโ”M™~žฮŒ'านS†E‰ห~Va*฿ƒิา๚E\นฎฅ ‹)).>mktˆ:าูล๎ƒG.๊Šจ7๛ะ๗ะถb๙ฬVท_<๗bมฉ`8สึ๋ฏf]๓*Eฆoh„g^~•ฮž~ขAa–ˆ %‚@ฉ]ฝš›—ึ`SzC1>๛ฬ&้ผzŒ 5L๑g6>z๋eํ+ส‹oะงƒT0†ำV˜Aส็ดอl=์'๒f๖,I;r๘<ถพq+฿DRฃ/Gำอ3S๙ค–7ึsลฺVš๊Q๊๓แฐค\ˆJคRŒ&9t๒{:ŽŠF๓๎ฝ๔ม๛๎šYYิ30ฤฯŸ}กเ‚T f๋๕ืpIหjTEกoxค๏ฑo~w?_ํ@A„Y!‚” ๙คพฆ™MM5ุ™๎`Œฟf?มค–—U‡ฯ™ฒฑ6.จห๋ฆตQ7อ๖pโ†๑DW!ฉฉฐ6M’oณจeIขศaร3ตZสmSQำดH๋นSแ8iฤ๏|๋0•oAjUS#—ถ5ณฌ~1%พbv อฌˆ Lr๐D'ฏ๎?D,‘ศ๗าC๗ษ๚ๆ•ศrneัฯ~ปU)ฌ฿‡๑ษ[ฏฟšหฺš๛TEmWyป๘K)‚ ณK)A๒?Hๅต-ะT*หtMFyไ้}Dาูผ}ผ–Iฤyl!†ฉ'O๙lื่ฟพzQตวฎฬใ~s ฆ2 ๅaz#ŸรŽž‹RN›ŠM–ฐ,H๋‰4}ก8Yำขุa๛ฝa*_‚T๓ฒ&.i]อฒ๚ล๘‹‹ฐlนaๅ†A"bd<ท5๏ๅฝHฆาy^ฺvฯo\YฤOŸูQPCอ3Y๎มแ๛฿vหgฏฟ’ํโ/ค ‚ \"H ‚ A๊ฟ\฿สuUจฒLg ส฿=ต—xFฯ๛็u!‡ฉอ_zฦฆ๊/]ืXYYa๊๕ eG7M‚I‘X Iส๓๗เwุsซฅ์*ฎฉ0eZ ้d.L้ฆ…ื~z˜บุAชyYึถฒdQพ"๏ิึ< 0H$S sไdป:O& ๆฝุป๏0ป๎๚ภ๏{ฮํm๎๔*iFฃ^Fอ]ถี โฤุdƒึ ๙%›‚Ilร€m„ˆeI xBIHศbY’-ษEถl๕^f4ฝท๋)๛วฬศ˜bd{ส=šฯ๋/|๏นง|๏นš๗sฮ๗ั๏ผ—›–/มฎฺ้่้ๅ฿๖@QฌคRษLผซo๐k_๛'–_F!„brIB๒?H=ธn9k็”ก*6. D๙ฬcคrบe๖ฏiฑ)ถ๖ฟe๗ฬ[ฃajหผส25/7๚๙ •ำ FRzโ)lฺื—รŽฯiว๗sa*ญ้ ง2t„ค5CลeWง-H-Ÿ7๗ภญ+—S[]E(่ว้pކ(M#žJา?ศ‰๓—8z๖<‰dสrc๛nYฑ ปjงณทŸ์;€ขไ๗HJ%3๑‘h=ษมปร!„bาIB๒?H=ดกf•ข*6.๔G๘๔ณวศ๊†ๅ๖ณaาฆุl31L=ดฤ7๎™_QCuไ้ฑกฎะ-H %3๔'R–ื~งฟslŽ)งงช`šฃsL %3tFำคŸ8ฝพ~V๕‚ภ๘ญyำ4ฉ}œ<‰ืNŸ#ษXvฌ่}นmeป๎~e๏๓(yzฉ„(!„b๚HB๒?H=ฒqทฬ*Eตมนพ0Ÿฺs รย็๏ู!#W4ฮ ๙vฯคqถ~๗มะ‡jžXPผ7฿ยิ›ƒ”ฮ@"ร`2mู}mšpู๑:๘ฦ&?wช &ฃท๒ %3\่oุ2ฟ๚เTฎW:“]๏tุhบN<‘คป€ำฏ๐๊ษ3dฒYห๓฿ญmฑบงรAw๒์๓yw๋g"™&SorไฟKˆB!ฆ‡)!„ ƒTใฆ•ฌฉ)Aฮ๖…๙ิžฃ–฿๓Š|f}•๏กdNk ธgาxหว0ešP[่'ไv’ัG'Jf,ฟฏ ำ$8>ว”รŽ฿iว>6ŸQFื7x๖){†aฎืtํ@<‘คฃง3—›8r๒ ู\๎†฿๗ฝg wดงรAฯภ ๒์syณnใ!*<<๒™'v6ถสฏŸB1}$H !๙คพฐyซซ‹ฑง{G๘๔ณว,ฝฟ–๐เ๚ๅT๘=$s?:z่{'šง๚๖ฉ้ถ~๗มะ}‹*ฅก"ดaบ'>ล ีKNgo˜}m&ท]ล7vKŸCU6(6”Žนกpd}Woใ็.p๔์yr9ํ†ื๗nฤ7ฏฦๅtะ;8ฤ๗์Ÿ๖u’%„Bไ RBAฉวถฎfeeงz†yh๏qK๏๏%e!>y๗2ส9>ยฯด2 c†ฉ=ต๗-ช{j:ร”aยฑ[๖าฺhŠdฒ7พ6 Ÿk4H9UeCน฿3ฅcํษ๚gฯะ4†ฯุฒuทฎมํtา78ฬž?Z<งA"™fpxไๅp2๙๐“=<ฃฮ+B!Dพ“ %„ไ๚โถ5ฌจ(ฤNt๑ศพ–฿ห+ ๙ฤ]ห(๗ป‰e4๑T3zฎh`๒ดฆwloIใp:ร”๙ssHฅ4žh’X6wร๎k0yฎฉ{รƒ๋Nๅ็~ไแวึซpเFว๏x7oฟทหIะ?ณoส็ผ“%„Bไ? RBAฉืฐผผ8ึ5Hใ“–฿++‹๘ซป–R๊sหไ๘ฮ๑f~zฑใ—^7Sริๆ'๗ฌฟgัฌฏ฿\Sฒlชย”aย"?.'ฉœFW4Iโผ์็MวS๖fBบgl^{+—‹แ0?|f/S๕๏M QB!„uHBเกฝวอื;๓๓Dmณ๑•ํkXRย^๏เ ฯŸฒ๔พฉบ˜ึ.ฅฤ็"’ฮ๑วฎฐ็rืฏ}ฝ„ฉษSฆ uE \’9ฮH‚ิ |[Hš,๎พƒmwŽวๅfpd„l๒ƒT"™ฆodค#O|๖ฌ: IDAT[?ฒ[~ี„Bˆ'AJ!€๖pย<ืๆ@s'{†๓j์Šย—ทฏaqYบa๒jว8m้}๋ฌRโŽล{]„ำYพฺežk๎yห๗˜]a—ก8wฑ~F=ฆ}*ย”9~…”I"ซัNั%HMด™ค6ฏฝ•{ึ‰วํf(ๆ๛๗ูI›C*›ำ่์%„BX)!„tร4ำšฮ`2อนพ0{ฏtsพ??š‡หฎ๒ฅmkXTD7Lท๐ฅƒึRwฬ)ใฯo_L‘วI8•ๅ๏\โPK๏uฝw&‡ฉญOํฑ~nล—๏ช-+›่0e˜P?คโYึ‘8šaะ๛S‚ิไุpอผwใ]x†#้ง{€‰๗f*™‰๗ ๅW?—฿–_1!„ยz$H !ั ำฉ*†IZำ้‹ง8ำ;ยฆ. Fฆu|N;o]อ‚’ ša๒Rk_yแฌฅ๗๗บบ ไึ…zœ งฒ|ใ• ผึถ–1ฆžฟkใLฏ“ฆL๊‹bึ‘๚ o R“ใ๎[ึ๐M๋๐y<ŒD"ใฉT2‰ฦฟั“นปฑ1ŒB!,I‚”Bวบ†ฬ9…~.ล†aBZำ้ฅ8ี3ฬ+]ดŒฤงe‚.m]อผโ ša๐BK_}ัฺAjc}%|หBn'รษ _;|#๏hY†I›bณ5๎ฝห๎™6nวริ–y•eชb{Wหฝe/@A,“ใ๊p Rm&ฉตkV๒;[7เ๓x Gฃ|๏฿6!ห•%„BX$H !๐฿}|ฯ‚jnฎ)กฎะ฿ๅภฎุ0L“Tn4L๏โู+tFSบn…'_ุฒŠ๚ข 9เ`K/๛า9K๏๏m๓ซนฆ๙ธ &2|ํ๐yํค๒35Lญ฿}0ดถฆเ๑{ๆWิใP๏d&`๊ GƒT4“ใ๊p์†฿wค&วmซ๘m๑{}Db1พ๗๏?{W“š'’i"ัฤ—%D !„7 RBl}jฏ r;ู4ฏ’f•2;ไว๏ดcWtร ‘ี้'9ึ9ฤฆnบฃษ)Yทฏ‹/lYEma€œฎ๓\s๋๐K๏๏฿ZTร‡Wฯ#่r0H๓?_:ว‰๎‰™L0iุ฿ถd&แ๕ป†>P๓ฤ‚โเฝo7L&จ6s }„Nย้,ญร๑ัJu“ 59nnXส}๏ูBภ็#๑Ÿ>K&›EU•ทตœD2M8ง๐๐ศgžุูุ*ฟTB!ฤE‚”B๐FWโuฑy^ทฮ*ฅบภ;ฆอ0Id5บข ^๏ไนๆzcฉI]ทrฟ‡ฦอ+™๒“ำu๖^้ๆฏ^ด๔ภ’ูมสz.;๑4_}๑,ง{G&๚c†ั8ีมaบ‡ฉyE฿ฟ๙ฅtรฤก*ฬ.๐›hพe$ŽM‚ิ„› Aj๕าE{ท๔๙‰&โเ๎%–Hโt\฿x”%„Bฬ ค„‚_RใJ|nถอฏโ–šRช‚ผ;vล†nšฤณํแGปูwฅ›กdfRึญ*เๅณ›V0'ไ'ฃ๋์นลG.YzฒZ>ธขฟำNo<ล฿ผp–s}“v'ฮ S{j๏[T๗TCEhรo Sšaโถ+ิGƒิH*Kˆ\!5fBZฑx๙}๏!่๗K$๘แ3๛G๐ธ]o๙พD2อเ๐ศห๑h๔%D !„7> RBมฏRใสณฐšU•ลTx๑:T› อ0‰gst„ผึ9ศ3—ปˆgrบnณ |<ฒqณ |ค5Ÿ]๊ไฏ_ถ๔เŠ:๎[V‹ื1คv:รฅIšแ!{wl99“ฦ๖๕„ฉœnเuุฉz =๙ฐ=ฟแ๗ฉษฑ|แ<เ๗PO&๘๑ณฯำ;0ˆ฿๋๙•ฏQแd๒แ'{๘ B!„˜$H !ฟ9H›๒ณi^%ซชŠจ x๑8์จ6ศ&๑LŽ๖H‚—๚ูwฅ›dN›uซ-๔๓ะ†j‚>Ršฮ\่เฉcW,ฝฟหชz~gษl<;=ฑ$_7.ปŠ ะ ƒp:K๓PŒ—๛9ะƒfผฝZTZภงึ-งย๏!™ำ๘แ™Vพบลา๛๛On]ศ๖ีธT•ถpœ/<Š๎hrฺึว4ˆ่ ป ลนk&†ฉตuO~จกฎพ2เ!เrะOsq Bะํธกท]‚ิไ˜_;›๗พขPˆd:ลฯพฤพรฏตูLณQB”B!ฦIB}ืPQศฦ๚J–•R๊sแฒ^a’ี "cWLผฺห ญ}\๏๙wiyˆฟพ{~๑ฌฦ๗Oต๐ฃณญ–฿v"ถฮฏย1ค๗Ÿค/žš๖๕šษa๊‰#—v|hลฦ€ห>ง/žๆL๏%>ื ฝอค&วู5ื฿}?%……คา้ศ3๏๚ฝ{65ส/B!~ž)!„`โ‚ิธUUEl™Wลขาล^n๛่\<`8•กi0ฦพฆnŽt ฦe5T๒‰ป–Qๆwหh|๏d3?9฿n้w,fS}%Uฅu$ฦg๗`0™ษ›๕3 "(4๎ป๋ฎ™๖]0LsGO,ีxฒ{xNeะsCoซฉษQ[]ล๗} RZฺ•สdv๙<ž0B!„ฟ@‚”B0๑AjญณJูT_ษ‚’ …ฎ๑0ฅ†ฉ a^ํๅตฮม_ปŒUUEๅK)๕น‰er<}ผ™ธุa้—w.e]]Uกy8ส#{ONg๓n= “6ลfk{–3ํ;๑ํื.jIy่QCฝa๏“ 5_"5•ป>๚ก์ช()‘%„Bˆ_K‚”B0yA ภUWฮ]ตๅ,() ะใฤกŒ†ฉฌฎ3˜ฬpพ/ฬก–^Žv า๛ืT๓๑ตK)๑นˆfr๚pCอ Šƒ๗ˆaJ‚ิ„{:cืุุ(!J!„ฟ๙๏$ RB1นAฺ๊ X?ท‚;kหYP$ไvโT 2บฮ`"รน0๛›บ9ำ;rํ}ทิ”๐ฑตK(๖บงณ<๙๚๖7u[z?ธn9k็”ก*6.F๙๔ณวIๅดผ_oรค ำุ1ีcบจaJ‚ิ„yฺฆiO์ll•_!„B\๗฿Gค„bj‚ิ8ลfc]]9๋+ฉ+ Pเ Sฆi’ส้ $าœํa_S7๚#1ปŒ?ฟc1E'แT–ฟ?r‰C-ฝ–฿mhเถYฅจŠ‹sŒฌnXi†ั8ริ,ญ๎ขาะ{}NปๅทG‚ิป&!J!„๏˜)!„`jƒิ8งชฐฑพ’ปjหฉ+๔p;q*6 RšN<ลฉž†’i~g้ =NFRY๎ี‹ผฺุg้ศฦ2ซี็๚ย|jฯ1 Uผ‡>ปiEใขภม™๔}Yฟ{Oํ}‹๊žjจmฐr˜’ ๕ฮ˜†yศPlO>๖๐Œ๗B!„˜Xค„‚้ Rใ<•ญ๓ซนmV)s \ca*ำˆg5B'.Ua(•ๅ๋‡ฯ๓J๛€ฅ๗wใๆ•ฌฉ.Aฮ๔๐เžc–Žš/l\ษ์฿กดฆ๏๐9ํญ3้{c๕0%A๊ํ‘%„Bˆ‰$AJ!˜ 5ฮ๏rฐu^ทิ”P[ไ'เt` SŠ ฐูHๅ4พyไฯX|R๓GทฌbUU16เT๏ŸyึšAjNศฯรจ)๐‘ึt~zฑใ้'Ž_j<ธc{๋L๚ฌ฿ฝง๖๓f๔ๆš’eV Sคฎ„(!„BL RBA~ฉqE๋+น}v)5>‚.ชbระ4้Š&9ิาวพฆnบฃIK๎๏วทฎfEe'{†yx๏qKnG]กŸ‡6ฌ :่%ฅ้๛…vvkย0yZSฆ6?นg=‹f}*aJ‚ิ[3 อfš฿z‘๒+!„Bˆ‰&AJ!ศฏ 5ฎฤ๋b๓*ถ/จฆา๏มfRบaฯๆ่Œ$yฝs็š{่‹ง,ตฟwn[ร๒ŠBLเXืŸย’ใฆพ(ภg64P๐’สi๋๙vพ{ข๙ฺืเ๓†โupว๚๐L๚>Y%LI๚ี$D !„b*HB๒3H๛ƒ•s๙`CNปŠišืnแำ “DNฃm$ฮฑฎ!žนE$อ›/o_ราฒpดsฯ?wา’ใfAIื5P๐สi่\x๒๊›^cDt…]35LmœWฯwี–•ๅc˜’ ๕ "ฆอ|@B”B!ฆไ๏ RB‘฿A๊๗–ี๒มu๘v’YกT†B ฏรŽbm์ŠฉŽp‚W;x๖r๑ฌ–ท๛ฺฎ(์พ†%e่&iเฑง,9n•๐ฉuหฉ๐{Hๆ4~xฆ•๏Ÿn๙•ฏษaj๋S๛vฌŸ[๑ๅ| SคฦDtƒ]š[ตปฑqFM!„BL RBA~ฉ6ิq฿๒Zผ;ฝ๑฿=ัL}Q€••ETข™n's‹”๙o SัLŽ–แ/ท๕๓\sMฯ›ํ๑9ํ<พu5 J‚h†ษKญ}|ๅ…ณ–7ห+ ๙ฤ]ห(๗ป‰e4๑T3zฎ๚Z€I›bณ5ฮฤ0๕ะ฿ธg~๕G=ี1๋1“ƒ”ฎ๑y QB!„˜Nค„‚Rดบž,™ƒวฎาK๒Rk%^๗Xš&UanQ€RŸท]EฑAฮ0‰ฆณ\Œ๒jวฯ5๗ำi฿žทƒวถฌฆพ8ˆfj้ๅผxฮ’ใfEeu็Rสnb™฿=ัฬฟ_่x[ห˜ฉaj๎ƒก7ิ<ฑ 8x๏t…ฉคžถiZใ;[ๅฬ/„Bˆ้$AJ!ศ๏ uš๙ผw๑,‚”i˜‡C฿!!J!„๙F‚”B฿A๊On]ศ๖ีธT•ถpœŽH‚ฌ๖›oฝS>‡Y!E.ปr-L '3\ SG:ฆt{*>ทi%sB~2บฮณ—ป๙๛#-9nnฉ)แck—P์uNgy๒๕+์o๊žจลฯะ0ตง๖พEuOME˜บ‘ƒ”i˜‡ ลึ๘ไcฯจ๑#„B๋ %„ไw๚ณฑu~Uฅ=ง+’$ปIสvNMศKก…SUฐู ฃ %3\่sจฅ—ื:งd{j ||vใ f๘Hk:?ปิษท_ฟlษqs๛์RSไuNeyโตKผฺ;กŸa˜<ญฉFใม[gาwr*ยิค$D !„ย*$H !๙คโŽลlชฏฤกชtDโt„“๏่ฉy‡ŠSU™๒๒8qช ฆ ]g(™แ|_˜W{9=4ฉS[่็ก ิ}ค4ธะมSวฎXrY[ฮŸถˆB“‘T–ฟ{๕"/ถ๖Mสgอิ0ตu๗พ•็U}๗ๆš’eฆnค e@› ;$D !„ย*$H !๙ค>~็RึืUเP:# ฺย๑๋บe๏ื๑:UN'7Nล†aBZำLฆ9฿แูห]œ๏Ÿœงมื๘ฬ†ช^R9Ÿ\h็;ว›-9nึีU๐งท.$ไq2œส๒ฟ_นภแIž›kฆ†ฉอO๎YฯขY_Ÿศ0u#)ฺlฆู๘ญวู-gr!„BX‰)!„ ฟƒิ'๎Zฦuๅุ…ฎh‚–แ89xWหดู ฤ็&ไqt9๐9cWL™คr:‰4g{Gุิอฅศ„nฯ‚’ ฎk 2เ!™ำ๘๑ู6๑ิUKŽ›๕•๑- น '3|ํ๐…)™“ห4ˆ่ ป ลน๋เŽ๕แ™๔]ศ0eๅ %!J!„V'AJ!ศ๏ ๕ษป—qgm9vลFw4E๓pMŸ˜ีUUทŸCล๋tเPl˜&ค4พxŠS=ร์ฝาอีแุ„|ๆ’ฒŸผ{ๅ~‰œฦNท๐ƒ3ญ–7[ๆW๑‘›Pเv0”ฬฐ๋ๅ๓ผ>Esqม Sg๏6ึW~๓ฎฺฒฒwฆ,ค "บมฎ'w>(gn!„BX™)!„ ฟƒิงื7pว์Rิฑ ี4E7&vuUลFuะ‹ฯๅภ๏ดใuุฑ+6Œฑ+ฆ๚โ)Žwณ๏J7mแ๘ป๚ฌeๅ…๕ห(๗ป‰e4้ิUๅ\›%วอ{T๓_ošOะๅ`0‘แo_>วฑฎก)_™ฆถ>ตoว๚น_~'aสRAj,Dinmื๎ฦฦuŒ…Bqc’ %„ไwzhCทอz#H]Œ2Y็n‡ชP๔t9๐:ฦย”ช &ษœFo,ลฑฎ!๖5uัIพฃฯXQYฤ'๎ZJฉฯM,“ใ;'š๙้…KŽ›๗.šล‡Wืp9Hค๙Ÿ/ใD๗๐ดญaาฆุl{๏฿ฒ{ๆ}‡Gริ–y•eชbปฎ๗X"HIˆB!ฤ J‚”B฿A๊ณWp๓ฌR ;–ไ๒`&ymv•ช€‡ ‰หฎเwฺฑ+ ša’ศjtG“ํไนฆบco/Lญฉ.ๆตK(๕น‰frรั+‡พxŠฏผp–๓yy1ห!ร0ง:พLท฿ฆ๒0HIˆB!ฤŒ!AJ!ศ๏ ๕๘ึีฌจ,FƒTำ4ฉk?6Mg^q€ช รŽjƒœaฯไ่ˆ$xนญŸMฤณฺฏ\ฦuๅ้ญ‹(๔8Ie๙ฦซyฉตฯ’ใๆC+๊๘ฝeตxvzใ)v:รฅH>ฏ๒ S{j๏[T๗TCEhรฯO|ž/Aส4ฬC†bk|๒ฑ‡gิqB!ฤฬ&AJ!ศ๏ ๕ฅmkhจ(ฤบ" š†bำพNYรภก(ฬ- Pแw†)ลFV7ˆerดฤyกตƒW{Iๆฆ6ึW๒วท, ไv2œฬ๐ฟ^นภซํ–7ธฒž{—ฮฦใฐำK๒ลƒghŠZaีกุุปcหษ™๔=S๓ŠJ}๎iRข„B1“IB๒7Hู€obYy่ฮ“ 5.gธ์*u…~สv๕ฺSัt–ๆแฏดฐฏฉ›œnŒ๎๋๙Uท›Pเv0˜ศ๐ตร็yฝsะ’ใๆรซ็๑Kfใฑซtว’<~เ4W‡c–YรไiM5๎ุ:“พ๏๋w๏ฉต๋J#ฆฑ{:‚”b˜ข„B1ำIB๒7H)6_พ†ฅๅ!ts๔ ฉๆก เP๊Š”๙ธ์*6@3 "้MรQ^iเนๆถฮฏbวšy]i๖ฅ๓๏ฒไธนอ|ปxปJg4มใNำ:ทvธ์๊ำ_ฺพบqYYaซœ „B!ฤT %„ไorจ ;ทญaqYบaาMru(ฏภ1ท]aNแa ซDาYš‡bฤณทฮ*!เrะO๓?^:วฉžaKŽ›ผ€{ึเถซtD<๚):" หm‡฿i็๑ญk˜_|Z3Œv5,g!„B1™$H !๙ค<•/n]รยาเhŠ$-qK˜อfร๋T™]เฃุ๋บvลTF7ศ๊^‡ŠjณัO๑ีฮrถฯšใปe!๏YXKUi$๘ยs'้Š&-ทn'mYE}qœnDถ๔๎๚๒แ+ป๎X/aJ!„BLฮ฿ ค„"ƒ”฿i็ฑญซYPR€ftF’ดXhŽ"ปjรcท3;ไฃะใผฆฐูH็4พ{โ*?:jษq๓฿o[ฤึ๙UธT•ถpœฦ็NาKYn;Šผ.พฐys‹ไtƒW{๘ฯGt…]†โ”0%„B!&œ)!„ ƒTมc[VS_ R Z†ญ7G‘กโTUf…ผ”๙ุำ4้Oค9ู3ฬ -}–›ฯo_ฬ–y•8T•ึ‘8ฯ ?žถ๑)๕น๙ๆ•ิศ้:๛›{๘๚แ ฃวศ ข+์zญrฆB!„E‚”BฟAชศใโ [ธrฅ+jอ 5ฮiWฉ/ P๔`ปJJ7L2บฮP2ร๙พ0๛›{,3งิว๎Xยฦ๚JชBหpŒฯ๎?มP2cนใR๎๗ะธy%sB~rบฮณWบ๙ปW/พ้5†I›bณ5๎ฝหn9c!„BˆwK‚”BฟA๊ฏ\้Œ&iตp๐9ํฌฉ.ฦiWั ร4qจ ฆi’ึtโiฮ๕‡ู{ฅ›๓๙}งุว๏\ส๚บ ชB๓p”ฯ๎;มH*kนcR๔๒ู+˜๒“ัu๖\๎โ‰#—~ๅk%L !„Bˆ‰ AJ!ศ฿ U๐ะธiๅตPะuฉวษา๒.Ue$•ก;–ข2เ!่vโTl&ค5พxŠำฝ#์o๊ๆ๒`4/ทๅw-ใ๎บr์ŠBำP”‡๗'šษY๎˜ฬ*๐๑ศฦฬ*๐‘ึt~vฉ“oฟ~๙-฿c˜ดa;๖d๛A9ƒ!„BˆทK‚”BฟAช:่ๅณ›V2ปภwรฉRฟ›…%AชJ{8ฮ—กกขf•RW เrเS9xŠS=#์k๊ฮป' ~๒๎eY[Ž]ฑqyp4HลณšๅŽImกŸ‡64P๔‘าt~zกƒ8vๅz฿~ศ0ŒF SB!„โํ %„ไoš๒๑ศ†ิŒ]นาณ~ช*๐2ทะ?6xŒฟ;r ]%‘ีhจ,dEEu…~.vล†nšคrฃWL๋โู+tFyฑ-ฎ[ฮฺ9eจŠKQ>ณ๗ฉœnนcR_เ3จ xIๅ4~rก๏o~ป‹‘0%„B!ฎ›)!„ ƒT]กŸ‡6ฌ :่%ฅ้๔D“ดŽX;Hอ)๔3ซภ‡CUธ:ใ๏\ฤ๋ฐฟ๑ๆ•YS]ฬฌ~ง‡ช &ษœFO,ษฑฎ!๖7uำIN๋ถ<ดกf•ข*6.Dxpฯ1ฒบaนcฒ $ศƒ๋จ xHๅ4~tฎ๕ฬQฌ๘ซบด<ฤ_฿ฝŒ ฟ‡xVใ๛งZ๘ัูึ Yถ„)!„B๑+/AJ!`็ก3ๆก–^๔<ปบeIYˆOฝŒŠภh(่ป‚ิา๒ล^ืตพyไAท๓7พฯญช,( าP>zล”ืaGฑf˜ฤณ9:#I^m`ฯ•.โS๔คปฦอ+YS=คฮ๔๐เžc–<& …|โฎe”๙ฤ2฿;ูฬOฮทO์‡˜ๆืฒชซ๑เŽ๕a9ใ!„B RB๔ฦRfำP”W:8xต—\žฬดฌ<ฤ_฿ฝœ๒ฑPะOา>’ฐ๔พ^VQH‘ื…jƒs}aพ๕๚eBืคฒบAฮ0ธcvซ*‹จxFร”bCำ ข™‘/ต๖๑|sฯค?๑๎ั-ซXUUŒ 8ี;ยgžตfZYYฤ_ต”RŸ›X&วwŽ7๓ำ‹9ฆADWุe(ฮ]ฆ„B!f6 RBฆifuƒH:Kหpœ๚8tตwฺ'จ^QYฤ_นt์ส•=ฑakฉฅๅ!Š}nเl_˜oฟ~‰B๋m-#–ษแPึฮ)ceee>7๎ฑ[๙rcaชu$ฮหmฃajฒž|๗๘ึีฌจ,เTฯ0ํ=nษcฒฆบ˜ฏ]J‰ฯE4“ใŽ^แ™ห]“๖yฆ„B!„)!„R9t`๔*œp:K๋HœZ๚xกตŒฆOหzญฎ*ๆใw.กิ็&šษัMN๛“ๅญ%ๅ!J}nlภ้ž:vๅบฏ๚EฑLรฮํณKiจ(คฬ๏มmWQl3Lข้,MC1Žt ฐฟฉ{ยใทญaEE!&pข{ˆG๖ฐไ1นนฆ„ึ.กุ๋"’ฮ๑ไ๋—ูืิ=้ŸkDPhwึ]rB!„˜Y$H !pจฅืœ_คะใฤฉŽฌaIei‰๑J๛ฎN•6o >vวJ|ฃก ;šค;jํ ตธ,D™฿ ภษžaพsผ‰‚wคฦล29.ทอ.eyy!e~7.UลfƒX`ผ:็ฅึ>\ํ™ฐ'แํพ†ๅๅฃA๊XืŸoอ u์Rโ๖ลy]„SYพ๙ฺ%\ํฒฯ7Lฺ›ญq๏[vหูH!„bf %„ภถง๖šwฬ)ใฮฺr–Pไ}#L฿vu8ฦ๋ƒ์k๊!•ำฆdฝnUสว๎ ้,]ั$ฝั”ฅ๗๕ขฒ*Lเxื฿;u•เ[๚TพH:;iกเOn]HแX(่Š$่[7Hูlฐฐด€ส€็Zฤ๙๑ู6|N๛ค|^,“ฃ*่แ–šR•P่qแTl6ศhฃa๊|˜Z๚8า๑๖ย”SUุน} ‹J ะ “W;xภiK—๕•๑- น '3|ํ๐…ทฝ?&ษ!ร0%L !„Bx$H !ฟ:H[YYฤๆyU,*ฝbสmWQฦžๆ6zลTœื:9pต‡‘ิฤ†ฉ_ ั$RŠbc~qช 0yฅ}€ฟะŽวaŸิฯerฬ)๔ฑบชd,L9qช ฆ Y]g(™แ|„W{8ึ5t]หtUพดm Kƒ่†ษหm์nƒ‰ _;|žื;๓i%L !„B`$H !oคฦญฎ*ๆ๎บr––…(๖นฏ=อM3Lโ™ญแ8วป†ุ{ฅ›๐]1ตe~นinCษ ‘C‰Œe๗ณชุ˜_ค2เA‹8?ปิ‰ฎNษ็ว29j :ซ”yลB๎ฑ0ค5มฤ่S{ฏtqถ/–ห๒9ํ<พu5 J‚h†ษKญ}|ๅ…ณ–<.๗,ฌaวšy]i๖ฅ๓๏สป๕41-ง˜ฑฝUฮZB!„ึ&AJ!ธพ 5nEe๋๊สYZ^H้ฏSั$ฏwฒ๗Jืปพb๊CAg4ษฐ…ƒ”CUจ/P๐ข‡Zzู฿ิƒSUฆt=9ฺŸg—RW ภใฤฉุ0TNง?‘ๆl฿๛›บนะ๙•หบ<ถu5๓Šƒh†ม -}|๕Ekฉ๗/žลYUOภๅ ?žๆผtŽS=รyปพ†ษำšj4J˜B!„ฐ. RBม Rใ–”…ุT_ษา๒e~žฑ[๙4 –อัM๑Z็š{้‹ฟณ'ใฝo๑,h, $าtF’ 'ญคœv•๚ข9เภี^ํล1ลAj\&ง3ฏ$ศš๊b๊ NŠ ำ„”ฆำOqชg„}M]4 ล๔ษฃ[WQ_$งฦต๙า9K—{—ฮแC+ๆpู้‹ง๙›ฮrถo$๏ื[ย”B!„uIBYทธฌ€อ๕Uฃaส็ฦํฐc›c*žี่Š&9ฺ9:วTO์ํ…ฉ฿Y:›ผขZ(่Œ$งฒ–ฯn‡สขๅ~9]gs/ต๖aW”i]ฏŒฆณธ,DCE!s‹\์Š ร4Iๅt๚โiNtฑฏฉ›ึ‘8ล^_ุผŠบข9เ๙ๆพv๘ผ%ห}หk๙†:|;}๑_yแ,็๛ร–Y >o(ฮ]wฌหูL!„ย$H !๏.H[XRภฆy•,ฏ(คฬ็ฦใPQm64ร$‘ำ่Œ$9ั=ฤฆ๎๋Sใกภ๏ดำOัIฑp๒\ส่:{ฏt๓jวชอ–๋g˜&๓Šƒฌฎ*fNก€ำ]Uะ “dNฃ/–โX๗๛ฎt“ึt>ฟyต…ัธึิรื_น`ษใ๒กuฒZผŽัqถ๓ะ. D,ต ฆADWุ%aJ!„ย$H !คฦอ/ ฒฉพ’ๅๅ…TฆบฃINtณ๏J7ฑไ[.๋ƒ+๊ธ๏็BAg$I4m ๅuฺฉ+ P๎s“ึtžนษ๑ฎ!lyคฎ8bcAiีUET}๘vช‚6ฆบฃI.DXS]LUภ{-ฎซ-y\pe=๗.วaง'–ไ‹ฯะ4ตไถH˜B!„ฐ RBมฤฉqs‹lชฏคกฒช€รŽj4Id5zc)Žwณฟฉ›ŽHโบBAg4I,ณ์~๖น์ิ๚)๓yHk:?ฝุม™ซศ†%ๅฌฌ,ข*่ล7v;ฆ>v+ŸCUpฉ iอเ™หป”ีUลิ๘๐9ํŒ฿l˜ส้\ŒpธฝŸM=ฤ,ฆ>z๓๎YXƒฎาI๐…็Oั๙kฎฺณ* SB!„๙E‚”B05Aj\uะห–๙Uฌช,ฆ*8zล”:๖DทdNง/–โT๏่S๋+yฯ‚ัPะIะM’ดp*๐8ฉ ๙(๖บIๆ4~tถอrsล29tำไ‹gณnnN๕'ๆtƒh&G[8ฮKญธฺc‰€๘งท.b‚*\ชJ[8ฮž;๕็7ณฐC†a4๎ศ๖ƒrๆB!„˜>ค„‚ฉ Rใช‚^6ฯซdUe15^|N๛ุSฃ๓๕'า˜&ิxq( mแ8ั$ฉœnู๒8™S่งฤ๋"–ั๘ม™ZGฌwkXw4‰วa็s›VPๆsc9รDตูPmฃ;šษั<ๅีŽ๖_้&ฃyป=~๛bถฬซฤ1ค๗Ÿค/žบัฟ๖‡ฒŠฑใเŽํญrB!„˜zค„‚้ Rใช‚^6ฬญเฆ๊ช ผ๘v์ส่LำฤฎŒึMั2#mแ U่u1งภGฑฯE,“ใŸN]ฅ#bฝ+qzbI|ŸZทœส€‡Œฎำ6’ภeW(๗{pูU่S‘tŽซร1ท๗๓\sน< Sqวb6ีฉ–แŸ‚มdๆ††ฑAฎ”B!„˜ค„‚้ Rใส6ึWpKM)Uมฑ0ฅ*ืๆ(สh:W‡c„ำYโkถWไs1ปภGฑืE4“ใ{'ฏาต^๊ฅ๐ป์|๊๎ๅ”๛=$r?8ยน0›๊+Y^^Hฉ฿ฎฃa*œฮru8ฮก–^ต๔ข๙๓๛๛๑;—ฒพฎ‡ชะ<ๅณ๛N0’ส๐฿{ RB!„ำG‚”BAj\กวษถี\]ย‚’ ฎฑจaษฌFค„‚ Rฎ[ฮฺฺrŠTN'ฃ๋๘ช‚a˜ค5มdšŽp‚ดfไ}˜*ธฉ ๚yœŒคฒŸฃWˆคญwkุ@"Mศํไฏ๎ZJฉฯM,“ใ;ว›๙้ลŽ_๙๚ตsสธซถœEฅz\ืžฬ—ีu†’Y.๔‡yกต#ำsลิงื7pว์RTลฦล(Ÿy๖ุ่x78 RB!„ำG‚”BฟA๊3๋ธ},\Œ๑bkทฬ*กฆภGะ5ฆLs4L $าtDd4รศฯs{EะCuภKศใd8™แG/[r>ฌมDšBฏ‹ฏ]BฉฯM4“ใŽ^แ™ห]o๙พป๋สนซถœ…%zœcว2บฮp2ร๙๛›บ9ู3<ฅ๓ะ†n›5:ฮ.๔Gx๐ูcy9๙๚D“ %„B1}$H !๙คูธ‚[f•ขฺเ|„๗ลeWู2ฏŠf•2ปะOภๅภกุฎ…กd†ถpM7๓.*TฝTฝธ %3|๋ตห$sึ RCษ ล^ฌ]BฑืE$ใฝฬ+ฟ๙‡ธณถœM๓*ฉ/ ปb๊็รโ๙{ฏtqฎ/<ฅใLฮ๗‡๙ไžcฬ„HB!„˜>ค„‚ RŸด’›jJP€sa>๙ฬัkอ๋ฐณu~7ี”0ทะOภํฤกุ0ฬั[ม†“:" ฒบAVห0U๔R]เ%่r0H๓ํื/“สY๏ึฐ‘T†bฏ›ฑ˜"ฏ‹p:หท^ปฬ๓อ=ืฝ ‡ชฐ~n๋๊*จ+๔t;qŽฟดฆำŸHsบg˜M=\ŒL๊๖4n^ษš๊ัqvถ/ฬง๖฿{ RB!„ำG‚”BฟA๊๓›Wฑฆบpฆw„Ÿ=๖Kฏ๑:์lจฏเถYฅฬ- ผ)lduแT–ฎH’”ฆM{˜ช zฉ)๐p9่ง๙ึ๋—ษhV RYสn๖ลyœ„SYศ%ต๔พํe_๑v๛์R๊~!,ฆ5XŠำฝร์ปาM๓plRถ็ั-ซXU5:ฮN๗Ž๐้_1ฮnDค„B!ฆ)!„ ƒิฯ‡‚“=ร<ด๗๘ฏ}ญฎrw]9wืU0'ไ#ไvŽ dดังบuG“$sำฆFƒ”€หN_<อ7_ปdษนŠ"้,ๅ~ถEŽMะW/๒Rk฿;^ๆ๘oทฬ*ฝโอๅภฎุะMHๅ4๚โiNt๑์•.ฺร‰ žวทฎfEeง~ร8ป‘HB!„˜>ค„‚ Ro]อสส"LเD๗์;๑฿ใRึฯญไฮฺ2j Œ…) S#้ แ$Y]'ฅ้0…[^๔2;ไร๋ฐำO๑อื.กึ๛ŠฆsT=ษ- G'hOe๙๚แ๓ผา๎Ÿ’Wเvฒฑพ‚;f—1+ไ#0๖TEอ0Iๆ4zc)Žw ฑทฉ›ฮศฤ„ฉ/n[รŠŠยท5ฮnค„B!ฆ)!„ ƒิฮmkX> Žu ๑นื œชย†น•6ปtl๒l'e4Le๕ั0ีI‘ีu’9ฉ๘9จ z™๒แqุ้‰)ร‚ฟCัLŽš —ฒ€ษP2ร:|#๖E›ๆUr๛์2ชƒ^N;vUA7LYฎh‚c]C์o๊ฆ'–zwใl๛–—bวบirF|๏%H !„BL RBA~)›อฦ—ทฏaiY8ฺ9ศ็Ÿ{๛กภฎุXWWมsส˜_$ไy๓S‘t–žX’TN'™ำ'๕้jUA/s x์*ฑ$Oนdษ๑ฯๆ˜]เ็›ๆSเv0˜ศ๐ตร็yฝspย?+ไv๒[‹jธนฆ„ช ŸรŽชุFรTNฃ3’เhื{.u1œสผฃq๖•ํkX26ฮ^๏เ ฯŸš฿{ RB!„ำ๘๗Ž)!„ศฯ eWl์~Kส ะMxญc€G฿E(ฐwึ–ณ~n๕ลŠ<.\๊WL…ำYzb)ูฉœ1)aชชภKmศฎาM๐อื.cณเxId5j ์X3๏ฺ๖ๅ๓๏šดฯฌxุ6ฟšUUEิŒ๖จุ@7Lโูั0๕jวฯ^๎"šษฝqฆฐs๛šัqf˜้ไฑค„B!ฤไ’ %„ไgrฉ _ฺพ†Eฅฃกเ•๖พx๐๔ป^ฎbณฑvNูต0U่vแฒ+ุxs˜2L“‘Tc็xช.๐2g,HตG|๓ศEิฑญ$™ำ˜[เVี R_}๑งz†'ณg‡|lžWล๊ชb*ๆลณ“๒Yk็”ฑvN‹JC{฿ฆ9dV#–ั่‰%฿U˜ช RUฅu$ฮ“ฏ_FUฌwำ^ZำYXRภWิแwฺ้ง๘›ฮrฎ/<ๅ๋2ฟ$ศฆ๚JVVQๆ๗เถซ(6ศ&ฑt–ฆกฏv ฐฟฉ›ฌnา๛.o]อผโัq๖BK_คq–o$H !„BL RBA~ฉษฃ[WQ_$งj้์wt\i^เ๏M•ซTฅR*IVvฮvปsป: /ณ K\e†ษMำ“ ห ;ภ–xู]Xย๎พคmwปฃsJถ%U)”Jชœ๎ฝ๏Uฒ3ำูvU๕>็ฬ9sfฌาญ็+ฉพ็yžหz๑์mžบ[ุ5aeK€ฐว‰Sื*K๙,›lฑDถd’ฬ—ˆฅs”ฟEx;• ๅวะTF็SูัaqฉBูdu[ฌ๏รc่Lงs|ๅะiฮฯ,ึ์˜Vท5ฑgฐ“๕!Zฝ.\๚จธ˜/1:Ÿโล+ำ์‰Qถฌš^g๕B‚”B!DํHB๊3H…=Nžฺณ™f?%ำbH”ฏฝt๎Ž|๏-]a๖ FXฺูT Sš†ช*฿0cชD,•ฃ๔.ยTwะKศ‡ฎช ว“ท#X ๘kจhZฌm๒แตฝx h*ว—žโา\ฒๆวถฎ=ฤ#ห;YำึD›ืu#*V๗‰งุ?ๅ…๑lฎ้uVkค„B!jG‚”BPŸAชอ็โษ›้ ๙(™&ฯ G๙๚ห็๏่1ีๆแVทฏฯ˜R([6ูR™tฑLถXb*๙ฮยิฒ —พ]Uธ4—ไžWAซ^”L‹๕!พoMnC'šส๒ล็O1Oีอ1nŒ4๓่๒NV/Eล›ยิ|ฎศๅน$๛Gฃ ว“5ฟฮjE‚”B!DํHB๊3HEn~u๗&zƒ> ฆษ3—ฆ๘W/ิไXถt…ูืฮฺถ -ีY7K๛ๅJerฅสSSษ์[ฆžjาT… ณIๆLc)ำฒู ๑=ซ{p๋“ษJOีฑณฌ•ฌlmzรฦ๕…ฒE"W`<‘f0์งลใช๙uvงIB!„จ RBA}ฉ๎&Ÿต‰ž&/๙ฒษ?_šเ_ปTำcZืb๗`„5ํAฺช๛ฝ1L™$ซK๙ e๓›พพ'่ฃฏู‡ฆภน™E๊ิ(ธ‰”ilŠ4๓ซ–แา5&3|ภ)ฎ,ค๋๖˜๊kฏl\฿ึDณ‰CSฑํสŒ)]Uะ5•Bูไ.\ซ๙uvงHB!„จ RBA}ฉ ฯ์@w5H…kษ‘หuqlkƒ์์dM{Vฏ ทฎกU๗˜สVรTชX S๙า0ี๒ั๒กgg๘๓cรธ ฝแฎถูๆ;Wvใา5ฎ-fxjI&3u์๕ตณc ƒๅแ!ท‡ฆ‚ข T฿ื๘B†ฏฟ|žำฑฤพ— %„BQ;ค„‚๚ Rอ~>ตc]นฒษw๎*zlธฎŽqM[]ƒึ-อ˜2tด๊Sน’IถT&S,3•ส’/™๔Uƒ”œŠ%๘ำฃร\FC^3[ปย<พข งฆqe!อS๛N2•ส6ฤฑซŠย๖vv DXัR SŠR™ฉV2-&“YฮN/๐๐็f>ฐ๗ฝ)!„Bˆฺ‘ %„ิg ๘ิŽ๕Drฅ2w๖*qbค.วoUk;"ฌ๏ัแsแ24TEมฌ†ฉtฑDฎlข) 'ฃ๓๑๋—h๑บ๒šูึยcห;1ชA๊ษฝ'˜N็๊=84•kc??ฐฎ—ฎaุ6– ๙ฒษt:วฉX‚ฝรSu๑ม[M‚”B!DํHB๊3Hญlmโฏงร็&[*๓ืgฦ๙ห“cu=ŽCแป#l่ัแwใพiฦTฆTฦPU††iู›Š๓ฏ]$โ๗4ไ5soO+{#šฦx"ล{O0—ษ7๛Xูาฤ'wฌ'โwcฺP4MtUEW•J˜*•™ฮไ9>g๏pด.7nฏ$H !„BิŽ)!„ >ƒิšถ ฟ๒๐::|nาล2ujŒฟ>=ใ9๖ณ{ฐ“ !ฺn<†Žฎ*ุถ Šถอd2วŸ?…ฎ*๘ทl๏6vD04•ั๙O์=ฮ|ถะp๏cM[_ูพŽ๖j๘<=ภฅk๔}๘บฆVgบ•™N็865ฯณ—'นบi๘๛^‚”B!DํHB๊3Hญ๏๑หญฃ็"U(๓฿OŽ๐ฟฮ^mจqํ๙ุ3ิษฆH3m>7ง†ฝІใ)NF็yebหฒ*Lm๏kg{†ฆ2O๒™็Žณ˜/6ตฟฎ=ฤวถ฿ธฮวษQ๖Dู5แ6บ›<๘†ฆRถlฒฅ2ัd–ฃ“q๖ŽL1ฑ˜mุ๛^‚”B!DํHB๊3HmŒ4๓หญฅี๋"U(๑็วG๘๛๓ืr|{‚^[ล‡Vu_ชž ˜–EถdMf9K๐สีส ฆv๔w๐P;บชry.ษgž;FชPjธsณ1าฬ/=ธ–6_ๅ:๛‹ฃŸs•๐t9x|Ew/kฅปษƒท:ำอดm2E“‰ล วฆโƒิถ๎~แ5„=N๓%๘ศ%žป<ีฐc์w|แั- …˜ถอฤb†Bูค+P บZYVูซ(ฯ้X‚—ฏอ/™uฆ๖ urO+šชpa6ษ'Ÿ9Jกl6yนซ+ฬ/<ฐ–oๅ:๛“#—yๆ๒ไทท]{†:ูาฆซษƒ็ฆM๋Sล“‹Y_™a฿ศ‹๙๚Sค„B!jG‚”BPŸA๊พžV~พี4{œ,ไ‹มซ90kุ1น<๕ศf›”L‹็วbJ&A/aƒ ห‰ฯกฃk*V5Lลชa๊•kณไJๅบ S.๏ไe• u~f‘OŠฆษ3—งะT—ฆ]7N]ฃ3เฦ๋ะ๑•h7…ฉูl3ำ ^ป6วbพXำ0๕]+ปฺู‚ œ™^เใOiศ๓๒P_;?w๏*Bี๐๙ปฏ\เลw>Wถ4ฑ{(ย†Žm>7.]C] S๙"ฃ๓)^พ:หแ)Šu4‹L‚”B!DํHB๊3HํŒ๐ำwฏ ่r0Ÿ-๐ต—ฮ๓๊ตู†ใฎ€‡'voขงษKม4y๚า$>‡๒-ญำะ่๐น๑;o„ฉ๋K๙ส&๑Lžณ3 ผte–dก6a๊Cซ–ฑต+ŒœŽ%๘ฤ3G๒ผ์่เg–ยgถภ๏ผ|žWฎพท๋lu[{†:Y฿ขอ็ยฅWbcษดXฬWfL‹qp,Fูช-'AJ!„ขv$H !๕ค[ลOตœ&—ม\ฆภื^:ว๋s ;ฦฝAŸูน๎&/๙ฒษแ)<†–_ใะ5"~~งปฆŒj˜ส—Mๆ2yฮฯ.๒๒ีYนย S฿ณz›;+A๊DtžO?{ฌ!ฯหžกN~jr‚.๑lฏ>วk๏๓:[฿โัๅฌn า๊uโิ5EกX6IไŠŒฬงxnxŠ—ฎิvฦŸ)!„Bˆฺ‘ %„ิg๚ฮ•ุึ!NƒูLž฿~๑วฆโ ;ฦอ~>ตc]นฒษกั†ฆพฃฏ54•Hภ฿aเq่ธ CUฐm(˜&ณ™<็f921วl&Gยิ๗ฎ้acคจฉฯ4hz|E%|œ•๐๙‡ฯrt๒ึ\g[ปย์Œฐช5Hุใภกi( M‹๙\‹ณIล8\ฃ0%AJ!„ขv$H !๐งG‡ํ็วbL%ณusLbMjำ~งมL:ฯoฝx–“ั๙†ใๅ->๙๐z"~นR™—฿รฒ0]S่ x๐:Œ๋๛Lี=ฆŠฆI<[เฬ"G&็ˆฅrท5L}ฺ^6t„ฐc“qžุ{ผ!ฯห‡V-ใ_oฤ_ Ÿ้ลณŸบตืู=m<ิ฿ฮชึ&šNีนฆฮอ,๐ย๘๔{^*๘^IB!„จ RB,ไ‹๖T2ห‰่<Fc\Iคk~L฿ฟถ—8€฿ฉ3ฮ๓‡ฮpf:ัฐcผชต‰?ผžˆ฿MฆXๆ๕‰9ฬ๗ธฎฉDn|ฝฆŽj˜*˜&๓ู"—ๆyๅฺ์m S?ฐฎuํA,เ่ไO๎=ั็ๅ{ื๔๐/7 โw๊ฬค๓ๆ g8ป=ืูC}ํl๏ogEKอn†ฆbCL7ฝc3%H !„BิŽ)!„,ถ-&[2‰ฆฒœ‰-๐XŒ‹ณ‹5;ฆฌ๏ใ#๚๑9tbฉฟ~่ ็fvŒืถ๙ุ๖ut๘ค‹eŽผ ตDืฺ}nี=ฆ|N‡ฆb6…ฒI<[ไr<ษKWf˜N฿บ0ฅ( ?ธฎ—5m• ๕๚ตYžฺฒ!ฯห‡ืUยงฯกK็๘อCg83}{ฏณ๛ฺู3a0์'่rเะ5l{i_ฐสŒฉg/O๖+AJ!„ขv$H !,”lกก* –m“+U๖%:;ณภกฑ้š,•๛่ฦ>ผฎกMๅ๘สมำ\œ[lุ1iๆ—\K›ฯEชPโ่Tำผ5ฟƒ4Uกร๏ฦ๏4๐:>‡~}ชByiฟขEŽMลนบy฿aJS~`}kฺš0mx๕๊,Ÿ?ะ˜A๊‡6๔๓‘๕}x ้tŽฏ:อ๙™้ชสށ๎oง?ไงษU‰‰KณฆำyNว์žโยm รค„B!jG‚”Bไจฝ)าLgภƒฯกฃฉ7žไฯVbฦั่-์๙๘‘อƒ|฿š†ฮT*ห—ž?ลp<ีฐcผฅ3ฬ/>ธ†Vฏ‹dกฤฑษ๘๛ž!๕TUฉ.ๅ3p~งกุฏ(‘+pi.ษ๑hœ+ ผo๓”ฟ7cจ• ตชต ำฒy๙๊,_|TCž—nเรko„ฯ/<ลฅนไ๛NMe๗P'๗๗ถั๒p9ฎ๏ –/›LงsœŠ&ุ;2ลๅ[|\ค„B!jG‚”BPyส^gภรŽ๎๊ำ้๗เsี=nn,Ž'94>อแ๑in๗Oฯ:ฤ๗ฌ๎มญkL&ณ|แภIฦ๊`oซ๗j[w แ5ดx,ๆKœˆฦ)›ทgUU!ไv`ะไ!่บyฟ"‹…|ๅ\™œใ๊Bฯป SN]ใึ๕ฒข%€iูพ2ร—žnศ๓๒แ๓‹N12็รงะxdจ“{–ต2ะ์ฏฦDำ†\ฉฬt:ฯ‰hœg.Oฒ=$H !„BิŽ)!„ ค–{ศํ`็@„{–ตฒฌษS๙`|ำ๒ฏ…|‘หsI^Ÿ˜ใ๙ั(ำบ-ว๔SV๐]+ปq้‹>wเ$W2 ;ฦ๗๕ด๒๓๗ญฆูใd!_ไT,Aฉlึ๏ฉ(เ24ผ†Nฤ๏!่vเ\:—ฆลBฎศ่|Š—ฏอpm1๛ŽgLน ฏํeyK€ฒe๑ย๘4ฟq่LCž—฿บœ๏^ฝฌnยgภiฐk0ยฝm,k๒^ฟส–MฎT&–สqt*ฮแฉ๗}?HB!„จ RBมƒิกณ{(ยถฎ๚›}4นื—•,‹ล|‘๑Dšื'ๆุ7%S,฿าc๚™ปW๒+ปpjW3<ต๏“ษlรŽ๑C}ํฝซน$rEฮN/P(›wๆ—.]รm่t*3ฆœบŠยอ3ฆR›Œ3šHใ1ดท|=ฏฃคร• up,ฦoฝpถ!ฯKฝ†ฯ หมžกN๎๏mฅ+เล็ะัซ3ฆฒฅ2‹ŽNฦู7e*๕๎ RB!„ต#AJ!๘ึAj‰กU6_พwY+Cแภ๕˜PฒlR…‹^น:หมฑ๑lแ–ำฯปŠG—wโิ4ฎ,คyr฿ bฉ\รŽ๑ฮ~ๆ๎•ๆsE.ฬ.+šw๔–fL95ฎ&!—‡ฆข(Pบ)LŠฮ3Oแ|“0ๅw|บ^š”L‹ฃQพz๘\Cž—zŸM.ƒ๏ZนŒปบ[่n๒เ5t4ต๒๐Lฑฬตล,G'็x๚าไปพ๗$H !„BิŽ)!„เญƒิอ๎๋ie็@„กฐŸฐว‰SืP…’i‘.–˜Jf92็เh์}จ๙๛Vณg(‚กiŒ'R๊ฬf๒ ;ฦ,๏ไ'๏ZNะๅ ž-0O’.”ks0ีS†ชา๔rฟ1L-ๆKŒ%RŸšg8žฤฉฟ1L59+Aช/ไงdš์‰๒;/oศ๓า(แณ็ๆัๅlํ ำ๐โuhhŠBูฒIหL&+Q๘™หS,ๆ‹๏่5%H !„BิŽ)!„เฉ%wu…ู1aek€ฐว…Kืะ0ซณ6&“YNF2๗ใ๙…ึฐs ‚กฉŒฮงxb๏qๆoั์ซZ๘Ž]๘]ห 8 f3yฦi’๙RอหะU\šFw“ทซK๙,›ไMห2วiีงBn฿ทถ— ’i๒p”ฏฟ˜A๊แ3อฏ๎=^ืแsY“—=Cl้j&โ๗เฉฮ˜*›ฉB‰k‹^บ:ร‘(‹os}IB!„จ RBมปRK6FšyจฏuํAZฝ.††ชT–eK&ฑTŽ3ำ žqav๑]ฝ๖/=ธ–‡:ะU•‘x’ฯ๛ญhZค๒EฦiŽOอs~v๎€็z*˜&ฯ\šโ๗_ฝะ็ๅๆ๐96Ÿโณ >{C>๊dsg˜vŸ ๗7„ฉ๑Dš—ฎฮผๅnค„B!jG‚”B๐ƒิ’-v tฐพ#Tตq#LๅK&ณู็ฆx~,ฦษ่;zอm_วC}ํ่ชสๅน$Ÿ~๖(้bนaว๘๛ื๖๒ร๐;uฆำy&๋+H-14‡ฎฒฌ:cสกiจสยฦๆS วS฿JwภKม4๙ง‹แk—๒ผาƒkู฿ก-…ฯใ๏xษ[=l๖๓ศ๒N6Eši๓บp:ชeห&Y(1O๒๊ต9žป<๙MOฤ” %„BQ;ค„‚๗ค–๔…|์่๏`Sg3สฬบฆbY6๙ฒI<[เโ"Fข™Œฟๅk}โแ๕<ะ†ฆ*\œM๒ฉg’+™ ;ฦ?ธพฺะฯก3ฮqm1หbฎ~ร‡ฎ)่ี=ฆZฝ.œšVูcสฒษหธ งฆ’+›ร… ๘๕ฦ R{h๕฿>Ÿ;Fบะx3๑Vถ6ฑg0ย†ฅ0ฅkื๗KJŒฮงx๑Je)_ฉฆ$H !„BิŽ)!„เึฉ%~ดsWW ]>งก*ุ@กlฯŽ'ya|šฏฬ๐ญ~z็๎]ึŠฆ*\˜]ไOฅ๘ 3<ษG7๐แuฝxŒส ฉk‹’ 0GQบJo“—V_%Lฉ  ((€iูœŒอ๓๋ฯ0Ÿkผ=พnŸ—ๆ’|๒™cไJ;om{G†:YคีW S@ฑ๚ลั๙4๛Gขผ0>Mู4%H !„Bิ๊๏l RBq๋ƒิ’&—ƒƒ๎^ึBO“ฟำภจnŒ]4-นJ˜zmbŽ็Gcส7f@}vืF๎^ึŠฆภู้>๔Qฌ™#›๙พ5=ธส ฉซ R4GงฎัไฅอWYฆ6/™\š[ไต‰9Œฦ˜k ง!~jว๎๋น>?๙๔ัoZฺึˆ6t„xtykฺšn<ณz฿ลsŽNฦ๙ำใ;๔z^~ !„Bิเฯk RBq๛‚ิทกณg0ย]- 4๛hr90ิJ˜*Yษ|‰๑…สำ๖O‘)–yr๗&ถvท gฆ๘๘ำGzŒb๋r>ดzn]#–ฮqu!Mบะx3qL&่vฐต3|=.ฺPูLปXโฺB†ฃSq๖G"L>ฯอ,๒‰งPถ>8ยށVทiv;ph60ฮ๑Wงฦvวื>/?…B!๎< RBมํRKtUeว@๗๕ด2๖r9q๊jeๆFuำ์‰ล ฏ^›e[W ๋:B(ภฉX‚O>sดกว๘งทญเ;Wvใชฉ๑Dšlƒnา~e!อ๗ฎ้!์qbSูWJS”๋›iง‹%ฆ’YŽLฦy๚าd]?ต๎Wwoโฎj๘<;ณภว๙ฤฟ ่mใกพvVถ6แu่ฤณๆ๔๘ฮ?ผy๙ („Bq็IB๎\บู=หZู5ayุOณวY„Yน>ำฦPU<†Žeœˆฮ๓้g5๔์=ซxlE'NM#šส2žศ4์^Eษ,ญ่คร็&W2Kคq้ีฅ|ฺ๕0U&šส๒๚ฤ๛FขฤRนบ{/ฟถg3[ปย(ภ้X‚O4x๘|;๖ตำ๔ฯๆ9—%{B!„5"AJ!จMZrWW˜‡:XีฺDุSู„YS–~J+`DS9~m฿ ฦ้†ใw฿jŠ`hฑTŽฑDŠ|ƒ>50–ฮฑgจ“vŸ‹Tกฬ89ส™้ป;Y฿ข็ยm่่ชBูฒHหL%ณ›Šณ$ฦฤbฆnห็ูฬๆฮJ:K๐ฉxบ™บ••ญLหๆ๐•พ|๐๔ทอ}/AJ!„ขv$H !๕คBnO=ฒ™มๆ%ำโ๙ฑฟโู7]Uyธฟ๛zฺj๑r9q๊* PดlR…“‹^ฝ6วมฑณ™|M฿ำฏํูฬึฎ0 Kๅธ0ธAJQ6w6r;˜ฯ๙๚ห็Iๆ‹ธ ]ฟ–ฎ)ฌi ฒฆ-Hw“ท:cชฒ๙yพd2“ษs*–เ๙ัุ-บขฯก๓๙Goฬฤ{a|š฿8tๆๆพ— %„BQรฟฉ%H !Dฉ“งูL_ศOษ4ู7ๅw^:ฆžeญ์่`EK€fงฆกช eำ"U,1•ฬql2ฮ๓c1&j๔Dทฯ?บ…M‘fฆำ9.4๐ )CSู t9˜ฯ๘—ฯ“+™84๕}ฝๆ๒p€๕!–Uร”ฎU–๒ๅKefณฮN'ุ;ฝeaชษe๐๙Gถ0X‰wp,ฦoฝp๖ๆพ— %„BQ;ค„‚๚ Rํ>7O๎ูD_ะGั4y๖๒ฟ๛ส…ทบญ]av๔wฐชต‰ฐื…KืะชOt+3•ฬq26ฯ‘(cw๘‰n_|l+;Bุ4~rฺ๋C4น โู_=|ำฒัTๅ}ฟถฎ* …lŠ4ำUฤๆง+ฮd๒œŸY`๏p”3ำ‰๗๕ฝš•๐9ะ์งdZ๒ีร็พm๎{ RB!„ต#AJ!จฟ ี้๗๐ฤ๎๔}L“ง/M๒_^ฝ๘Žฟ~}Gˆ‡๚ฺY฿ขอ๋ยmhจJeXถd2“ฮq:ถภมฑ[ฟ ์[ฒพ๔๘Vึท‡ฐ€ูtŽ๓ ค|NีmANƒนL฿>|…สRพ[ฦ†ญMlŠTfLy—žฎhCพl2—ษsvฆrOอฟงoัโu๑ิžMืgโํ‰๒Ÿ฿b&)!„Bˆฺ‘ %„ิ_๊n๒๒ฤฎ,k๒’/›ำล ่๕K๏๚u›์Œฐก#D‡฿ƒืกก) fuใ์นls๏3jผชข๐•วทฒถ=ˆi7~jr;Xูภ๏4˜อไ๙ํฯขฉ๊m๙^ฆmณบ5ศ๚๖ ฝ!พj˜ฒl(”Mๆฒyฮอ,๒ยXŒ#“๑w๕ฺK3๑zƒ>Jฆษ3—ง๘ฝw0๏ƒB‚”B!DํHB๊/H๕†||f็บ^re“8?9z๙ฝฟ^ะวรํlŽ„้ xฎ๏Oดด l>Wเา\’#Q^Ÿ˜ปๅ๏วะTพุVVท5aZv%„M/4์๕า์q2๖ใwฬค๓|๕๐น[ฒ\๏ญุถอPK€ อ๔…|n SK็๐ย์"Fข๏8Lu<<ฑ๋ฝฯฤktค„B!jG‚”BPAj ูฯงwn ำ๏!W6๙฿็ฎ๐็วF๗๋ถ๛์่`[w ]>งCUฐBูb>W`8žไ๐•Mcข฿nCใ‹neekำฒ‰g œmเ ี๊sั๒ใw๊LWƒ”~›ƒิำถ๙ฺูฆ7่ล๏rเะTlฆP6‰g \œKฒox๊mริฒ&/Ÿฝ3๑•)!„Bˆฺ‘ %„ิ_Zเ“o โw“+•๙ณW๘o'Foู๋๛{†"JOะKภi W—œ•,‹…\‘แx’#“q๖Dษ—อ๗๕|Nƒ/<ฒ…ๅ-•งนล3…;ฒwีําpำ๔แs่ฤR9พ๖า๙;ค–M‹กฐŸญ]-๔VฯกQ}ส_%Lน0ปภ‹ใ3ผtuๆ[พฦญž‰ืh$H !„BิŽ)!„ ‚ิชึ&>๐z"~7™b™ฟ>=ฮ_žปๅ฿วmh์ŒpWW Ca?M.ฦMa*U(1žH๓๚ฤ{‡งHห๏้๛]>๗่f›”L‹™LŽKณษ†ฝ^บš<,k๒โ1tb้_{้๕qปำŠฆษ๒p#!๚C~š\7โbั4™ฯน8ปศแ+3ผxe†›๏ใLผs๎*vl๘ๆพ— %„BQ;ค„‚๚ Rkƒ|l๛::|nาล2yrŒฟ93~พŸฎ*l๏๏เž6†ย~Bn'N]EŠ–MบPbb1รks‹1“ฮฟซืo๑8๙ต=›้oฎ<อm*•c4žjุ๋ฅ'่ฅ+เมm่DSY๓ห็ฏG Z)”Lร~6Fš ๛ บšŠmWยT"_dx.ลก๑/Žฯ`ูvu&z"~ฯm™‰W๏$H !„BิŽ)!„ ‚ิ†Žฟะ:ฺ|.R…2ํฤ๛ี;๒ฝ๏Yึสฮ–ท{œ85 UU(›้b™ษd–ใSqžqm1๓Ž^s้in}AEำไ๊B†ซ ™†ฝ^๚š}DบฦT*หื_:ฎฉuqlน’IoะหหZh๖ฌ๎1/[$๒Fโ)๖DIไŠืรgถt๛fโี+ RB!„ต#AJ!จฟ ตนณ™๘เZZฝ.R…vl„ธpํŽร–ฎ0;๚;XฺDุใฤe่hJeSํLัd*™ๅ๔t‚#QF็฿zถำ7>อm,‘fj1ฐืห`ุO›ฯ[ื˜Hf๘W.ิlษ›ษ^S- „•0ฅณฒOุt:GOะG“ห ],๓Wงฦ๘๋ำใ฿6๗ฝ)!„Bˆฺ‘ %„ิ_ฺฺๆXK‹ืIฒPโOŽ\ๆ้K“59–uํ!ถ๗ทณฎ=Dปฯ…ะPหถษ–Lfา9Nว84{ำ'็๕ฝ|v็FบซOsปO2๛.—ี“ก–m^.]cb1ร๏ฝzกๆK๖Lถdา๔ฒฅ+ฬP8p}ฦ”ข@ูฒัUUศ—L฿ใ#ทuihฝ‘ %„BQ;ค„‚๚ R๗,kๅ฿฿ฟšฐวษBพศฟ~™ฝรS5=ฆf?ป#l่๑{๐:44Eมด!_*3—-p~v‘ƒฃ1ŽMล฿๐ต!Ÿน‘ฎ@e๓์๓ณ ,d‹ {ฝ …ด๛]85ซ‹~• ืŸpWฏ2ล2}!/#aVถนช๛„)ชjPผ IDAT `ู6W2ู+ตใฦๆูงงค ๅ†ฝ^ร:ชA๊สBš๒๊ลบRKR…M๎Yึสฺ๖aฅ๚•-‹๙l‘๑…4‡ฦb›ฆP6?ฐ๗ฝ)!„Bˆฺ‘ %„ิ_ฺ฿ฮฯณАA"Wไw_นภ‹ใำu5fํ>7๗ทณญป…๎&/>งCUฐBู"‘+p9žไฅ+3Lง๓|l๛:"~7™b™ฃSqJๅฦ3๖๑ป14๑Dš?|ญq‚ิ’Tกฤถ๎>ฒพงฎaุ6( Eำ"™/2–Hsx|šƒcำdKๅ}/AJ!„ขv$H !๕คv F๘7Vt;˜ฯ๙ฯ/ใๅซณu9v>งม#Cถuทา๔pื๗S*Y•อณg2yzƒ^ฮสๆูฏึ้{yงnRc๓)๐ต‹8tญแ‡ฎ*}•ฅกEห&S(แ24œš†ข@ษฒIๅ‹Œฬงx}bŽฝรัT˜’ %„BQ;ค„‚๚ R u๒“–t9ˆg |ํ๐น๋ห฿๊•Kืุ5แฎฎ0ห[4U7ฯถํส“๙–6ฯ.”M๑ยงัฐืหPK€ŸCSO๑Gฏ_ฤก5^r๊?w๏*šซ3๑๖Ot;Xำ$์q~S˜บฒแีkณ<7ฯKWfฺุfGซ‚ดxธt (Z6ฉB‰k ^พ:รั(‹๙Rร๗ค„B!jG‚”BPA๊Cซ–๑ฏท โwฬf๒งฯr|jพแฦ๕๎๎v FX฿ขลใDฉFฉฒe“.–ศห,ไ‹,ไŠ 5ใๆๆ uy.ษ=r g.ู๓; อ+บฬg |ํฅ๓ผzํฦrส‘f๖ EXีฺD‹ว…KืPU…’iUยิb†Wฎฮ๒XŒ๙lกแฟ)!„Bˆฺ‘ %„ิ_๚5=หMƒ๘:3้<ฟ๙ยNล ;พjำ ูPู<ฦฒAU*K๙2E“™Lމล,ูR‡Z›ƒUƒ”ฆ*\œM๒ฦฉซ w^Bn?yื š\๑lฏ>ว๋฿bi่ฦH3ป#ฌim"์ญ„)ญบ”/](qe!รัษ9๖D‰7P˜’ %„BQ;ค„‚๚ R^ืหoภ็ะ‰ฅsฦก3œ^hุ๑}จฏŸฝwaทƒ‚i‘ศ๑:t<††ช(XถMถd2“ฮse!iู(u~†ย:n4Uแย์"ztธ!gHตz]ุึ!ี™xฟ}๘วbi่ฦH3๛ฺYืขตฆTๅฦŒทk ŽNลy๚โ$ ๙bฟ RB!„ต#AJ!จฟ ๕C๚๙ศ๚>ผh*วWžๆย์bรŽ๏ฮ~ๆ๎{‰%๐:tZฝ.Bn'^‡†ฆ(˜6ไKeโูW3M หชฟ฿SCแM4ฮอ,๒gว†q5`๊๐ป๙ัอ7–†ๆ g9}๛ฅกkฺ‚์่`}Gˆ6Ÿw5L•,›Lฑฬd2หkณ์Ž2›ษืํ๛— %„BQ;ค„๘่_ฒ็๊่ƒ๓G7 ๐k{q• ๕ๅƒงธ4—lุ๑ฦงŽ%า”M CS นx^Cวmh่šŠeูL“xถภไb–|ูคdZu๓~†ย~:›ผจภน™ุ.ฃ๑‚Tw“‡nฌ, ฎ. =.–†ฎjmb๗`„u!ฺฝ.†ŽVc*],3•ฬrdrŽ#1ฆRูบ{ค„B!jG‚”BTข‚}t2ฮพแh]|pั-ƒ|๏๊†ฮT*หœbd>ีฐใ{๓S็ณEฎ.ฆ)šํฦพKM.Cรm่ธ ‡ช`…ฒE"W`2™EQrjซkจ%@gภƒ œžN๐฿OŒ6ไ’ฝพฺะ}i่ฏ<รน™wฟ4tEK€=C•S7…)ำฒศหL,f96gH”ษd„) RB!„ต#AJ!€ฒeู™b™ฉd๎๚็k‹™šฯOl]ฮ‡V/รญkL$3|แภ)ฦ้†฿›Ÿธ/26Ÿฦดmt๕;Eู6\n]รkธFu“๓’Uyฒ[ถT&[,Mๅ0kดœoy5H)ภฉX‚ฟ:5†ก5ฆๆƒa??ธฎQ R_>xš‹๏ci่P8ภฎม6Eši๓นฏ๏fZ6ูRe)฿‰่<ฯ^žbชย”)!„Bˆฺ‘ %„T‚TeฃสS฿&“ND็ู7\›0๕ำV๐+ปq้ื3|nษšฒ๗๋ๆง.ๆK ว“(Š‚ชผY(ฐ๑ป šœ<†ŽำPo„)ำ"S*“+™ค‹%ขษ_ฮทคNF็๙ณWะฅแฮหส–&พmOuih–/<อๅ[ฐ4ด?ไcฯP'"!"~ฯ7…ฉX*วัฉ8{‡ฃLิ๐บ– %„BQ;ค„ธ8ทhw๘8{V๒๘Š.œšฦ•…4Oํ?Y3Jซ\฿w}iุbพศp<…ฆพ}ภ)[6>‡Nุใฌ,ใำTšŠBeํlฉLพd’*–ˆฅrไKๆy?ห[t<ุภ๑ฉ8็U” Rkฺ‚‹5=ธuฉT–/8ล่-\ฺ๒ฑs0ยๆH3‘€ฯ–๒™Lงsี๐;ลX fJB!„จ RBิ฿ถ๗ vฒ1าLgภsำS฿์7|p~nxŠ+wเƒ๓}๏*]‰Cำ_H๓ไLงs ;พ?ผฑŸจ. [,y‡AjIูดqญ^Cรกi84UU(›ึ๕ูR‹๙"‰\‘Lฑ|[฿ฯŠ๊ )8:็๏ฯ7fZ฿zราะฯ8u[ฎ๏ ƒ6w6ำแwใu่hช๚†S'ฃ๓์‰ัฝา$H !„BิŽ)!„“gm€ž —]6w†้ T>8๋ชJน๚มy&ใd4มพ‘)†ใท๏ƒ๓ฟฟ5ป#šฦx"ลฯg.[hุ๑‘อƒ|฿šสาฐ๗ค–”Mงฎ๖ธ๐:tœšŠCW฿g39ฎ-fษ•สื—๙j+Zt๚=Xภ‘‰9ยต†\ฒท)า†ฅกOํ?y[—ะu๚=์Yakg ๗๕S– นj˜:Kฐo$สp๖?UR‚”B!DํHBnฉ%]ป‡*œ#7^CGื*3:๎ฤ็_|p-;๚;04•‘๙$O8๛7ftไซ3:Nลr~ๆp•ํ๋xฐฏ]Uธ4—ไำฯปํ๛"N7oาžศธฒแVฎp[ Sอ'>‡KW๑Tใ†mไห&๓ู‹Y๒e๓}=•OS†n R/]ญ)ทัxA๊พžึบXฺ๎sณkฐƒmญt๘บฆbY6นฒษL:วู™๖ G97ณpหพฏ)!„Bˆฺ‘ %„ผ}บ๙ƒ๓ฮถuท\S7ฯ่˜อ83x฿œ?นc๗๗ดขฉ f“|๊™ฃไหfรŽ๏า&ํ†V™!uๅอz3MN‡†หะ๑:FuฟชBู"‘/0น˜EUน"๏๖๗`%H๙้ x([6‡ฏฬ๐๗็ฏแu่ w^์kฟพ4tt>ลgŸ;Vำฅกa“ƒ๎YึJW“Ÿร@W์๊lทสŒฉฯฦ8Kผ๏๏'AJ!„ขv$H !๏๑๔ั†฿m_วC}•Mฺ๏tZRถlผทกใะTšŠข(ืรTพฆฆS9rฅoฝDากkt<๔…*A๊ภh”ธ0AศํhจsbZ6.๏ไ64Uแโl’Oึ้าะ หมรืำJOะGภi`ด?ุ\ฆภลูE๖D฿U˜’ %„BQ;ค„‚๗คnเผk0ยo>ฃใย์"๛Fฆ8>๕ๆ3ฆ>๗ศf6w†Q€“ฑŸzฆฑƒิ'^=|ฬg‹Œ/คั๏pZR6m\†Fซทฆœš†CSQU…ฒi‘/›ค %๓Eนโ7อrฟ›พŸ’iฒw$ส?^˜ ์q6ิ9)™฿ตช๛ KC?๑ฬั๗ตแ๛ํๆs่์Œ๐@O=A/~—‡ช`S ฟูf94>อซืf฿๖๕$H !„BิŽ)!„เึฉ%M.ƒ‡๛;ธฟทž&/—ใ]อ่๘ยฃ[ุiเDtžฯ<{ฌกว๗ๆ=ฑๆณEฦitMฉ้1•Mงฎ๖ธ๐:tœšŠCWQ•สำ3E“ูLމล,นฒ‰^…eht<๔}M“g.O๑ฯ'h๑บ๊œM‹๏YฝŒป—ตข)pvz?}ซ.p: U6?๏ UfL้ีe˜Esi)฿"/]™แ๐•™7} RB!„ต#AJ!ธ๕Aj‰วะู=แž6zƒสŒ)Mลถo|p>7ณศ ฿0ฃใKmeCG86็‰ฝวz|o+‘+0–ศ`ิ8H-)›6บฆ๖8๑.CรuS˜ส•*{%า85…Nฟ› ‚i๒๔ฅI๙โ$mพฦ R๙ฒษ‡ื๖ฒตปฒ4๔ฬ๔๚HCฝ—ฎฑgจ“m- …•๐[รญhšฬ็Š\žKrh|šรใำ|ใM.AJ!„ขv$H !ท/H-q:{ช3:๚฿bFวแ+3ผ|e†/?~ฺ๋ƒXภั‰9žwขกว๗ษ=›ธซซ˜ฯฏฃ ตคlฺ( ดTgLน ทกกฉ*ฆU™ู–ศศหZ<.๒e“บ8มำ—&้๐ป๊œไJe>ฒพŸ-]•ฅกงb >ู KC]บฦ๖v๊kง/ไ#่rเะิ๊R>‹Dฎภp<ล‘(/_นฆ$H !„BิŽ)!„เ๖ฉ›?8๏ŠpOw+ƒีŽ๊SK3:†ใIzƒ>บ›<˜6ผvm–ฯํ?ูะใ{๓žX๓นW™š/ู{3Kaชูใฤ็0p้*CGฏ.น,”-tUAืTŠe“u๎*ฯ\šค3เiจs’)–๙่ฆ6U—†žŒฮ๓้_jh*๗wฐฝฏfM.GeVP0-ๆณŽLฦ๙฿็ฎ0ฑ˜• %„BQCค„‚;ค–8uํ}ํl๏ึ3:TUมก*”-›—ฎฮ๐…งz|ฟ๐่6Ešฑฉ,ูปฒฉูฆๆ๏Vภ้ภ๋ะp:CวPEAlๆฺb–ฟ=s…k‹†ึ0็$],๑#›‡ุX]z|*ฮgŸ;ธŸ Meว@๔ด1ะ์'่v`จ•๛k:ใžใŸ/MJB!„จ! RBมRKี4ฃรกฉ7‚0“ฮ๑วฏ_ๆะXŒF‰ๅวทฒพ=t=H]]ศ 5Hฐmธ \บ†ฯat(ีMฮห–E<[`l>อ้X‚ห๑$FuVN=KJ๘ึก๋็ๅศไO๎=๑บฏuUaว@„{–ตฐผ%€วะ‰g ™+<7<%AJ!„ข†$H !ต RKี๗๗ด1๖ำ๊uกVƒ‡iูLgr\žK๒๒ีYล([๓ณ[Uพ๒๘Vึถ1mHd \[lฌ ตฤฒlŠฆลๆฮf\†^๙m(™ฉB‰ซ‹NF ฯ%กŽ฿bฒPโ'๏Zฮฺถส^eฏ_›ๅฉ_๚ฆ์๛;่ z‰g œŠอห’=!„BˆZ&AJ!jค–่ชยwฌ์ๆวถ แsืgI-…ล|‘‘๙/ŽOsplšฒeีุ๊ชสW฿ส๊ถ&Lห&‘+2ฑ˜Amภ Mๅุiฆร๏ฦฒm2E‡ฆเิ5EกdZค %&“YNO'ธ8“คh™ืcฝHJิถฌikยดแีซณ|ภษoซ๛^‚”B!DํHB๊'H4ป<๕ศf†ย~l f%fผ9๓bพศ่|šฃQ^Ÿฎ๋S.]ใKmeekำฒ™ฯ™Lfiะล\ฆภบŽ >7้b™รWfะU…•-M„=N\บ†ช*”M‹LฉฬT2ห‰่<วฆโห~งQ๏#](๑ำwฏdU๕ผผ|u–/>๊๊พ— %„BQ;ค„‚๚ R-^OํูD_ศOษ49;ณHฎTf0์'ไrโิU hZ,Tริ‹Wฆ98ฃhึ฿Œ)ŸC็ neyK€ฒe1Ÿ+MๆP4H-ไŠฌn า๎s‘*”929‡Kื๐์yt%w}็OํUwืฺRki๕ฆnป๏ฦX†8!&ยd&v ž $$มa˜็<99Cกำฃ์CN†yf’ฦ6  ุํ}มฝช7ต๖ๅ๎ทถ_ี๓วฝ’ป—n[Rj}^็p’CิาญบUาอ๛~฿าUคu iCCJWกซ2dIZZE5Yฎโนษ<›ํ‰ศรTล๕๑๋1ุž„๘—Sำ๘โรฯฎฉ๛žAŠˆˆˆ(: RDDhฎ ต.eแ๗^‰ น!๐ภัqำ gp๙บ,ฎํiวึถ Z,บข@’๊ณ‹๒ถ‹ใs%<:6‹๏Ÿ€ใ‹ฆ9ทYSว็nฟ ›2๐D€…šƒษr-ถืJล๕1ุžAGาDษ๑pdถO05พกศฺ“’šSS`žฆjžภLลฦ๓Syป๗*llMร๕'าMWโคl_`sk}๐|ั๑plฎOชฒ๔5พ!I๕cO้,Mฅ)Pd"a๛sU‡gŠxไฬ f*๖ช‡)๘ภ ƒุZ…Ÿ˜ฤ๐๙5u฿3HE‡AŠˆอค๚sI|jฯ่อ&a๛็๐:6ŽŽคน๔5%วCWฺย }ูEz}จ67Qด]œสW๐ร“S๘่$jžู๑tฆLUุุ’‚'fชf*vlฏ?1Kก=i `{8ฑP‚+่_็}ญฅ0ฅยTXš M‘†!_`ฎ๊เ่\ Žอเlกบjaส๑~๚mKก๐{ฃ๘“๙ษšบ๏คˆˆˆˆขร ED„ๆ R๘ไž+ะ“I ๆ ๏Nใ๛'ฆะ–0~๊kKއŽค‰7m่ฤถ๖ ZCต%I‚+”l'๓๋ฉi<|b%ว[๕ใYŸNเำท] น\!0]ฑ1Wuโ{ฑ„๕hุš0ท]œZจภ4Ezญ†ฌก#ฉ+05 Uถ8จฏoป<:[ฤ3“๓81_†ฉ)+zŽ/๐มถc  :6/่…5u฿3HE‡AŠˆอคถดฅ๑๛Cปฑ>@อ๓๑?r?:=ƒKลSr60 ŒQŸ/•ิT$tš\S^P‚โษ…2ž™\ภัูโRดZnž๐มถ7ซ์O|hM๗ RDDDD~ฎf""jฎ 5ุžม}ท๎FwฺBี๓๑?ž;…วฯฮ!cพ๖Vฎล0uMO.๏ฬข=aย8'L•ง๓e[จไxhต \฿ืŽ9ด'อ๓VL•c… ~tz฿=>ผํฎุ๑œปโห๑&ส5V๐็ญ†\ 9KGฎ>?q‘=j‰/B$tํ –ฆภP่Š I’เ‰eวรxฉŠg'๓84S€+dIzรว`๛ฟyำeKณส๙ะลcGืิ}ฯ EDDD)""4Wฺน.‡฿}ห.ฌK™(9>้Qš) ฉซฝJއฌฉใฆ\™Cวb˜’%๘Kซp*xไฬ,FF'0ปณถตg๑๑[wa}ฦBอ˜(UQŒ`–ีrhI!g๊(ิ๊3บ‚ฐTฝ7ย! UFGาDBWก+๕0ฅ4ซŠ็cผXลำ“๓x์\?xCะkžผใผYeร[S๗=ƒQtคˆˆะ\A๊Š๎V|์อ;ะ™2Qr<อSฃ8>W‚๕†\—CรMุฑ๎ลSŠTj\ษ๕p&_มcg็๐ใ˜]ฦงเ]™ร๏ฝe'บาชžภxฑŠฒ๏ ตฑ%ฌฉ!_sq2_^ึ๏ํ‹บ*ฃ-a ฉฉ0T†*C–$aˆj#๊=7™วฃcณจy๋ Sืรวnูyฌฒฟ~๒๘šบ๏คˆˆˆˆขร ED„ๆ RWฏoรoฝ๙rt$M๙ฤ1Œชะ—aธ๕b˜บฎทปบZะ™4aj*ไF˜*ปฦ UwVู฿>5Š๏'งืิ}ฯ EDDD)""4Wบuc>xร6ดX:ๆk.๔ว/ภ๑W'เ”š"ใฦพ\ูŠui MYš[ดฆžš˜วGว/hลิ-๋๐กF`+;ฺไ•@ IDAT>Nๆห๐ƒ๘)SUะ—M"กฉ(:๕RRDฏ% ดQ฿ฦ—ิT$tZckง(4f\=;น€ฃsลฅmŸsUYSรoฟyวyณสฯกฑ5u฿3HE‡AŠˆอคn๗_7ˆœฅcพ๊เห?>ด๊+ŠJŽE–pS'ฎ่jAw&ฑฆDข๊๙˜,ี๐ฤ๘<<6ŽฑBๅฟืะฆ.๚๕๕ภVr}œ˜/!ˆ๑฿ž„ฆข'“@BSQp<œ\แRB!R††S‡ฅฉ0Tyiพ'”\c… žŸว 3yฬUฌK™K[) ถ‡ลทœ]S๗=ƒQtคˆˆะ\A๊Žญ๋๑kื"kj˜ซ:๘ฏ?:ูŠขล0uCoฎ\฿Š๕๓โV>ฉr OMฬใ;วฦqโež8ทwหzผ๏บญศ™:Jއั๙2Bฤ๗oOJืฐ>mมาTฃ๓eHRsผ6_„H่ ฺ&,Mก*ะ’TŸ Vv<Œ—ชx์์๒5ฟtๅ&ด5f•ํ;x_S๗=ƒQtคˆˆะ\A๊ฮmฝธ๗š-ศf*6พใCAด/ฏไxะื๖ถใช๎Vtฅ-$uŠ,Ÿทb๊้‰y|๗๘Žฯฟ8่๛mƒ=๘ีkถ"kjซ>|%คu ™,UAม๑pbพิ4Aj‘/BชŒŽค‰„ฎBW๊a๊™`EวC{ย€ฉ*Xจน๘ณGใแ“k๊พg""""Šƒš+Hฝ๓ฒ>๒U›‘^ R?:ั$ฟซƒ0„.+ุั•ลฎuญXŸฑ–VL!P๓|L”jxfr฿9VS?ปฝ๗\]lEวร๑นๆ 8#k๊่JY0Uวล‰ˆ†š__„ะUm IM…ก*0Tฒ$! Y Iฐ=ฟz™k๊พg""""Šƒš+HŽ~ป+6#mจ˜*ืWH5ใ๏jM‘qyg—wถ 7›@r)L…จySeฯLฮC!๎ฺุƒดกขไx8:[„,วทHต˜::ฯ RMดe๏•๘"„"KhOH4ยิโ๛abบbใเุ,พb OMฬฏ‰๛žAŠˆˆˆ(: RDDhฎ u๗ฎผg๗Fคt“ๅพฃCM}๎ Eฦ`G;ืๅะ›M"uฮVพš็รา†M–Ph)%ฦAชี2ะ™2a( vc…TLว! Ckฌ๔2!5^bHœซ:8<[ภ๗ŽOเฑณs—๔}ฯ EDDD)""4W๚ล+6โ๎H๊*&J5|๙ว‡‡ก+2ถถgฐปซ=™Rบ M‘๋ซปัร๖N,”Pv|จJ<ฃT{ยDGา€ฎฤg…ิK๙ข ฏ๏๋€ฉ)รAB‘๋๏—ใ ฬU]Ÿ/โ๛'ฆ๐ร“Sธ?-0HE‡AŠˆอค•›qืŽ~XšŠ‰R_๑aฤiA‘"I์ศโส๎ฌฯ$5๔๓ถ†EวรLล†/ยุ…ฉŽค‰๖„MQPlากๆยB ถg14T]“ๅrฆ^_อฆศWXจน86Wฤฃcณ9>G—ฬ}ฯ EDDD)""4Wบ๗๊-๘นห๛aฉ ฮซ๘ณGAŽa๑ร:ฒx๛`:“๕ญa!„pEว(ปๆช\?ˆM˜๊LZhKะล˜mู;ถดฅ‘648~€C3(ฒ„ดก!khH่*4นฆผ @ั๖p2_ฦมฑYฆ›ฮซxfb฿ภ‰…rlฮƒQtคˆˆะ\A๊บ้2พฅšขเไB~๐๐า,Ÿธ™ฏ:๘ูํฝธm๓โ๑”๐ง?>KSQq}์๊jมญh„ฉ๚S๙๊3‹ฟพ•oฎ๊ ๆ‰ฆ S๋ำ ดX๕AํEวํPsU–ฑฉ%ซคž™ZXฺš๗r|BWdด% $tฆชภPeศ’„ Q๕ฆJ5<;ต€๏Ÿ˜ยOฆ๓Mคˆˆˆˆขร EDเ๖}ไ%ูfx-yำๅx๋ๆnhŠŒ๓%|ํเ‘ุฎ*ุ.~v{†6vASdŸ/โฯ~|I]]๚WุึžมฎฎlnM#m๊ะd้œ0 ๊๙˜ญฺจนั‡ฉžL9ณคJއั˜ฎา-iXชาุฒทpAื™/Bศฒ„Žค„ฆยTUXš E’ ยถ'0Su๐ยtŸ˜ฤ“ใ๓M{คˆˆˆˆขร ED`hx$'๎G•:L๖›wเึsฮพƒG_uๅJ3+ปฑญทl\U–qtถˆฏ{0HE‡AŠˆ่e P…|ฟ,แžีูฟu8Gf‹ุ๘11 RŽ/๐ฮห๚pc_Yยก™พ๒ศadM‚ํฆึ4ฎ^฿†ญ)dM}i––ิรTล๕ฑPsPv}จซT…๚ฒIdM€ผํโtพหR)]Co6CQP๕|™-.หqd  Mตฆืฎ+ไk.Žฮ๑ุุ,พ;: ว‘ž)"""ข่0HฝŠ(ยิ'†vใฆฮ_>~ บชฤ๒๙A€wl๏ร๕}P$เ๙ฉ<พ๚่ดX๚ุิ–ฦ๎ฎ ถg]ฺส๗b˜ชy๕แ็ืฟจmgฏG6‰L#Hอื\œ-Vb๙d =™4EAอ๓qxถ๐บWHฝTึฟฟฉสH้บz^L,ฺNๅห886‹‡Žฃ์๚‘œ)"""ข่0H]€กแz ธuฅึ์น7๔ืฮOฆ ๘›'วvห^†x็๖>\ ภณS ุw๐Z,ใขฟWล๓ฑ1—ย5=mุา–A‹ฅŸท•ฯjžภlี^ัSนิา–รนชƒ‰R5–๏MฮิัN@Sไ๚ ฉ™ไe>g"‘าUไ, Mก*ะ7Qr<œ-T๐ศ™YŒœ˜ฤlล^๋“AŠˆˆˆ(2 RDDa๏พCฒ,฿ SŸนํJ\ภ๓ำyํSฃฑj?wYฎZ฿ ภำ“ ๘oEฮิ_๗๗ซธ>zณ ิ฿‰MญiดX๚า–F7เxj~}ลิJ„ฉ  ˜ญุ˜,ืb๙พดZึฅ,hŠŒŠ็แศLqลV—๙"„ฅ)hOš็‡)I‚/”\ใลž8;‡‘“+ฌฮช3)"""ข่0Hฝ+ฆp๏Uธฆงpž\ภืŸ=UŽ๏ ฉปvlภ•ญ<51ฟzโุอz-ฯว†\ื๖ดcK[นฦV>Iช?ฑฏโ๚๕x>JŽทlฑe1Hฆห5L—ํXฮjKิƒ”*หจธŽฬW|ปฃ/BชŒŽค‰„ฆBo„)EDขโ๚/ึ๐๔ไช๎๋S2$lhI!mจ!0^จbฎj/๛์ฅีฐ.eก=a@‘%”GๆV/H-๒EYฺf#Lฉฐ4Š$A„!lO`ถ๊เ'ำ๕0๕ไ๘ฒ|)"""ข่0H-ฃๅS๙mืœทข่Ÿล7H9พภ/_ฝ—wf!Bเ‘ำ3๘ฦ๓งิี๛™%วรบ”…7m่ฤึถ ฺ: U$IpE€ฒใกๆีท๓•]ขถษ’„\ )C…BŒช˜ฏ9+พีm%tฅhKP$ ไ๘8:[„ชDsพ!K@kย@Rื`ฉ ,Mชศ‚ถ/0_spdถˆ๏Ÿภมฑูe๙น RDDDDัa""Zท๏เฃpฟ$#{Qฟ”% _|๛5็ญ(๚ๆแฑุžGธ๗๊-ุ‘B๋้ำ งai๊Š์’ใก+mแฦพ ถgัšะa( dฉ„ทช๋ก์๚จy%วป 0ฅH6œคNๅ+ศ๎ชฏ,zฃB=้Zd%ืรัูbS<อQ‚„ฌฉ!กฉ05 M…&K8~€๙šƒcsE๐ไ4~pr ม๘ร EDDDแ็>)"ข•14<’“๗ฃJ€^h˜Rd _|๛ตK+Š=3ƒGฮฦ๖ธBเWฎูŠม๖, ภONแ[GฮยT•U{ ‹aฺ๊žv\ึ™E[ย€S^#LU\5_ hฟz˜R% -)คt ~เฤBEƒฆฤ,H…@_6‰œฅCPt<›+5ีq„2F=LYš‚คฆ. ๗๗‚๙š‹ฃsE<~v฿=>3คˆˆˆˆขร EDดย.&LŠŒ/ผl๏ศB!~tzํฑปBเ}ืbs[~เแัI1‰้ฒš฿“AŠˆˆˆ(: RDDซlh๘ภ€*ไ๛_.Lฅ Ÿฟjlmฏฏ(๚ม‰)Œœ˜Œํฑz"ภฎ฿†-)ธBเกc๘แฉฉฅญWQ*9ฒฆŽ›7t6ถ๒™ฐTฒ,มo„ฉ๚S๙๒ถ ItEF.…„ฆย‡f ฐ}cท .‡ล •3u„ ถ‹“ ๅX g๗EKSะž4—ย”&หK๏[ู๕qถXล“ใsฤ™BๅฟƒQtคˆˆ"๒ra*k๊๘Waskž๐๐‰IเไTlั>xร6lศฅเoว#c3Pคๆ ‹+ฆฎ๋mรฮu-hOึWLษเ!jž…š‹’ใกโ๙ุั™ƒีRฯOเ ฑช3ฑ–รนA*Pจน8•/ว๊iพaจ2ฺ“&’š ]‘กซ  aˆŠ+0^ฌโ™ษy|otฃ๓ฅŸ๚ RDDDDัa""Šุร^‰ ทถ% |v๏Uุุุโ๖ใ๘ืำำฑ=6๘เ ั—Mย๖พyx OŽฯA’š/|”Cว }ํุฑ.‡ฮ”u^˜*ปfส6:’&ฒฆG<;™‡˜Zผ‚”„ุุ’B‹ฅC„@พๆเLพ9fO ๊aJSdด% $u†ชภTeศ’„ Q๕ฆห5<7•วร'&๑T~้฿2HE‡AŠˆจI์w`จ+“ธฎบuq‹ƒว&๐ศ™™ุ“C|่†m่อ$Q๓๙…3xvjกฉ_sษ๑ิUุื]-X—ฒฮส'Kาาฃ3๕ี^–ฯR-–„ศ.ฮชˆaZโ‹’t$M$uฆชยาd(’ถ็cถ๊เ…™ฤใs RDDDDb""j2ว็KCนิŽท~๛ศ8;;฿ƒ ธ ๋ำ ิ<๋…ำ๘ษt!/ฝไxฐ4o๊๏ภฎฎt&MXšบดญ-0WฑqถTยz|‹‹—ฉ๙š‹๑b’๛g1LีWLiฐT–ฆ@UdAGฬU-โ;วฦ๗|mืŒ๐ทั๊c""jRืื7ษNNmHZ<ศ๘เ ฑ>cกโ๚๘ฦ๓งpdถซc(9LMม}ธฎท=™ไFน ย๚Vพš ๆ๙(ุn,ยิ‹Aส€˜ฏ:˜(ี.‰ u๕'!cjHh ,M…ฅฉะe !ว0Wต๗๔f“#mCDDDมg5)"ขๆvว๏Mฺg{2V_ย”,บa;บาสฎ|๖$Žฟฬp้8(9ึฅ,ๆ›.Cช๑>, AจyUฯGพๆ"@๓}RนFšญุ˜ฎุ—์=ศ,MERS‘ะจฒŒแU–G๘[†ˆˆˆh๕1Hลฤb˜ฺิš๊ำ9ฏY‘d|่ฦmX—2Qr|รณ'prก๗ oป๘[wa}&?Qt<่ŠŒ„ฆ.=ญๆ ุพ@ู๕1[ฑ†€ช4ืาฃ 1ะ’Fฮาแ‰ณU3—pZ:๎0Dฺะ5uXชŠ0 ๗ไ,}„ฟ]ˆˆˆˆVƒQŒ ไฒZ๘;™ไGR†šj๖ืซส2~ใฦm่Hš(9๎้QŒชฑ=Eวร}ท๎BWสBี๓๑ƒ“Sธผ3Irf)oช,มร”฿”a*B ดฆ3 xB`บbcฎ๊ฌ™๛ศB$4Oœ๓หWoแo"""ขีว EDCCร#นžคr_ปi|ธ™ร”ฉส๘ภ๕๕ Ut<อ“ว1Qชล๖ผW\ฟ๗–K[ŽอยT่ŠŒึ„”ฎ"กi็?อจy>*ฎ™& Sa ดค3uธB`ฒTร‚ํฎฉ{จๆ |ๆม'๘”="""ขˆ0HลXณ‡)KS๑๋ืข-a oป๘ซ'ŽวzkXอ๘ท์\ฺ‚๘ิภิ€,Ihฑ๊ม,Mฉ*Pd Aย๖ุž@ู๕0[ฑDฆฮ RŽ˜(ีP`""""ขUฤ EDt >0ะe&จ3iผท™Ÿง ๏ฟnญ–Ž|อลวaก฿ญaฎ๐ฑ7๏@gชพ๑๘| Ž/`จสy_งHR}NQc€ถฅ)S!?hฬ˜๒0Sฑซฆฮ Rถ/0^ฌขไzk๊žฑ=O3HE†AŠˆ่าla*c่x฿u[ัb้Xจน๘‹วŽฦz%Ž๘ํ7๏Xš‰5:_†ใ ่๊ห™_ S ญพbสj<อB8~}๘๙โV>„ซฆฮ R5_เlฑŠ ƒญ")"ขKPณ„ฉVหภฏ\ณ9Kว|ีมื;‚ฒใว๖ผaˆ฿บyฺ“ŠŽ‡S eุพ€๖O=”% YCGBWaฉ‹aJBŽ/P[ๅ0๕า 5Vจ ๊๙k๊ฑ}O?ภ EDDD)"ขKุ}†ฺ’ๆ็ึฅฌ›ฃSํI๗^ฝYSรlลมื‰u๘|ไๆหั–0Pฐ=œษW`๛โ‚’ YS;gล”บฆ\ภ๖|Tผ๚S๙<ฑra*M-)dM5ฯว้|ถk๊p|O1HE๗ูšAŠˆ่าU˜๊L™ธ็๊-ศf*6พ๖่ิ๘†U–๐oบ ญ!ํc…j=HษŽร”ฅ)Hh*šฺ~^SŽ/Pq=ฬTx"X๖0„ภฆึฒ†Žช็ใdพ Ok๊žpŸzเq)"""ขˆ0Hญ!{๗ส%ฬ/ญO[;W#Lญฯ$๐๏ฏ„ดกaบlใฯใ eจ ~ใฦํKCฺฯ*pEE~}มH†„ดก!กฟฆTEF„pDืจx>ฆห๖ฒ†ฉ 6ทึWH•]'ส๐)""""Z= RDDkะ๛ผ7mhŸํษX}+ฆDbcK ๏ฝbRบŠษr ่‘XฏฤIh*>xร6ดX:๒ถ‡ำ๙2 „;‘ิSI]i<™O…ึSK+ฆผ๚Œ)ืใa*€อmidM %วว‰…‚5๖yภเ RDDDDQa""ZรริฆึTŸƒน/–lฯโ฿๎@RW1Qชแซ†ˆ๑฿ดกแื "g้(ุ.Nๅ+Ai™vิ…!OๅS`้0%KCภ ‚ฅง๒อVl8o LีWH-)ว็Kk๎ฺg""""Šƒแ=๐๛ปRึง 5ตœฮu9ผ{วXšŠ‰R_}๔HฌWโไLฟvVไLรษ…Vโhยศ˜,UAาะ–ยTžเŠF˜ช:ฐ=qQa* Hภฦ\ 9KGั๑0บƒ”'|’AŠˆˆˆ(2 RDDษ๕$•๛ฺMใรหฆjžภ5=m๘7—๗รRœ-V๑ีGว๚ต& ๊5[‘55l'V6ไ„าบ†„ฆ ฉซH่๔ล0ิท๒U=™Š}มa*Bศฒ„ นZ,}UŽฃy"ฤ'ฟƒQDคˆˆ่<หฆชž๚:๐ฮํ}0Uc… พ๚่‘e…sŸXด=ŒฎRศ C ฅซีR ’บ]‘†/ฮ˜บะ0ๅ!tEF_6ู˜…ๅโิBkํำ€/B|‚AŠˆˆˆ(2 RDD๔ฒรT›ฉ๕ >/ปnX‡;ท๕ยPœ.T๐•GA•ๅุž“๎ด…pีfคW9H- ‚iSCRSai*Rz}๘9P฿"้Šืร\ีEี๕_6Ly"„ฉส่ษ&—žxชPมZ๛<เ!>q€AŠˆˆˆ(* RDD๔ช†† t™‰?๊L๏ฝ˜0Ut<ถนwl]CQp2_ฦW= -ฦAช/›ฤ{ฏุ„ดกข`ืg/Eฑโk1LYชŠคฎ ฅkKกฯ ๊aช๊๚˜ฏ9(ป>ิs่Šบ"/mู›ฏน8/ฏน๋šAŠˆˆˆ(Z RDDtA.6Lๅmo์มอะ'J๘ฺมฃ็ล‘ธhIแ=ป7"ฅซ(8.F็ส‘nAAˆดก!ีx"_RW๋[๙๐โŠฉšW~^i„)วPe›าศ™:ๆซŽฯ—–VZญ"๑๛ RDDDD‘a""ข‹RSๆ—;“ึฏฆๆซyY๖l๊†ฆศ8>_ฤ_>~ RŒ‡HmnMใ๎]Hh๊าำ้šแpD"ฉซhKฐTฆ&/ญDsƒŽภ๖|LWmŠ,aฐ=‹ฌฉaฎ๊เ๐L ]]Sื1ƒQดคˆˆ่uูป๏ภP[าบ”u๓ห…ฉูŠw๏ภ[6ฎƒ*ห86Wฤ฿ำ+ แ!สއช็ฃ๊๙(9d้า S!€“AŠˆˆˆ(* RDDดข\|T๎fr!๛็Oล๚Xฎํiวืว6H@อ๐ƒื๗vภิˆ €„ะd’xAˆŠ๋กโ๚จyEวฝdริ๏1HE†AŠˆˆVœ+‚“๓ป'G?–2ิT\ใ๚vฑu=4EA1ฆAส๖„ธฒป –ช`กๆเ่\ ฝฺูtEฉ‡) ๊๙จx5ฯGั๖pฉu))"""ข่0Hัชษ๕$•๛ฺMใรq S7๕wเถอKAjtฎปyKถ/ CยฮฎXช‚๙šƒcsEช‚Vห@สะj @—ธAˆช็ฃๆ๚(ป>สฎwษ\ RDDDDัa""ขU74<’๋ตค/ด&ฬฆ -6ฏ๛ๆ ุณฉš"วv…”ใ hฒŒห:s0A๊๘\ a}š,MEgาDBWa( tE†,KK+ฆชฎJcฦT1HE‡AŠˆˆ"34|` หLQgาxoยิ[ึแึM]Peน๑”ฝR์ๆ+น~CUฐญ#CQ0WupฆP9/ฌ-?oOšH6ย”ฆศ%ภBิ<ฟ>cส(ุnlฏ?)"""ข่0HQไโฆ†6uแ–u็ฉ2bถcฎะTlmKCWฬีœษW^vฅ—/B่ชŒ๖„คฎมT:LีŸสฯ0ล EDDD)""jw ?xe‹กืu)๋ๆf Sทm๎ฦอ:กศŠŽ‡ัน2d9^็ุ!R†ŠM-)hŠ‚๙ชำ…๊ซ†5_„P IIM…ฅีgLษง๒ีผ๚๙*ž’ํ!@<>[0HE‡AŠˆˆšฮ}†ฺ’ๆ็š-Lพe=n๊๏h)ฃsลุ 5๗ƒCร†\ š"ืท์ๅหt/ SฆฆยPd(S5O ๆืท๓A“ฦ`""""Šƒ5ญf Soฺƒ๚; H@ั๑p|ฎ%fAJ!r–Žพlช,cฎjใtพrQวแ‹Š,กณ1cสT่ชฅฑ•ฯ๖ลy3ฆš5L1HE‡AŠˆˆšฟxเ]YS{2V_”a๊g{p]_d%ืร๑น2”˜mู ‚- =™TYฦlลฦ™Bๅu…ตล0ีž4jฬ˜2Tฒ$A4ยTีจy>๒Mฆคˆˆˆˆขร EDDฑqว๏Mฺgฃ S?ปญื๔ถCF}…ิ‰๙R์ถ์!ะž0ะถ ศf+N*P฿ภq๘"„,)IMƒฅ)0^ฒbชๆ T=๙š43ฆคˆˆˆˆขร EDDฑณฆ6ตฆ๚๔U\ข๔ฮํ}ธบง €ผํโ๔+<ฎ™…!ะ‘4ฑ.eพค๒จส?_„e4fLฝฆTY‚ิgLูพ@ู๕0[q†X–Ÿ๛z1HE‡AŠˆˆb๋฿ํ๗>7I~$eจฉU๙y—๗ใส๎V@พๆโLฑ)†็ญ3iข#eA‘€™Šำ๙*ดe Cพ!I๕0•า5ชK“กศ2D ๆจy~=LU ข0ล EDDD)""Šตกแ‘\ORนฏ4>ผาa๊] ˜ฏ:/UcyฮบSZ“&dณUง๒eฌฤJ3_„€t$Lค ฆชยT๋Oๅ ย5/€x*฿tล^๕0ล EDDD)""บ$ฌF˜z๗Ž ุีี‚ภlลฦdนหsี“N %a@jว้Bฺ n}๔Eˆ!:“’บ KSai๕แ็Aย๖ุ^}+฿Lล^ตญ| RDDDDัa""ขKสะ๐.3๑GIใฝห9๘\๐๎ุน.‡ภLูฦt%~A* พ\9S€ฦS๖–wห+๑E3วโS๙,Mฅ)ญ|๕แ็Žb˜ ‚• S RDDDDัa""ขKาr‡)Y’๐ ;7`วบDL•j˜ญฺฑ;/A ไ’ศš๚าJฏฑb๕ =e๏b-nๅkOผฆLUชิร”๋ ิฮ~.‚pEยƒQtคˆˆ่’ถ\aJ‘$ฝk—uf!‚ฅๆkN์ฮG„ุุšFฦะ" R็}ณ $4–ชภิ๊Oๅ B,…ฉŠ๋cฆb/{˜b""""Šƒญ {๗jKšŸ[—ฒn~=aJSdยฮl๏ศ@!ฮซศn์ฮƒBljฉภ\ลฦูbŠํ๓eHศZ:,Uฉว)MY~๎๚l_ ์๚˜ญฺ๐ล๒„))"""ข่0Hัš๒zร”ก*๘…0ุž„8Sจ ไxฑ;ล •55ˆฐy‚ิ"Y’1๊๘’Zžป•ฯ*ฎ‡้สS RDDDDัa""ข5้bร”ฅฉx๗Ž ฺุž8ตPFล๓cw็ฉ ฤ\ีiช ตH–$ค ษฦjฉ„ฆBUdAWิWL-nๅ๓D๐บยƒQtคˆˆhMปcƒ๗ฆ ํณ=ซ๏ียTRฏฉอmx"ภษ…jพˆ๑พ\/V!7Y:Wึะ‘ะ๋QสิThฒ„0ฤyajถjร๕/.L1HE‡AŠˆˆ/†ฉMญฉ>]‘๊ž64ตc6ตฆแ‰ว็‹pEปใ|1H้๐ƒ๓UใฅšธGB9Cฏฏ–าUX0„€'8B ์๘˜ซฺp.0L1HE‡AŠˆˆ่๏๙๛‡฿฿•ฒ8eจฉs๛ฌฉใฎhIรGๆŠA†žค<`กๆ`ขTƒ$ล็า†KS‘ิU$ฯ SฎเŠท๒ฝV˜b""""ŠƒัK ไz’ส}ํฆ๑แล0ีb้๘๙0Kม/L)~ว„ภฦ–ิRšซ:˜*ว+H-J้Rzcฦ”ฎAWd„a}ฦ”ใ T=ำๅWS RDDDDัa"""z‹a*ญชฟ1ุžIฟkG?6ไRp„ภ๓S๙ฆ~!ฮRณUำ;Žm †@ฺP‘ะ5$รฯuEF,…ฉŠ็cฎโ ๆ‰๓ยƒQtคˆˆˆ^ระ๐HnCZ๛่พ๕Šฯ๔e“ฐ}g&`จr์Ž% –rฆWฬTฬVํุฟGA"ณ8cJS‘าUจr๑‚Ž โy˜ฏบ(9. Ua""""Šƒั:™/๔e’๗พธ็ฉ‰9Xšปcxišฎุ˜ซ:—ฬ{!าฆKUll้ำaXSฎPu}L•k๘o๓เฏฝm„W6ั๊c"""บHeืxุ่ฤฺฦ/&๕xEฉ๐œ-{Ž_R๓5็’{‚ Dาะั5˜šŒิโŒ)ิท๒aˆƒcณ{nุ5ย+šˆˆˆh๕1HฝNCร๎์๚U๋ฎK˜:7HูB`บdcมv.ู๗H!Rบ๚โv>]…กิท๒9"ุcชสฏd"""ขีว EDD๔ํw`่ฮํ}_บฎท}gณ‡ฉ06ถฆ5tุพภTน†ผํ^๒๏Q=LihM่ฐT†*C•ๅ=Š,๐ &"""Z} RDDDห$.aj %ฌกม๖&ห5ึ@Zดธb 5๔=๋3‰^นDDDDซAŠˆˆh™ํw`่๖มo๊๏ุุŒajqห^อ˜(ีPt5๗ซxr|nฯงzๅฏX"""ขีว EDDดB๎ุเฝC›บพxห@gg3…ฉล U๕&JU”oอฝ7๓Uyไ้=ฝ๏ํ#ผR‰ˆˆˆVƒั [ Sทo้๎Td)ฺ?6ถค‘15T]๑Rewํฉ…š‹/|AŠˆˆˆ(ฒฯฅ RDDDซใณ฿}๚‹ทm๎-KSดศ๐ุุšFฦะPu}œ-UQq5๗^lŸ.ƒQdŸKคˆˆˆVฯะ๐H๎žฝ_lหE˜’ acK SCล๓qถPEี[{Aชh{๘wŸb""""ŠƒQข Sฒ$a WReืวูB5_ฌน๓_r<ง๏0HE…AŠˆˆ(BCร#น_ฺัื;r๏Xม็Š$aC.‰Œฉฃ์๘+V`ฏม Uv}|๖ก'คˆˆˆˆ"ย EDDิ†† ฝ}ใ]น=+ฆTYBถฑBส๑qบP+ึ^ชธ>AŠˆˆˆ(2 RDDDMdฅร”&ห่ห&‘15”\g๒k3Hี<ฯ<๘ƒQDคˆˆˆšะะ๐Ÿา๗Oื๕ถ๏\ฎ0†€ก*่ษZศ:Jއำ๙ ผ Xs็ื๖>อ EDDD)""ข&ถw฿ก;ท๗}i9ยT–ฆ`}:ฌฉกh{8S(ร ึgว๘ิ RDDDDQa"""ЁๅS"‘ะT๔dศŠŽ‡ำ ๘แฺ[!ๅ๚เวคˆˆˆˆ"ย EDD#{โwฝus๗Wo่์ผุ0ๅ!š‚พliฃพB๊Tพ ฑ? ธ"ภ|›AŠˆˆˆ(* RDDD1tว๏ฺิ๕ล‹ S~ยR๔็RH*Jއ ek๐ณ€'|’AŠˆˆˆ(2 RDDD1ถฆn฿าฉศาซ~ญ'BชŒMญiคteวว่BiM)_„๘ฤทc""""Šƒั%เ“=๙ๅ;ท๖ผ฿าํ•พฦ4Yฦ`{ MEล๓1:WB€5ค‚Ÿ8ภ EDDD)""ขKฤะ๐H๎žฝ_lห๕raส๑ศฐฃ3KSQ๓}-!\ƒAJ!~ŸAŠˆˆˆ(2 RDDD—˜W SŽ/HุีีKU`๛‡g k๒aˆ๛พล EDDD)""ขKิะ๐H๎๎ํ฿ุ•“ิUุž\ั SUP๓Ž0H๐J!"""Z} RDDD—ธกแwo฿ธส๎–=๓Uoฝคฯ ญมs„ภ}฿:ศ EDDD)""ข5bh๘ภภo^w๙o\ก(จz>ŽฮืไนCเใ RDDDD‘a"""Zcชž?ค+สฝ๕Tพผ&ฯƒQดคˆˆˆึจ#ณลก๕“ำ|cวUI]]sว{฿d""""Š ƒัทw฿ก;ท๗}้บ๖k)L1HE‡AŠˆˆˆw์๐กM]_ผe ณs-„))"""ข่0HัyึJ˜b""""Šƒฝฌล0u๛–๎NE–.นใc""""Šƒฝขกแ‘อฝูฯ฿นต็–ฆh—าฑ1HE‡AŠˆˆˆ^ำะ๐H๎žฝ_lหuฉ„))"""ข่0Hั[ S[Zำ๏‰๛|))"""ข่0HัE>0p๗๖๛wwๅ๖ฤ5L1HE‡AŠˆˆˆ^ท8‡))"""ข่0Hั64|`เฎมฏ_ตพํ๚ธ„))"""ข่0Hัฒูป๏ภะ๛พt]o๛ฮfS RDDDDัa"""ขe‡0ล EDDD)"""Z1{๗บ}ฐw›๚;66[˜b""""Šƒญธ;๖?x๏ะฆฎ/2ะูู,aŠAŠˆˆˆ(: RDDDดjริํ[บ;YŠ๔ต0HE‡AŠˆˆˆV๙sŸผyC็g,Mัขz RDDDDัa"""ขH ไ๎ู๛•มถฬ]Q„))"""ข่0HQคข S RDDDDัa"""ขฆ04<’๛ฅฝฝ#๗Žี|ฮ EDDD)"""j*Cร๎พq๎ฎž• S RDDDDัa"""ขฆดาaŠAŠˆˆˆ(: RDDDิิ†† –พบฎท}็r†))"""ข่0HQ,์w`่ฮํ}_Zฎ0ล EDDD)"""Š•ๅ S RDDDDัa"""ขXฺป๏ภะ[ท๔|–ฮฮืฆคˆˆˆˆขร EDDDฑvว๏ฺิ๕ล‹ S RDDDDัa"""ขKยb˜บ}Kwง"Kฏ๙๕ RDDDDัa"""ขKส'z๒หwnํyฟฅ)ฺซ}ƒQtคˆˆˆ่’34<’ปgw๏W2wฝR˜b""""Šƒ]ฒ^-L1HE‡AŠˆˆˆ.yCร#นปทwcwWnฯโเs)"""ข่0Hัš14|`เ๎ํ๗฿ิ฿พ‡AŠˆˆˆ(: RDD;vL 0๐ฅ …ฑ2† Fค ฅ.ฒp'!c€฿9๏็˜™yฏ๕ฉะ3คHRค )R†)C €”!@ส eH2คHRค )Rj%ุ๚^fhIENDฎB`‚sparse-0.18.0/docs/assets/images/logo.svg000066400000000000000000000545651514474157100203050ustar00rootroot00000000000000 sparse-0.18.0/docs/assets/images/logo_with_text.svg000066400000000000000000001102611514474157100223660ustar00rootroot00000000000000 sparsesparse sparse-0.18.0/docs/assets/images/open-book-icon.png000066400000000000000000000111341514474157100221320ustar00rootroot00000000000000‰PNG  IHDR’gdgAMAฑ asRGBฎฮ้PLTE”Qโ tRNS,Qn•ยโํ9หสIDATxฺš=S@†w๘ฐฎ]I8i…C ฬa“คŒ‘D\"AIBlSj ุ*5 1๚ูบLdํ้๎œห๙)\kŸู“5 8ญN<šฮE‘EฑXL'ฃจ ี€`ํ๑8หก6Ÿ„†-์ท;ั่‰๑๓ฯ0jZtฦ)P8“ n'žฮ2๘ถ˜Žย@‡€ฮE‚,‡!ญxF=›ีœคP‹ๅ00P|%ฮต‚€Pvบ๖๊วิแAZ@คX†ธ>8ƒบJ psค1ภ๕๐ๆ$`\Nภศณjแ ู•‚พฃ:จยd€vTไ=h จ/ภ=8]Tมฝtอ – <~ ฆ๘ >สrƒฃเซ๑7)ภธฯ`V€i=0,ภฐsุ(ะWซ฿~จีoฟึEq.a๓@#ะ0ฬ `ลโ‰ฌ(ิพษ$ยXำงร๐•‹๊ฤใYโD!ย'`VmgfนฮหpjRผl)ฃฐL=o03จึ:ห?JHผ„a๓QtŒฅ่@โล™ŽA่^“ใj|hผq.8T“ธ9ฑ‡4$ัSจๆ Vrจด4/€ฮ๏'›ภ๙ฦ‘ภจZมŽสX@›€=y่žI‚ฝpณ@e;:บัGดA็lc9nJlฺ เZอค ๘‹ฃ5่HปQ๗ฐขE่™~[๏4บh•:ื`%s๐ใ๊๖ะVุžƒ>ฑ`ตK}pแ๐-@ุ€}ด\๖„’”ุฌZ,ฯZเH’ํ@่ %1มเฅT ๕[.ผบ<"Bต^6ซ[เ”q‡v  _๓xe< ๅ่Aธ]ี ด^๖ซภแ๖  วภีW@‚๖  ใgๅ;ภnž//ฯG_{ไ€อ๒BSbw`ณ๚&เุ$‚scš%๓Z…๒qฟUfem :ไ๘2@ฟw…`อ฿ํM_ธ๐Sl/{์@ปฤๅฅณC€.Bฺ.ะฅห[Xบรฐt)๐ฑ๏4ฝ{๓รไQ$YŠฉžEW… dู‘}N๏ุ1ี P4Vป—๗I€j%โ— ๐๓ฌใw์™เ”`š†ˆฎ~,’A€EB๙ะ 3 ภXๅiภg&~AFaฏA๚ฤฤƒx ๘ฑQ€ฆˆ เ)๐‰PB/ เฯ†>ัฒq€%0ŒฬQG ฌ๏mฐl2`eฏK,P&Pห~<ช)ื5ๅwญ j๗nFxMŸrQ€โK๚ปณ้ B}ง€่ํMัO‹Dbใoกb็˜?จ8_ฆ„l_ŽธIdŠ"๑38ั๑ƒ d `QนgHช)`๕์$— ๐œH‚7งhช Ÿ่™!€‘ฌL๗‡O4o ฃ9ฆ^๛ลY0€ฎeฯbูซม V~ ›๒„ฦ‘ห-kอ€๊Sฝ ™›ั"‹โ›:]‰cภg˜ญœFฑพ, žaมU |๛Qๆด?ฐ‚ก• >๚a>šกtฅG}ษำัM#60ฤK๛ผ] ‰QJ™gS5‚ม‡ม๘˜šp๚ใ4 ˆ—ทŸ &๖54ำนbsผ5ฬงX0€งz๘ร.›%ฌ๗๚๘| จ๔๋lm `”pซŸฃฅP/ม [hฌ๏KวOTขL Šฺ*๎u๋7ๅp/นQ gS่Cjฺ็Hิ&ึณ˜ู&ภ –ƒแ›€ว@ˆ:f6€Sปฤ๋ภวm‘งU9มO€๘๚๏w™g€รw { ภeวลlg5›ฐ[๐ฎ“ฟหl `< žเ=x๛ํ(l)๐Zj›ษ2พXvิปก{ข)ไŒู2€z‘bK Oฌเฯฑ๓b ๐ฉฺภK5;ลM๎1@Zิฯ.<—5Ejเ :ปx7๏ฃภุYฌo~๐์-ฯ.n๚Yเ%จกฏฏซฮ€ฎ6ฏซญ'\uQ9 \q•ฐ‹0ฟ]ฅ๋1€8W hDŸฤ^xู๐YC?ใฃ๛Iตp,ภK ‰T๕x1ฃเ”Ex;'Ÿซ€ณณ8‡ฬO@๒๖ธฐ๐8เ€pภ8เ€๘ล<7 pภ/kม๙ฦฌฌ์๕๚ƒ“๋?Kถัฟ_y{b FZIiภคˆšฦเ[ l]‚โ้ฒย‚ฆฤ4@TPฅXtJภฝt>X&ย๚p+ก9C PอV2@xLF:I-?๚ฆ๊ห˜Pก้Yภe-—ใฬ,^ 0>๘g€‚ำฒถsš €๎ฃค€Kฑl/‚ฯ %8ะฐ–ส3C‹„s๋ g฿็„ใ5uิRย ุภ๏$’}k$’/ฦยŒD๒—.€w$?6š;€šy1PIฺT˜เฐๆ‰:@”L0ˆH งzถI I‰ ฎิya\ƒ†3ฯๅฬสnp`เฑŸZ)%j_ขk“X DW]ทc Œ f ˜4n$ๆZz@€๑ƒ-›ธญŸศDh฿k ` e`๘ึ0ภQ†o ทะม ส@#)รjญŸฝxZ€0ซญเใ `€0ณ฿ €สถอt ฐูd@iใ๎j€ฐำdg+งขœุI.่2xฦ0๘ฎ) P—”6{่H”ฮ‚ึ3€'๑1€฿ม4ซx+๋ƒํ5{ L!p๘ฯ.สXฬ6T—ย€X์จ ๘"l€+:pY-Qธโ๊`@ ใ7a…5฿ ภy/๘›น3ฆ#{ฐภO Lๅz‰yqตpWAŸE8ซ0ฆ)๐๚แtฉ:ฏา€;เ๓ox;ฃ๋X <&”ซ ฟ^ภ8เ€p3๐ู8เ€๘ฅrเ€p r๑/ nถ.†797๗wƒ ญ๐Ÿ๓ฯเโโhฏต1;aจŸˆ@q‚แลa+ถ PGต‹๊€apิฒnw^ฮเpร<@Œ^3ž - Zำ$6Pภmด์เฆj๚V/‰ฌเvU๐๐ญเ๘]\”f €@ ~€ท9UศิRขช6ulU €่L+@๘ช@^S@-ฃ €Iภ๔ฏ$y‰€wคœฆ๋P์, ฅd %-9Uจeค!ฑ์wŒจ็[ฌฐ˜“†<=ภ2iŠ—(ฌ‘–,H,‘ฎ๘Mi€mา“9 €ด%ุ‡ๅŽŸ๖%ธA๚r ฐCšโณ ภiฬ (u๔E €ำ20ภ;า• –จ‘ฮœ"๕๗n8ผ่‡ร๛พ ฏ“ฮœ…๑ƒ๓รอฑท9\ู๋๕๓ฑ๊k ฎ]R0 {ล?๓jณพwิ๋฿Hน๑฿M๘ช—• uY gๅมM9” <๗$พใE'น;‡ 'eฦ?่‚ั๋ภ‰ฺ}Kะ o1่ฆY&พQI"๑€ZN(^—™อ`ƒvF8^ ขLdำู่ฎ ณ€ยT`๘๖ิo|ดัณUu‚“‰๏๑Vณe๕;8อ ;pŸู€TCมโ๘๑ฃKhgฅ}@ a1@-ป‹@eGน*3๐qฒ*x7:\ผกแวoภึr…๐–ๆC€upY)|S็d`๒๘นbx!:ใa พชคj๘2ฦ“ฮี`~/๐œช ปป€๑›ฐ$ฦo ภพภ)ฐ/pลO€฿K฿&€}ฟ๙ษpว๎๘ํ„ฉฤc-ี›hฝ๚เvบ…R}pร D›y€pณ>บ๘Dย๗|ฏ*=?ฺŒq‹eœG^q๏จ7๖‚G‡ญอX;ฎิ๔€@pwQ\IุPxคhฅ}q“ำcน=!a ฌ‹>18o=๘แŒฤ๒ศ>ฮะŠKXi๗๓)K c๐ิ<†/บก g`โว7z๊ธJ์Nท 4A…จ(B7–_,+0_Nฆx%ญ@๔๖†๔$8Kฏพxแœ๔ไ๎,‘ˆฺฃว฿’๚,€ขศเ0‘ุ๊“๖œว๐ \?แฐGฺ3่N๕r*#ม:๎ณโไว•ํ`ตOฅล๏N<ฎถ2Q<a๐'(็6y ๐. D•„o3*=g‹d-Y< เ6#๑RฒHpI...........zr?JNฦBvs7ธ8ฺˆวo]ต{๛า ็‡ใทย•อฝฃ‹๑กต6$ฝ‚ ๆฅ1(cE ๚p้’4ๅ5-ี๏ทเเ;๊ๅม๊๗ฐJnหQ;Sปฃ’pQ0‚ๆทพ—RN‰w1ฅึuM„เผลЉzethลฉ‹ผnGฏ#แดป(ีeเSŠ๏ง่!่M}I=๘—G ํ๚๊-aฏแ+kkD=O/ฉ0ƒ๋ฯjJ๑vY๊}*ฬgZิบจ7ฦ ฮD๋JผOœ=อPZขKxใ Dk‹Ÿ‰—ลฺ)ช Nนฤ๘œcโ _{ข”‡$H˜˜฿€แ๋ฯ;PhŒเ+31‡)พฌๅ :ฺ 8Jมฅ—ร@๔วฆฃ—ค$ฝร„อๆ˜ฦrณัDํ๓.๓ภVถAuœก[หZงภต ๗Fฉ>ฎข šซptœื‰ี?แ?พฎ™ค™ฒ1IENDฎB`‚sparse-0.18.0/docs/assets/images/repair-fix-repairing-icon.png000066400000000000000000000126051514474157100242710ustar00rootroot00000000000000‰PNG  IHDR๖‚ๆSgAMAฑ asRGBฎฮ้PLTEคtRNS%T†ต>‰ IDATxฺํIw8€’าxฆฌ„gZฒyึุฯrœเ,ฎ'Lง฿๔เฉIb+ฌ2q้ืŽžฤ(ิ†*`ๅf a~ํ๑๊หoร?cลศฃr ฃJS่ค5๘;2kด_eา_†๑๘๙%ะwรไ(ฎŸถฆGฏ]Ÿ‡ู๑q๕:Ž1๐u›tๆจฏ๛ŠW qบZ“ฮ๕štศV"ใๆๆ&œI/มqP˜ฯŠฯm่ี :Z‰จอยšuจฆ.^ใ“๗์๙ 1 6:†เ๏™Q๓ะC‚Gƒิh%๕Fผฤำัณฟ*(๘h จ์โ้—ๅฏถ/eู็Qช ดวีฬH†!,๘Tš,:ํtt8H%฿ํต*ฦj >แ ฟŽUBงb/Zškณ)แP’ ึ?vฆ%ขถ€ฏ่ืC0๐5๚FลtรwV๘ถฒ FหwYญpV๔Œโุ์N@อPšPx๗หณ&ตU๖ใr๏วq'แF3ีเ?<_7ฟbฺภ๊๐“ฯชฎห๘,฿ขืmษwฺ‘แ#_ฑu1Oั@ ์f0L:+าm‘ฐ/-ต.?)ตuู,ฤWOq๔ี็m,พห˜ณ—์hIณC…ฃG์ฒ‚ ๓ูใ‰>y/ wฮ\G3้hฺ9๐ต7n}`EฯH์06|p์h&• _‡มฮf’YM๖0๑ู ๗wx3^๎Kไฑฎใ‡=ฟ฿๖)ใ฿ 9๚ญO์'…pw่฿ถŒๅฮL eมุw๚ู1ร(P?{ไำถบv้+ZZb™ษg3กสGM/๓,ฅ๚V%ช๒ซกRJ<~ศgcฟ๖#K๕M2t๛Lไ\:ฒˆNG ›‰™ๅ[Yอ]ฟถŒวฎภ่EธŽYฬYั“j>3†ีXJ฿eาอ9ึŽ๎xb< ๘qะใVพ|ทณW-๛:๕ฬฤ๊ฑfโJ~ืBi5mYซผศ๙…๛๗v๗ืฦ฿3ๅโมฃภŸ หฝžOผ4 vน๓#ฎ‚ณนˆร]๎K1า๑ึL๎ฦ’ˆๅœิ ˆ+“[Ÿvฺต.lG–~*ธ๐•ํบ๖ุาOnหฦƒ๕างิฮOล~•ศ~/GฅKณภJขZœ[/๓D–๖Ÿ ท:ย)ค ศ„‹<7รrO•ะ[lฑณupR‘ณึฅศNฉ TFfตผฐtd  )?ธ๘5่น ใWชUนมฦฏ`ฑ‡ฟฎ™”งฦz wh฿ฤiK–ด ‰WD`–>";๑k4gั๚Iqุฮrว\ืุจ๊ฑฟ–“`ฑn์ิŽšŸ1คฑำS–r+ม;ฺโฟ๓ฟš๚†๏\ถไๆึต+ฺ=6ฉ๔ฌคฎปE๎ถฒq ๛ฏ่l๙š™{๘หฝhpm็^็ภำ)ุ๕กm'๛ฟKฺ-|็๐€ฤึ๑ตG—ว^gNฏS้œhชํ\ยึkี7MDฤลAน9งฌ ํ๏‡Glพขฅ†๎&พ™ผฌ๐ำธธyฤ๖- รฤ๏˜๕Ÿแxึฤ฿VWk52๑๔บk‡O&…~๗5ฎ#%cกฟญ‚ผ„žมhัK(—๐ข๓2 Ÿ&lvsผ๖ |๗ฏ–ฐ_{l๒ึฎฬ๓{’?ทๆ ฯศแ๔0๑‰ •Eิ\™?œzฟ…>โ‹้ซ™0์\•yภยˆ“ฯ๗‚ำัeL|๋;เฯ…ŽNGก_่žฃำ‘y็ืยท.b๔k;ฯ4<ผ>1๑pมร+[B_x!<fก?{vงผ;๑ญ}ิFฆU่;Dฆ๚wโมถU5จŽu๗ๆ^ v”S4'๕ั-ผˆ8V๔๑’X๕O“ŠๆไXโแRฯ—ซ7ฬธŒี'๗ฦbFL\9D€์\สฒ฿:ฤ๎v๕ิ๚"ืษX˜๖_๛*?ร\’’Pษ4€™ำ๏๑ๅ>Mฅƒะ ่žง Ž.ํ%Ÿˆr+๕‰G/3ฉ}ไ.š)ฅv พ้ >+๚H๒็ˆศNผฟ'™ๆฒhTฒT=œM;อE รรeu#อ ›ววว-6ฤtXEEdšชr ๑บ€๎มGŒ๔ซ$|ญI๖Nbงคย ืŒ ”๛^S“[-นEŠ๕p…jb๓จ'Œle๋บL—_๓กฌ#[=Šพ“฿6zาcเZภNฆGแŠ,48<‚<ะvJัLฉ๕’5ไ;์ฆฉD3ฑึ ดdcภฐฃ๘ ๊ำeภ†รัฬ=๓(˜ศ@bฬE3๚€$๓=†ๆ8 #ั \฿๑ญฦ œไฌMG3ˆ–<ร=๋เษํx4คžิะf๔•*E4gkMB/๑%XืแO:ถ5:“ั _๊?ๅ kษ}`ญั ณภŸ!าŠ๔”ฤฆ#5]_+นำ™ž\gฃ)šQUwXกฐฎีดตัkŠfTี]ญPPyิxˆ<šิmayxm™ณัh†?๑ทq{3kภE†>ฮู„Gเyw‡ฬF๎;R€W๏้Œ‰wDพดูU@+3†9Cชkw…‰ญ–h ํ:‡BฏAxPyrแฎร?ƒ๛ฦํ*กฯ5(ปtฤ†‰_kxํ๋ั’ C่#€ฒc\™ h\Yน^ฯMอ๗ฆwทเฑ๖ฤ‘{/ …ณGžด[E๒Š~E>๑ฤง‡ฟ๕  ษme แKi๖ิ~C53แ›ฺ๋[ธRv=ุR4ะงY!บยีฺ ฮIไษY9๒ร่›š๒ๅุข๎O฿UŠชŠxาX[ชjY๔ข,ฑ•'งไŠ~7L ™๗ํ>–(ลQQลX{ํศศ5ข:๖น'ว†ฤ๒์w่•ๅ๒Š่Oฟ…n๖HVfฃ’ฉงเ์งy7โ-3gเ;ุฑYJ{ห๚อ7ฌ^สฃผญtจฉRฎ;๛Eคแ๎ภŽŽ*๔ฐูRRJูฺํ{M'4œ:ไยŒc:Rฅึu (็G๛ฬˆc‡> มฮ(8๋ฃ5ยžฆฝ•7ซ|กึงคข์กูย:gแชลฬ2{)4ํ?%hพฆอฆถ6ข*Tl‘ฌแ<ข†ซb2ซ์‘ุใ’Zวมk˜ทoูXeล.o%|ง~เwu`›์‰˜Y"ร‡†sจบ‘„:~hฯ๋ญ๙์๔sNย’๐ั…™7hmฮ๛šƒNูkะrงh๔';<>ดปf‡VO #๑ๆr๚?c[ธgงgบQ๖d้ฤำ@a"ž:ปgฤ]h8Zด sŒง‚ภฦ5{ทD๋Zžช๚5ฅœฐ7n๖LŽunZ?4y๛‘ำ ™า76แฯ๓MS›อณŽU%ำ)‘|t‡ˆu๖‰๕u=N;5O_๕ๆ.๘์o˜*[mg‹น฿ัb›์–๛ฑFืัูzR <_—Š…Qkึีrน–“dง๔":;T่Sั$˜่KN๕ฒทข์-ธฦ ฮพถลื๘ษV# ,ภŒ๕ฒ7ณ์๔^!ี/š๔ŽDู#ป์TYŸ`œŠษ—^๖šรNWm 2๏–‚๋ส2{ฌช์6ขช2fฯญฒS๋฿[ฅCฝ>ด4l์ฒ_v๗$iใ~ถXOKPl›}ญ|jI/ŒึำXƒlณGส!-zฆเŒ‘‹5ฑฬŽLŸSŠ๛ฮนe๖1\†_‰๗llณ—†{O$zb์นู.C$๓ฝถูSณMG‘ฬb*-ณoฬvฺล2_ป๑‚ฝ6sฟ:ๆ|ุ2๛ฺpใM$ำ F์ฒ'Œ ฏvฉ็Žฆ–ูท—>ˆรวNุว?ใูHง])~~ถ๖†fฑดwฺ!" Ÿ[e)๛ล›่#ไรว็}…Œ๔า็ยw„‡์ซฤแHธ[>uษžะKฟิ๓แ#—์ศLKu.ฺฌU:cงws๓g`อ๑>ถฯ^ฯ˜™_Oz=ก๙•1v2ใฯำn`Eh&~”œaงหฉcฐ'ฐVJQฆฦ๐ฤืs6คaฐวฆ›R0)˜˜bOจ๑พ๑3หสtุภผู‰ฏgพธว vdฌซฌL ฦฆุc*n์์Xชฐ:๑น!๖Utศ&œศ›ฝต:๑H;;lvbkโ[†3`…=อA5ุZ๑ฤณ?๎*;์ƒ U_ ~ณ‚๘M {มc?iv๎€mQํ๘@}eŠฝต|]ร=›4Xป๚&ษ^R๖หฟ3ดŸGFjgโdšแธบƒณำoJอำ้HƒชมOi†ฏขJ=›๛Kฉ7k$ ธ๏…*…“‹W‰J{u๑ฤY๐7‡รa/f˜KDIท„ฃ๊(•อ\œฝโฐS?c๒Rz:{ พD‹ุ฿ฏ—๑b‰._ษZ;#kMมๅ/f'R–ํ฿cšfšฅ-์TฏOถึขgยji๔ห๑w‡รแ๑f”n˜r„๐j Y๏„ฒฯeญ#บq']œ๖บว์cuท–๖mVc๖ูฌ๕-ฃk๋งคSeซปตlืฑRนี…nฝฅห\ ~ H‡ั๕>'Keฝ8“]ŽD฿”แ‘rlLู›๙ —ˆฑำYอDสRVทTมAฎจ.ีl1egว}ต่ทœ˜–ฑI&า‰|ก?ฉฑทฃฟ+ฑ5›๛ ‘์ีSH„ะŸีJ—:nถฃx คแ =˜}œพY@ยœงม6๊ˆf#๊3์ๅ W๊#ภ#’ูท[icoA๙๒ŽmQฤjVGฦPvชI… ‹ูSลGd‡จน ๖๎๔xข~%Q:ŸM@บุ;7ฝ‡ิูืŒ@เม๛Z๛พHฉœ๚ŽYTฉŸ=tO|ชกX/-ฒ'|v๘ฤวู๊_fฌ’๋fงO W๕๐๒อ’ๅB โ๛pY๐๊~ฬxzเzฏม์ญAฏ07์W[j๐๋ฮ๐BฯŒOะช7ก4์ฎ[f„๓H [dR{Nฟฦ๓ N*ฯวซ5๘f๖ ์Cม%ศ๛ุต๖ี=]‡0๖šรCบฮ:์ซํJ {ฯ3'-h?ำฬ/่—9๓็ ชล?yฬฮ?ใ+U%ท^ณท์ู๋๕ ™vx0‡ชก–้ี^ณฬ้ฐhง๓•Q}žฬ;<ž—(ž ฒร ฺฑั›ธ[Ÿ็}(ฬ^ิ‰}ž๗ณู™Oณึ์žฝ1{|3๛ฐ'๗์๖h^่5Žื๛€อj๚bฦ๓้Vฐgf…พž‘าฃ์GณB฿O`ท+ุkรw๏Œƒk๖feW่้pฯพ‡ผ๓˜}X†•)5™9šนrษ๗่a™+ูฆ {ภ๙งi>‰fhๆ๊่œฝหh“‹Oฏ‰ณศฮฏ* žZ›์^TาV€xฦฤ๏๘>rnBuํ2’๙hSฮ˜kืปb็ืบญŒ bรตS)F•q๛›zฅh%2ฮžุˆgิท*‘ปvŠ%e7žQLฬDฆอ๏ฺB<ฃฃ>P๖`…ž(๎6"B๕Aจ๑ฬ 7ฉ%†ู7ๆใ๕{e–=2๏ฺฉง"cสf<ƒ้๗’ฎŠ ใ™‘J({ฉ๊ฒVQ๖ใ™’}OŽFูsรiมTKDีPˆฉ๊5xท-\ืneตเฺฬ๐•ฆชs†‰s>"ณB_26ส่+;ฃ๗›ฎ=`กงชS๎e'ืฯ”€๗ะใ@?L่ฉ๊ะzช:ัฺV้M h =U]rูOWฯภY&Aงช้*๚ ž 3UMU]–ีv๎Ko่"ZลvZ๗ฅ7๔nฆาซฏาตC”.L|๑L๏าะuช)‚ลoฅ๏3_Joฐๆพรพฤ3Xo“฿bo\;˜V๓k๘Žwย๛_็ˆช y฿๚‘ฑไ–๐ซLvไ’ผ฿๛ตEqึa, ึญ๔”{N}m8้y{xM๚฿๏{ํา—ืฦYƒ๛Pฎu–๏uŸป้ƒ๎ธcำญ‚เIซจ… mTปวำ(พ„&{;7 tฺู๋7ฐi+รy:qlฺ๛U€#‚x&จ Wไั๎p๘ว<FI˜>๛ ะซA๋hqH๖M๓hŠcด, —๎ซN|48 ๖ตNๆภ\œ๛๙ j๙ภ|b‚ฝ๙ย์ํยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ยพฐ/์ ๛ย๎i๋?อาํ๛HMฐC?๊ใ๚๛@ะ;g4๎}8…ย…;ํ๐q๎)'๐qGดฮบE๗_ะ™ƒ๐โ/นIENDฎB`‚sparse-0.18.0/docs/changelog.md000066400000000000000000000626341514474157100163220ustar00rootroot00000000000000# Changelog 0.15.1 / 2024-01-10 ------------------- * Fix regression where with XArray by supporting all API functions via the Array API standard. (PR [#622](https://github.com/pydata/sparse/pull/622) thanks [@hameerabbasi](https://github.com/hameerabbasi)) 0.15.0 / 2024-01-09 ------------------- * Fix regression where [`DeprecationWarning`][]s were being fired unexpectedly. (PR [#581](https://github.com/pydata/sparse/pull/581) thanks [@hameerabbasi](https://github.com/hameerabbasi)) * Extended [`sparse.einsum`][] support (PR [#579](https://github.com/pydata/sparse/pull/579) thanks [@HadrienNU](https://github.com/HadrienNU)) * General code clean-up (PR [#586](https://github.com/pydata/sparse/pull/586) thanks [@MHRasmy](https://github.com/MHRasmy), PR [#598](https://github.com/pydata/sparse/pull/598) thanks [@jamestwebber](https://github.com/jamestwebber)) * Bug fixes with respect to NumPy compatibility (PR [#598](https://github.com/pydata/sparse/pull/598) thanks [@hameerabbasi](https://github.com/hameerabbasi), PR [#609](https://github.com/pydata/sparse/pull/609) thanks [@Illviljan](https://github.com/Illviljan), PR [#620](https://github.com/pydata/sparse/pull/620) thanks [@mtsokol](https://github.com/mtsokol)) * Bug fixes with respect to GCXS (PR [#611](https://github.com/pydata/sparse/pull/611) thanks [@EuGig](https://github.com/EuGig), PR [#601](https://github.com/pydata/sparse/pull/601) thanks [@jamestwebber](https://github.com/jamestwebber)) * `Array API standard `_ support (PR [#612](https://github.com/pydata/sparse/pull/612), PR [#613](https://github.com/pydata/sparse/pull/613), PR [#614](https://github.com/pydata/sparse/pull/614), PR [#615](https://github.com/pydata/sparse/pull/615), PR [#619](https://github.com/pydata/sparse/pull/619), PR [#620](https://github.com/pydata/sparse/pull/620) thanks [@mtsokol](https://github.com/mtsokol)) * ``matrepr`` support for display of sparse data (PR [#605](https://github.com/pydata/sparse/pull/605), PR [#606](https://github.com/pydata/sparse/pull/606) thanks [@alugowski](https://github.com/alugowski)). * Larger code clean-up with Ruff formatter and linter (PR [#617](https://github.com/pydata/sparse/pull/617), PR [#621](https://github.com/pydata/sparse/pull/621) thanks [@hameerabbasi](https://github.com/hameerabbasi)) * Packaging and maintenance (PR [#616](https://github.com/pydata/sparse/pull/616), :commit:`b5954e68d3d6e35a62f7401d1d4fb84ea04414dd`, :commit:`dda93d3ea9521881c721c3ba875c769c9c5a79d4` thanks [@hameerabbasi](https://github.com/hameerabbasi)) 0.14.0 / 2023-02-24 ------------------- * [`sparse.einsum`][] support (PR [#564](https://github.com/pydata/sparse/pull/564) thanks [@jcmgray](https://github.com/jcmgray)) * Some bug-fixes (PR [#524](https://github.com/pydata/sparse/pull/524), PR [#527](https://github.com/pydata/sparse/pull/527), PR [#555](https://github.com/pydata/sparse/pull/555) thanks [@hameerabbasi](https://github.com/hameerabbasi), PR [#569](https://github.com/pydata/sparse/pull/569), thanks [@jamestwebber](https://github.com/jamestwebber), PR [#534](https://github.com/pydata/sparse/pull/534), thanks [@sarveshbhatnagar](https://github.com/sarveshbhatnagar)) * Some performance improvements (PR [#570](https://github.com/pydata/sparse/pull/570), thanks [@jamestwebber](https://github.com/jamestwebber), PR [#540](https://github.com/pydata/sparse/pull/540), thanks [@smldub](https://github.com/smldub)). * Miscellaneous maintenance fixes. 0.13.0 / 2021-08-28 ------------------- * [`sparse.GCXS`][] improvements and changes. (PR [#448](https://github.com/pydata/sparse/pull/448), PR [#450](https://github.com/pydata/sparse/pull/450), PR [#455](https://github.com/pydata/sparse/pull/455), thanks [@sayandip18](https://github.com/sayandip18)). * Maintainence fixes (PR [#462](https://github.com/pydata/sparse/pull/462), PR [#466](https://github.com/pydata/sparse/pull/466), :commit:`1ccb85da581be65a0345b399e00fd3c325700d95`, :commit:`5547b4e92dc8d61492e9dc10ba00175c1a6637fa` :commit:`00c0e5514de2aab8b9a0be16b5da470b091d9eb9`, :commit:`fcd3020dd08c7022a44f709173fe23969d3e8f7c`, thanks [@hameerabbasi](https://github.com/hameerabbasi)) * [`sparse.DOK.from_scipy_sparse`][] method (PR [#464](https://github.com/pydata/sparse/pull/464), Issue [#463](https://github.com/pydata/sparse/issues/463), thanks [@hameerabbasi](https://github.com/hameerabbasi)). * Black re-formatting (PR [#471](https://github.com/pydata/sparse/pull/471), PR [#484](https://github.com/pydata/sparse/pull/484), thanks [@GenevieveBuckley](https://github.com/GenevieveBuckley), [@sayandip18](https://github.com/sayandip18)) * Add [`sparse.pad`][] (PR [#474](https://github.com/pydata/sparse/pull/474), Issue [#438](https://github.com/pydata/sparse/issues/438), thanks [@H4R5H1T-007](https://github.com/H4R5H1T-007)) * Switch to GitHub Actions (:compare:`5547b4e92dc8d61492e9dc10ba00175c1a6637fa..a332f22c96a96e5ab9b4384342df67e8f3966f85`) * Fix a number of bugs in format conversion. (PR [#504](https://github.com/pydata/sparse/pull/504), Issue [#503](https://github.com/pydata/sparse/issues/503), thanks [@hameerabbasi](https://github.com/hameerabbasi)) * Fix bug in [`sparse.matmul`][] for higher-dimensional arrays. (PR [#508](https://github.com/pydata/sparse/pull/508), Issue [#506](https://github.com/pydata/sparse/issues/506), thanks [@sayandip18](https://github.com/sayandip18)). * Fix scalar conversion to COO (Issue [#510](https://github.com/pydata/sparse/issues/510), PR [#511](https://github.com/pydata/sparse/pull/511), thanks [@hameerabbasi](https://github.com/hameerabbasi)) * Fix OOB memory accesses (Issue [#515](https://github.com/pydata/sparse/issues/515), :commit:`1e24a7e29786e888dee4c02153309986ae4b5dde` thanks [@hameerabbasi](https://github.com/hameerabbasi)) * Fixes element-wise ops with scalar COO array. (Issue [#505](https://github.com/pydata/sparse/issues/505), :commit:`5211441ec685233657ab7156f99eb67e660cee86`, thanks [@hameerabbasi](https://github.com/hameerabbasi)) * Fix scalar broadcast_to with ``nnz==0``. (Issue [#513](https://github.com/pydata/sparse/issues/513), :commit:`bfabaa0805e811884e79c4bdbfd14316986d65e4`, thanks [@hameerabbasi](https://github.com/hameerabbasi)) * Add order parameter to ``{zero, ones, full}[_like]``. (Issue [#514](https://github.com/pydata/sparse/issues/514), :commit:`37de1d0141c4375962ecdf18337c2dd0f667b60c`, thanks [@hameerabbasi](https://github.com/hameerabbasi)) * Fix tensordot typing bugs. (Issue [#493](https://github.com/pydata/sparse/issues/493), Issue [#499](https://github.com/pydata/sparse/issues/499), :commit:`37de1d0141c4375962ecdf18337c2dd0f667b60c`, thanks [@hameerabbasi](https://github.com/hameerabbasi)). 0.12.0 / 2021-03-19 ------------------- There are a number of large changes in this release. For example, we have implemented the [`sparse.GCXS`][] type, and its specializations `CSR` and `CSC`. We plan on gradually improving the performance of these. * A number of [`sparse.GCXS`][] fixes and additions (PR [#409](https://github.com/pydata/sparse/pull/409), PR [#407](https://github.com/pydata/sparse/pull/407), PR [#414](https://github.com/pydata/sparse/pull/414), PR [#417](https://github.com/pydata/sparse/pull/417), PR [#419](https://github.com/pydata/sparse/pull/419) thanks [@daletovar](https://github.com/daletovar)) * Ability to change the index dtype for better storage characteristics. (PR [#441](https://github.com/pydata/sparse/pull/441), thanks [@daletovar](https://github.com/daletovar)) * Some work on [`sparse.DOK`][] arrays to bring them closer to the other formats (PR [#435](https://github.com/pydata/sparse/pull/435), PR [#437](https://github.com/pydata/sparse/pull/437), PR [#439](https://github.com/pydata/sparse/pull/439), PR [#440](https://github.com/pydata/sparse/pull/440), thanks [@DragaDoncila](https://github.com/DragaDoncila)) * `CSR` and `CSC` specializations of [`sparse.GCXS`][] (PR [#442](https://github.com/pydata/sparse/pull/442), thanks [@ivirshup](https://github.com/ivirshup)) For now, this is experimental undocumented API, and subject to change. * Fix a number of bugs (PR [#407](https://github.com/pydata/sparse/pull/407), Issue [#406](https://github.com/pydata/sparse/issues/406)) * Add `nnz` parameter to [`sparse.random`][] (PR [#410](https://github.com/pydata/sparse/pull/410), thanks [@emilmelnikov](https://github.com/emilmelnikov)) 0.11.2 / 2020-09-04 ------------------- * Fix `TypingError` on [`sparse.dot`][] with complex dtypes. (Issue [#403](https://github.com/pydata/sparse/issues/403), PR [#404](https://github.com/pydata/sparse/pull/404)) 0.11.1 / 2020-08-31 ------------------- * Fix [`ValueError`][] on [`sparse.dot`][] with extremely small values. (Issue [#398](https://github.com/pydata/sparse/issues/398), PR [#399](https://github.com/pydata/sparse/pull/399)) 0.11.0 / 2020-08-18 ------------------- * Improve the performance of [`sparse.dot`][]. (Issue [#331](https://github.com/pydata/sparse/issues/331), PR [#389](https://github.com/pydata/sparse/pull/389), thanks [@daletovar](https://github.com/daletovar)) * Added the [`sparse.COO.swapaxes`][] method. (PR [#344](https://github.com/pydata/sparse/pull/344), thanks [@lueckem](https://github.com/lueckem)) * Added multi-axis 1-D indexing support. (PR [#343](https://github.com/pydata/sparse/pull/343), thanks [@mikeymezher](https://github.com/mikeymezher)) * Fix `outer` for arrays that weren't one-dimensional. (Issue [#346](https://github.com/pydata/sparse/issues/346), PR [#347](https://github.com/pydata/sparse/pull/347)) * Add `casting` kwarg to [`sparse.COO.astype`][]. (Issue [#391](https://github.com/pydata/sparse/issues/391), PR [#392](https://github.com/pydata/sparse/pull/392)) * Fix for [`sparse.COO`][] constructor accepting invalid inputs. (Issue [#385](https://github.com/pydata/sparse/issues/385), PR [#386](https://github.com/pydata/sparse/pull/386)) 0.10.0 / 2020-05-13 ------------------- * Fixed a bug where converting an empty DOK array to COO leads to an incorrect dtype. (Issue [#314](https://github.com/pydata/sparse/issues/314), PR [#315](https://github.com/pydata/sparse/pull/315)) * Change code formatter to black. (PR [#284](https://github.com/pydata/sparse/pull/284)) * Add [`sparse.COO.flatten`] and `outer`. (Issue [#316](https://github.com/pydata/sparse/issues/316), PR [#317](https://github.com/pydata/sparse/pull/317)). * Remove broadcasting restriction between sparse arrays and dense arrays. (Issue [#306](https://github.com/pydata/sparse/issues/306), PR [#318](https://github.com/pydata/sparse/pull/318)) * Implement deterministic dask tokenization. (Issue [#300](https://github.com/pydata/sparse/issues/300), PR [#320](https://github.com/pydata/sparse/pull/320), thanks [@danielballan](https://github.com/danielballan)) * Improve testing around densification (PR [#321](https://github.com/pydata/sparse/pull/321), thanks [@danielballan](https://github.com/danielballan)) * Simplify Numba extension. (PR [#324](https://github.com/pydata/sparse/pull/324), thanks [@eric-wieser](https://github.com/eric-wieser)). * Respect ``copy=False`` in ``astype`` (PR [#328](https://github.com/pydata/sparse/pull/328), thanks [@eric-wieser](https://github.com/eric-wieser)). * Replace linear_loc with ravel_multi_index, which is 3x faster. (PR [#330](https://github.com/pydata/sparse/pull/330), thanks [@eric-wieser](https://github.com/eric-wieser)). * Add error msg to tensordot operation when ``ndim==0`` (Issue [#332](https://github.com/pydata/sparse/issues/332), PR [#333](https://github.com/pydata/sparse/pull/333), thanks [@guilhermeleobas](https://github.com/guilhermeleobas)). * Maintainence fixes for Sphinx 3.0 and Numba 0.49, and dropping support for Python 3.5. (PR [#337](https://github.com/pydata/sparse/pull/337)). * Fixed signature for [numpy.clip][]. 0.9.1 / 2020-01-23 ------------------ * Fixed a bug where indexing with an empty list could lead to issues. (Issue [#281](https://github.com/pydata/sparse/issues/281), PR [#282](https://github.com/pydata/sparse/pull/282)) * Change code formatter to black. (PR [#284](https://github.com/pydata/sparse/pull/284)) * Add the [`sparse.diagonal`][] and [`sparse.diagonalize`][] functions. (Issue [#288](https://github.com/pydata/sparse/issues/288), PR [#289](https://github.com/pydata/sparse/pull/289), thanks [@pettni](https://github.com/pettni)) * Add HTML repr for notebooks. (PR [#283](https://github.com/pydata/sparse/pull/283), thanks [@daletovar](https://github.com/daletovar)) * Avoid making copy of ``coords`` when making a new [`sparse.COO`][] array. * Add stack and concatenate for GCXS. (Issue [#301](https://github.com/pydata/sparse/issues/301), PR [#303](https://github.com/pydata/sparse/pull/303), thanks [@daletovar](https://github.com/daletovar)). * Fix issue where functions dispatching to an attribute access wouldn't work with ``__array_function__``. (Issue [#308](https://github.com/pydata/sparse/issues/308), PR [#309](https://github.com/pydata/sparse/pull/309)). * Add partial support for constructing and mirroring [`sparse.COO`][] objects to Numba. 0.8.0 / 2019-08-26 ------------------ This release switches to Numba's new typed lists, a lot of back-end work with the CI infrastructure, so Linux, macOS and Windows are officially tested. It also includes bug fixes. It also adds in-progress, not yet public support for the GCXS format, which is a generalisation of CSR/CSC. (huge thanks to [@daletovar](https://github.com/daletovar)) * Fixed a bug where an array with size == 1 and nnz == 0 could not be broadcast. (Issue [#242](https://github.com/pydata/sparse/issues/242), PR [#243](https://github.com/pydata/sparse/pull/243)) * Add ``std`` and ``var``. (PR [#244](https://github.com/pydata/sparse/pull/244)) * Move to Azure Pipelines with CI for Windows, macOS and Linux. (PR [#245](https://github.com/pydata/sparse/pull/245), PR [#246](https://github.com/pydata/sparse/pull/246), PR [#247](https://github.com/pydata/sparse/pull/247), PR [#248](https://github.com/pydata/sparse/pull/248)) * Add ``resize``, and change ``reshape`` so it raises a ``ValueError`` on shapes that don't correspond to the same size. (Issue [#241](https://github.com/pydata/sparse/issues/241), Issue [#250](https://github.com/pydata/sparse/issues/250), PR [#256](https://github.com/pydata/sparse/pull/256) thanks, [@daletovar](https://github.com/daletovar)) * Add ``isposinf`` and ``isneginf``. (Issue [#252](https://github.com/pydata/sparse/issues/252), PR [#253](https://github.com/pydata/sparse/pull/253)) * Fix ``tensordot`` when nnz = 0. (Issue [#255](https://github.com/pydata/sparse/issues/255), PR [#256](https://github.com/pydata/sparse/pull/256)) * Modifications to ``__array_function__`` to allow for sparse XArrays. (PR [#261](https://github.com/pydata/sparse/pull/261), thanks [@nvictus](https://github.com/nvictus)) * Add not-yet-public support for GCXS. (PR [#258](https://github.com/pydata/sparse/pull/258), thanks [@daletovar](https://github.com/daletovar)) * Improvements to ``__array_function__``. (PR [#267](https://github.com/pydata/sparse/pull/267), PR [#272](https://github.com/pydata/sparse/pull/272), thanks [@crusaderky](https://github.com/crusaderky)) * Convert all Numba lists to typed lists. (PR [#264](https://github.com/pydata/sparse/pull/264)) * Why write code when it exists elsewhere? (PR [#277](https://github.com/pydata/sparse/pull/277)) * Fix some element-wise operations with scalars. (PR [#278](https://github.com/pydata/sparse/pull/278)) * Private modules should be private, and tests should be in the package. (PR [#280](https://github.com/pydata/sparse/pull/280)) 0.7.0 / 2019-03-14 ------------------ This is a release that adds compatibility with NumPy's new ``__array_function__`` protocol, for details refer to `NEP-18 `_. The other big change is that we dropped compatibility with Python 2. Users on Python 2 should use version 0.6.0. There are also some bug-fixes relating to fill-values. This was mainly a contributor-driven release. The full list of changes can be found below: * Fixed a bug where going between [`sparse.DOK`][] and [`sparse.COO`][] caused fill-values to be lost. (Issue [#225](https://github.com/pydata/sparse/issues/225), PR [#226](https://github.com/pydata/sparse/pull/226)). * Fixed warning for a matrix that was incorrectly considered too dense. (Issue [#228](https://github.com/pydata/sparse/issues/228), PR [#229](https://github.com/pydata/sparse/pull/229)) * Fixed some warnings in Python 3.7, the fix was needed. in preparation for Python 3.8. (PR [#233](https://github.com/pydata/sparse/pull/233), thanks [@nils-werner](https://github.com/nils-werner)) * Drop support for Python 2.7 (Issue [#234](https://github.com/pydata/sparse/issues/234), PR [#235](https://github.com/pydata/sparse/pull/235), thanks [@hugovk](https://github.com/hugovk)) * Clearer error messages (Issue [#230](https://github.com/pydata/sparse/issues/230), Issue [#231](https://github.com/pydata/sparse/issues/231), PR [#232](https://github.com/pydata/sparse/pull/232)) * Restructure requirements.txt files. (PR [#236](https://github.com/pydata/sparse/pull/236)) * Support fill-value in reductions in specific cases. (Issue [#237](https://github.com/pydata/sparse/issues/237), PR [#238](https://github.com/pydata/sparse/pull/238)) * Add ``__array_function__`` support. (PR [#239](https://github.com/pydata/sparse/pull/239), thanks, [@pentschev](https://github.com/pentschev)) * Cleaner code! (PR [#240](https://github.com/pydata/sparse/pull/240)) 0.6.0 / 2018-12-19 ------------------ This release breaks backward-compatibility. Previously, if arrays were fed into NumPy functions, an attempt would be made to densify the array and apply the NumPy function. This was unintended behaviour in most cases, with the array filling up memory before raising a ``MemoryError`` if the array was too large. We have now changed this behaviour so that a ``RuntimeError`` is now raised if an attempt is made to automatically densify an array. To densify, use the explicit ``.todense()`` method. * Fixed a bug where ``np.matrix`` could sometimes fail to convert to a ``COO``. (Issue [#199](https://github.com/pydata/sparse/issues/199), PR [#200](https://github.com/pydata/sparse/pull/200)). * Make sure that ``sparse @ sparse`` returns a sparse array. (Issue [#201](https://github.com/pydata/sparse/issues/201), PR [#203](https://github.com/pydata/sparse/pull/203)) * Bring ``operator.matmul`` behaviour in line with NumPy for ``ndim > 2``. (Issue [#202](https://github.com/pydata/sparse/issues/202), PR [#204](https://github.com/pydata/sparse/pull/204), PR [#217](https://github.com/pydata/sparse/pull/217)) * Make sure ``dtype`` is preserved with the ``out`` kwarg. (Issue [#205](https://github.com/pydata/sparse/issues/205), PR [#206](https://github.com/pydata/sparse/pull/206)) * Fix integer overflow in ``reduce`` on Windows. (Issue [#207](https://github.com/pydata/sparse/issues/207), PR [#208](https://github.com/pydata/sparse/pull/208)) * Disallow auto-densification. (Issue [#218](https://github.com/pydata/sparse/issues/218), PR [#220](https://github.com/pydata/sparse/pull/220)) * Add auto-densification configuration, and a configurable warning for checking if the array is too dense. (PR [#210](https://github.com/pydata/sparse/pull/210), PR [#213](https://github.com/pydata/sparse/pull/213)) * Add pruning of fill-values to COO constructor. (PR [#221](https://github.com/pydata/sparse/pull/221)) 0.5.0 / 2018-10-12 ------------------ * Added `COO.real`, `COO.imag`, and `COO.conj` (PR [#196](https://github.com/pydata/sparse/pull/196)). * Added `sparse.kron` function (PR [#194](https://github.com/pydata/sparse/pull/194), PR [#195](https://github.com/pydata/sparse/pull/195)). * Added `order` parameter to `COO.reshape` to make it work with `np.reshape` (PR [#193](https://github.com/pydata/sparse/pull/193)). * Added `COO.mean` and `sparse.nanmean` (PR [#190](https://github.com/pydata/sparse/pull/190)). * Added `sparse.full` and `sparse.full_like` (PR [#189](https://github.com/pydata/sparse/pull/189)). * Added `COO.clip` method (PR [#185](https://github.com/pydata/sparse/pull/185)). * Added `COO.copy` method, and changed pickle of `COO` to not include its cache (PR [#184](https://github.com/pydata/sparse/pull/184)). * Added `sparse.eye`, `sparse.zeros`, `sparse.zeros_like`, `sparse.ones`, and `sparse.ones_like` (PR [#183](https://github.com/pydata/sparse/pull/183)). 0.4.1 / 2018-09-12 ------------------ * Allow mixed `ndarray`-`COO` operations if the result is sparse (Issue [#124](https://github.com/pydata/sparse/issues/124), via PR [#182](https://github.com/pydata/sparse/pull/182)). * Allow specifying a fill-value when converting from NumPy arrays (Issue [#179](https://github.com/pydata/sparse/issues/179), via PR [#180](https://github.com/pydata/sparse/pull/180)). * Added `COO.any` and `COO.all` methods (PR [#175](https://github.com/pydata/sparse/pull/175)). * Indexing for `COO` now accepts a single one-dimensional array index (PR [#172](https://github.com/pydata/sparse/pull/172)). * The fill-value can now be something other than zero or `False` (PR [#165](https://github.com/pydata/sparse/pull/165)). * Added a `sparse.roll` function (PR [#160](https://github.com/pydata/sparse/pull/160)). * Numba code now releases the GIL. This leads to better multi-threaded performance in Dask (PR [#159](https://github.com/pydata/sparse/pull/159)). * A number of bugs occurred, so to resolve them, `COO.coords.dtype` is always `np.int64`. `COO`, therefore, uses more memory than before (PR [#158](https://github.com/pydata/sparse/pull/158)). * Add support for saving and loading `COO` files from disk (Issue [#153](https://github.com/pydata/sparse/issues/153), via PR [#154](https://github.com/pydata/sparse/pull/154)). * Support `COO.nonzero` and `np.argwhere` (Issue [#145](https://github.com/pydata/sparse/issues/145), via PR [#148](https://github.com/pydata/sparse/pull/148)). * Allow faux in-place operations (Issue [#80](https://github.com/pydata/sparse/issues/80), via PR [#146](https://github.com/pydata/sparse/pull/146)). * `COO` is now always canonical (PR [#141](https://github.com/pydata/sparse/pull/141)). * Improve indexing performance (PR [#128](https://github.com/pydata/sparse/pull/128)). * Improve element-wise performance (PR [#127](https://github.com/pydata/sparse/pull/127)). * Reductions now support a negative axis (Issue [#117](https://github.com/pydata/sparse/issues/117), via PR [#118](https://github.com/pydata/sparse/pull/118)). * Match behaviour of `ufunc.reduce` from NumPy (Issue [#107](https://github.com/pydata/sparse/issues/107), via PR [#108](https://github.com/pydata/sparse/pull/108)). 0.3.1 / 2018-04-12 ------------------ * Fix packaging error (PR [#138](https://github.com/pydata/sparse/pull/138)). 0.3.0 / 2018-02-22 ------------------ * Add NaN-skipping aggregations (PR [#102](https://github.com/pydata/sparse/pull/102)). * Add equivalent to `np.where` (PR [#102](https://github.com/pydata/sparse/pull/102)). * N-input universal functions now work (PR [#98](https://github.com/pydata/sparse/pull/98)). * Make `dot` more consistent with NumPy (PR [#96](https://github.com/pydata/sparse/pull/96)). * Create a base class `SparseArray` (PR [#92](https://github.com/pydata/sparse/pull/92)). * Minimum NumPy version is now 1.13 (PR [#90](https://github.com/pydata/sparse/pull/90)). * Fix a bug where setting a `DOK` element to zero did nothing (Issue [#93](https://github.com/pydata/sparse/issues/93), via PR [#94](https://github.com/pydata/sparse/pull/94)). 0.2.0 / 2018-01-25 ------------------ * Support faster `np.array(COO)` (PR [#87](https://github.com/pydata/sparse/pull/87)). * Add `DOK` type (PR [#85](https://github.com/pydata/sparse/pull/85)). * Fix sum for large arrays (Issue [#82](https://github.com/pydata/sparse/issues/82), via PR [#83](https://github.com/pydata/sparse/pull/83)). * Support `.size` and `.density` (PR [#69](https://github.com/pydata/sparse/pull/69)). * Documentation added for the package (PR [#43](https://github.com/pydata/sparse/pull/43)). * Minimum required SciPy version is now 0.19 (PR [#70](https://github.com/pydata/sparse/pull/70)). * `len(COO)` now works (PR [#68](https://github.com/pydata/sparse/pull/68)). * `scalar op COO` now works for all operators (PR [#67](https://github.com/pydata/sparse/pull/67)). * Validate axes for `.transpose()` (PR [#61](https://github.com/pydata/sparse/pull/61)). * Extend indexing support (PR [#57](https://github.com/pydata/sparse/pull/57)). * Add `random` function for generating random sparse arrays (PR [#41](https://github.com/pydata/sparse/pull/41)). * `COO(COO)` now copies the original object (PR [#55](https://github.com/pydata/sparse/pull/55)). * NumPy universal functions and reductions now work on `COO` arrays (PR [#49](https://github.com/pydata/sparse/pull/49)). * Fix concatenate and stack for large arrays (Issue [#32](https://github.com/pydata/sparse/issues/32), via PR [#51](https://github.com/pydata/sparse/pull/51)). * Fix `nnz` for scalars (Issue [#47](https://github.com/pydata/sparse/issues/47), via PR [#48](https://github.com/pydata/sparse/pull/48)). * Support more operators and remove all special cases (PR [#46](https://github.com/pydata/sparse/pull/46)). * Add support for `triu` and `tril` (PR [#40](https://github.com/pydata/sparse/pull/40)). * Add support for Ellipsis (`...`) and `None` when indexing (PR [#37](https://github.com/pydata/sparse/pull/37)). * Add support for bitwise bindary operations like `&` and `|` (PR [#38](https://github.com/pydata/sparse/pull/38)). * Support broadcasting in element-wise operations (PR [#35](https://github.com/pydata/sparse/pull/35)). sparse-0.18.0/docs/completed-tasks.md000066400000000000000000000000561514474157100174600ustar00rootroot00000000000000[Completed tasks](roadmap.md#completed-tasks) sparse-0.18.0/docs/conduct.md000066400000000000000000000124371514474157100160260ustar00rootroot00000000000000# Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: - Demonstrating empathy and kindness toward other people - Being respectful of differing opinions, viewpoints, and experiences - Giving and gracefully accepting constructive feedback - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience - Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: - The use of sexualized language or imagery, and sexual attention or advances of any kind - Trolling, insulting or derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or email address, without their explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [hameerabbasi@yahoo.com](mailto:hameerabbasi@yahoo.com). All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code\_of\_conduct.html](https://www.contributor-covenant.org/version/2/0/code\_of\_conduct.html). Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/inclusion). For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq). Translations are available at [https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations). sparse-0.18.0/docs/construct.md000066400000000000000000000165551514474157100164200ustar00rootroot00000000000000# Construct Sparse Arrays ## From coordinates and data You can construct [`sparse.COO`][] arrays from coordinates and value data. The `cords` parameter contains the indices where the data is nonzero, and the `data` parameter contains the data corresponding to those indices. For example, the following code will generate a $5 \times 5$ diagonal matrix: ```python >>> import sparse >>> coords = [[0, 1, 2, 3, 4], ... [0, 1, 2, 3, 4]] >>> data = [10, 20, 30, 40, 50] >>> s = sparse.COO(coords, data, shape=(5, 5)) >>> s 0 1 2 3 4 โ”Œ โ” 0 โ”‚ 10 โ”‚ 1 โ”‚ 20 โ”‚ 2 โ”‚ 30 โ”‚ 3 โ”‚ 40 โ”‚ 4 โ”‚ 50 โ”‚ โ”” โ”˜ ``` In general `coords` should be a `(ndim, nnz)` shaped array. Each row of `coords` contains one dimension of the desired sparse array, and each column contains the index corresponding to that nonzero element. `data` contains the nonzero elements of the array corresponding to the indices in `coords`. Its shape should be `(nnz,)`. If `data` is the same across all the coordinates, it can be passed in as a scalar. For example, the following produces the $4 \times 4$ identity matrix: ```python >>> import sparse >>> coords = [[0, 1, 2, 3], ... [0, 1, 2, 3]] >>> data = 1 >>> s = sparse.COO(coords, data, shape=(4, 4)) >>> s 0 1 2 3 โ”Œ โ” 0 โ”‚ 1 โ”‚ 1 โ”‚ 1 โ”‚ 2 โ”‚ 1 โ”‚ 3 โ”‚ 1 โ”‚ โ”” โ”˜ ``` You can, and should, pass in [`numpy.ndarray`][] objects for `coords` and `data`. In this case, the shape of the resulting array was determined from the maximum index in each dimension. If the array extends beyond the maximum index in `coords`, you should supply a shape explicitly. For example, if we did the following without the `shape` keyword argument, it would result in a $4 \times 5$ matrix, but maybe we wanted one that was actually $5 \times 5$. ```python >>> coords = [[0, 3, 2, 1], [4, 1, 2, 0]] >>> data = [1, 4, 2, 1] >>> s = COO(coords, data, shape=(5, 5)) >>> s 0 1 2 3 4 โ”Œ โ” 0 โ”‚ 1 โ”‚ 1 โ”‚ 1 โ”‚ 2 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 4 โ”‚ โ”‚ โ”” โ”˜ ``` [`sparse.COO`][] arrays support arbitrary fill values. Fill values are the "default" value, or value to not store. This can be given a value other than zero. For example, the following builds a (bad) representation of a $2 \times 2$ identity matrix. Note that not all operations are supported for operations with nonzero fill values. ```python >>> coords = [[0, 1], [1, 0]] >>> data = [0, 0] >>> s = COO(coords, data, fill_value=1) >>> s 0 1 โ”Œ โ” 0 โ”‚ 0 โ”‚ 1 โ”‚ 0 โ”‚ โ”” โ”˜ ``` ## From [`scipy.sparse.spmatrix`][] To construct [`sparse.COO`][] array from [spmatrix][scipy.sparse.spmatrix] objects, you can use the [`sparse.COO.from_scipy_sparse`][] method. As an example, if `x` is a [scipy.sparse.spmatrix][], you can do the following to get an equivalent [`sparse.COO`][] array: ```python s = COO.from_scipy_sparse(x) ``` ## From [Numpy arrays][`numpy.ndarray`] To construct [`sparse.COO`][] arrays from [`numpy.ndarray`][] objects, you can use the [`sparse.COO.from_numpy`][] method. As an example, if `x` is a [`numpy.ndarray`][], you can do the following to get an equivalent [`sparse.COO`][] array: ```python s = COO.from_numpy(x) ``` ## Generating random [`sparse.COO`][] objects The [`sparse.random`][] method can be used to create random [`sparse.COO`][] arrays. For example, the following will generate a $10 \times 10$ matrix with $10$ nonzero entries, each in the interval $[0, 1)$. ```python s = sparse.random((10, 10), density=0.1) ``` Building [`sparse.COO`][] Arrays from [`sparse.DOK`][] Arrays It's possible to build [`sparse.COO`][] arrays from [`sparse.DOK`][] arrays, if it is not easy to construct the `coords` and `data` in a simple way. [`sparse.DOK`][] arrays provide a simple builder interface to build [`sparse.COO`][] arrays, but at this time, they can do little else. You can get started by defining the shape (and optionally, datatype) of the [`sparse.DOK`][] array. If you do not specify a dtype, it is inferred from the value dictionary or is set to `dtype('float64')` if that is not present. ```python s = DOK((6, 5, 2)) s2 = DOK((2, 3, 4), dtype=np.uint8) ``` After this, you can build the array by assigning arrays or scalars to elements or slices of the original array. Broadcasting rules are followed. ```python s[1:3, 3:1:-1] = [[6, 5]] ``` DOK arrays also support fancy indexing assignment if and only if all dimensions are indexed. ```python s[[0, 2], [2, 1], [0, 1]] = 5 s[[0, 3], [0, 4], [0, 1]] = [1, 5] ``` Alongside indexing assignment and retrieval, [`sparse.DOK`][] arrays support any arbitrary broadcasting function to any number of arguments where the arguments can be [`sparse.SparseArray`][] objects, [`scipy.sparse.spmatrix`][] objects, or [`numpy.ndarray`][]. ```python x = sparse.random((10, 10), 0.5, format="dok") y = sparse.random((10, 10), 0.5, format="dok") sparse.elemwise(np.add, x, y) ``` [`sparse.DOK`][] arrays also support standard ufuncs and operators, including comparison operators, in combination with other objects implementing the *numpy* *ndarray.\__array_ufunc\__* method. For example, the following code will perform elementwise equality comparison on the two arrays and return a new boolean [`sparse.DOK`][] array. ```python x = sparse.random((10, 10), 0.5, format="dok") y = np.random.random((10, 10)) x == y ``` [`sparse.DOK`][] arrays are returned from elemwise functions and standard ufuncs if and only if all [`sparse.SparseArray`][] objects are [`sparse.DOK`][] arrays. Otherwise, a [`sparse.COO`][] array or dense array are returned. At the end, you can convert the [`sparse.DOK`][] array to a [`sparse.COO`][] arrays. ```python s3 = COO(s) ``` In addition, it is possible to access single elements and slices of the [`sparse.DOK`][] array using normal Numpy indexing, as well as fancy indexing if and only if all dimensions are indexed. Slicing and fancy indexing will always return a new DOK array. ```python s[1, 2, 1] # 5 s[5, 1, 1] # 0 s[[0, 3], [0, 4], [0, 1]] # ``` ## Converting [`sparse.COO`][] objects to other Formats [`sparse.COO`][] arrays can be converted to [Numpy arrays][numpy.ndarray], or to some [spmatrix][scipy.sparse.spmatrix] subclasses via the following methods: * [`sparse.COO.todense`][]: Converts to a [`numpy.ndarray`][] unconditionally. * [`sparse.COO.maybe_densify`][]: Converts to a [`numpy.ndarray`][] based on certain constraints. * [`sparse.COO.to_scipy_sparse`][]: Converts to a [`scipy.sparse.coo_array`][] if the array is two dimensional. * [`sparse.COO.tocsr`][]: Converts to a [`scipy.sparse.csr_array`][] if the array is two dimensional. * [`sparse.COO.tocsc`][]: Converts to a [`scipy.sparse.csc_array`][] if the array is two dimensional. sparse-0.18.0/docs/contributing.md000066400000000000000000000111031514474157100170630ustar00rootroot00000000000000## Contributing ## General Guidelines sparse is a community-driven project on GitHub. You can find our [repository on GitHub](https://github.com/pydata/sparse). Feel free to open issues for new features or bugs, or open a pull request to fix a bug or add a new feature. If you haven't contributed to open-source before, we recommend you read [this excellent guide by GitHub on how to contribute to open source](https://opensource.guide/how-to-contribute). The guide is long, so you can gloss over things you're familiar with. If you're not already familiar with it, we follow the [fork and pull model](https://help.github.com/articles/about-collaborative-development-models) on GitHub. ## Filing Issues If you find a bug or would like a new feature, you might want to *consider filing a new issue* on [GitHub](https://github.com/pydata/sparse/issues). Before you open a new issue, please make sure of the following: * This should go without saying, but make sure what you are requesting is within the scope of this project. * The bug/feature is still present/missing on the `main` branch on GitHub. * A similar issue or pull request isn't already open. If one already is, it's better to contribute to the discussion there. ## Contributing Code This project has a number of requirements for all code contributed. * We use `pre-commit` to automatically lint the code and maintain code style. * We use Numpy-style docstrings. * It's ideal if user-facing API changes or new features have documentation added. * 100% code coverage is recommended for all new code in any submitted PR. Doctests count toward coverage. * Performance optimizations should have benchmarks added in `benchmarks`. ## Pull requests Please adhere to the following guidelines: 1. Start your pull request title with a [conventional commit](https://www.conventionalcommits.org/) tag. This helps us add your contribution to the right section of the changelog. We use "Type" from the [Angular convention](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#type).
TLDR:
The PR title should start with any of these abbreviations: `build`, `chore`, `ci`, `depr`, `docs`, `feat`, `fix`, `perf`, `refactor`, `release`, `test`. Add a `!`at the end, if it is a breaking change. For example `refactor!`. 2. This text will end up in the changelog. 3. Please follow the instructions in the pull request form and submit. ## Tests It is best if all new functionality and/or bug fixes have unit tests added with each use-case. You can run the tests with: ```bash # internal tests pixi run test # array-api-tests pixi run xp-tests # or to run tests across various backends, close to the full CI suite (warning, slow): pixi run test-all ``` ## Coverage The `pytest` script automatically reports coverage, both on the terminal for missing line numbers, and in annotated HTML form in `htmlcov/index.html`. Coverage is automatically checked on CodeCov for pull requests. ## Adding/Building the Documentation If a feature is stable and relatively finalized, it is time to add it to the documentation. If you are adding any private/public functions, it is best to add docstrings, to aid in reviewing code and also for the API reference. We use [Numpy style docstrings](https://numpydoc.readthedocs.io/en/latest/format.html) and [Material for MkDocs](https://squidfunk.github.io/mkdocs-material) to document this library. MkDocs, in turn, uses [Markdown](https://www.markdownguide.org) as its markup language for adding code. We use [mkdoctrings](https://mkdocstrings.github.io/recipes) with the [mkdocs-gen-files plugin](https://oprypin.github.io/mkdocs-gen-files) to generate API references. To build the documentation, you can run ```bash mkdocs build mkdocs serve ``` After this, you can see a version of the documentation on your local server. Documentation for each pull requests is automatically built on `Read the Docs`. It is rebuilt with every new commit to your PR. There will be a link to preview it from your PR checks area on `GitHub` when ready. ## Adding and Running Benchmarks We use [`CodSpeed`](https://docs.codspeed.io/) to run benchmarks. They are run in the CI environment when a pull request is opened. Then the results of the run are sent to `CodSpeed` servers to be analyzed. When the analysis is done, a report is generated and posted automatically as a comment to the PR. The report includes a link to `CodSpeed`cloud where you can see the all the results. If you add benchmarks, they should be written as regular tests to be used with pytest, and use the fixture `benchmark`. Please see the `CodSpeed`documentation for more details. sparse-0.18.0/docs/css/000077500000000000000000000000001514474157100146265ustar00rootroot00000000000000sparse-0.18.0/docs/css/mkdocstrings.css000066400000000000000000000003741514474157100200530ustar00rootroot00000000000000:root { --md-primary-fg-color: #c96c08; --md-primary-fg-color--light: #94f2f7; --md-primary-fg-color--dark: #335365; } .md-tabs__item { font-weight: bolder; } .grid { font-weight: bolder; font-size: 160%; font-family: Georgia, serif; } sparse-0.18.0/docs/examples.md000066400000000000000000000000001514474157100161640ustar00rootroot00000000000000sparse-0.18.0/docs/examples/000077500000000000000000000000001514474157100156545ustar00rootroot00000000000000sparse-0.18.0/docs/examples/dask_example.py000066400000000000000000000017211514474157100206640ustar00rootroot00000000000000# --- # jupyter: # jupytext: # text_representation: # extension: .py # format_name: light # format_version: '1.5' # jupytext_version: 1.16.4 # kernelspec: # display_name: sparse # language: python # name: python3 # --- # # Using with Dask # ## Import # + import sparse import dask.array as da import numpy as np # - # ## Create Arrays # # Here, we create two random sparse arrays and move them to Dask. # + rng = np.random.default_rng(42) M, N = 10_000, 10_000 DENSITY = 0.0001 a = sparse.random((M, N), density=DENSITY) b = sparse.random((M, N), density=DENSITY) a_dask = da.from_array(a, chunks=1000) b_dask = da.from_array(b, chunks=1000) # - # As we can see in the "data type" section, each chunk of the Dask array is still sparse. a_dask # noqa: B018 # # Compute and check results # As we can see, what we get out of Dask matches what we get out of `sparse`. assert sparse.all(a + b == (a_dask + b_dask).compute()) sparse-0.18.0/docs/examples/formats_example.py000066400000000000000000000017511514474157100214200ustar00rootroot00000000000000# --- # jupyter: # jupytext: # text_representation: # extension: .py # format_name: light # format_version: '1.5' # jupytext_version: 1.16.4 # kernelspec: # display_name: sparse # language: python # name: python3 # --- # # Multiple Formats # ## Import # Let's set the backend and import `sparse`. # + import sparse import numpy as np # - # ## Perform Operations # Let's create two arrays. rng = np.random.default_rng(42) # Seed for reproducibility a = sparse.random((3, 3), density=1 / 6, random_state=rng) b = sparse.random((3, 3), density=1 / 6, random_state=rng) # Now let's matrix multiply them. c = a @ b # And view the result as a (dense) NumPy array. c_dense = c.todense() # Now let's do the same for other formats, and compare the results. for format in ["coo", "csr", "csc"]: af = sparse.asarray(a, format=format) bf = sparse.asarray(b, format=format) cf = af @ bf np.testing.assert_array_equal(c_dense, cf.todense()) sparse-0.18.0/docs/examples/formats_example_finch.py000066400000000000000000000020601514474157100225610ustar00rootroot00000000000000# --- # jupyter: # jupytext: # text_representation: # extension: .py # format_name: light # format_version: '1.5' # jupytext_version: 1.16.4 # kernelspec: # display_name: sparse # language: python # name: python3 # --- # # Multiple Formats with Finch # ## Import # Let's set the backend and import `sparse`. # + import os os.environ["SPARSE_BACKEND"] = "Finch" import sparse import numpy as np # - # ## Perform Operations # Let's create two arrays. rng = np.random.default_rng(42) # Seed for reproducibility a = sparse.random((3, 3), density=1 / 6, random_state=rng) b = sparse.random((3, 3), density=1 / 6, random_state=rng) # Now let's matrix multiply them. c = a @ b # And view the result as a (dense) NumPy array. c_dense = c.todense() # Now let's do the same for other formats, and compare the results. for format in ["coo", "csr", "csc", "dense"]: af = sparse.asarray(a, format=format) bf = sparse.asarray(b, format=format) cf = af @ bf np.testing.assert_array_equal(c_dense, cf.todense()) sparse-0.18.0/docs/examples/scipy_example.py000066400000000000000000000016521514474157100210740ustar00rootroot00000000000000# --- # jupyter: # jupytext: # text_representation: # extension: .py # format_name: light # format_version: '1.5' # jupytext_version: 1.16.4 # kernelspec: # display_name: sparse # language: python # name: python3 # --- # # Using with SciPy # ## Import # + import sparse import numpy as np import scipy.sparse as sps # - # ## Create Arrays rng = np.random.default_rng(42) M = 1_000 DENSITY = 0.01 a = sparse.random((M, M), density=DENSITY, format="csc") identity = sparse.eye(M, format="csc") # ## Invert and verify matrix # This showcases the `scipy.sparse.linalg` integration. a_inv = sps.linalg.spsolve(a, identity) np.testing.assert_array_almost_equal((a_inv @ a).todense(), identity.todense()) # ## Calculate the graph distances # This showcases the `scipy.sparse.csgraph` integration. sps.csgraph.bellman_ford(sparse.eye(5, k=1) + sparse.eye(5, k=-1), return_predecessors=False) sparse-0.18.0/docs/gen_logo.py000066400000000000000000000062751514474157100162130ustar00rootroot00000000000000import xml.etree.ElementTree as ET import numpy as np def transform(a, b, c, d, e, f): return f"matrix({a},{b},{c},{d},{e},{f})" def fill(rs): """Generates opacity at random, weighted a bit toward 0 and 1""" x = rs.choice(np.arange(5), p=[0.3, 0.2, 0.0, 0.2, 0.3]) / 4 return f"fill-opacity:{x:.1f}" rs = np.random.RandomState(1) colors = { "orange": "fill:rgb(241,141,59)", "blue": "fill:rgb(69,155,181)", "grey": "fill:rgb(103,124,131)", } s = 10 # face size offset_x = 10 # x margin offset_y = 10 # y margin b = np.tan(np.deg2rad(30)) # constant for transformations # reused attributes for small squares kwargs = {"x": "0", "y": "0", "width": f"{s}", "height": f"{s}", "stroke": "white"} # large white squares for background bg_kwargs = {**kwargs, "width": f"{5 * s}", "height": f"{5 * s}", "style": "fill:white;"} root = ET.Element( "svg", **{ "width": f"{s * 10 + 2 * offset_x}", "height": f"{s * 20 + 2 * offset_y}", "viewbox": f"0 0 {s * 10 + 2 * offset_x} {s * 20 + 2 * offset_y}", "version": "1.1", "style": "fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;", "xmlns": "http://www.w3.org/2000/svg", "xmlns:xlink": "http://www.w3.org/1999/xlink", "xml:space": "preserve", "xmlns:serif": "http://www.serif.com/", "class": "align-center", }, ) # face 1 (left, orange) ET.SubElement( root, "rect", transform=transform(1, b, 0, 1, 5 * s + offset_x, offset_y), **bg_kwargs, ) for i, j in np.ndindex(5, 5): ET.SubElement( root, "rect", style=f"{colors['orange']};{fill(rs)};", transform=transform(1, b, 0, 1, (i + 5) * s + offset_x, (i * b + j) * s + offset_y), **kwargs, ) # face 2 (top, orange) ET.SubElement( root, "rect", transform=transform(1, b, -1, b, 5 * s + offset_x, 5 * s + offset_y), **bg_kwargs, ) for i, j in np.ndindex(5, 5): ET.SubElement( root, "rect", style=f"{colors['orange']};{fill(rs)};", transform=transform( 1, b, -1, b, (i - j + 5) * s + offset_x, (i * b + j * b + 5) * s + offset_y, ), **kwargs, ) # face 3 (left, blue) for y2 in (5 + b * 5, 10 + b * 5): ET.SubElement( root, "rect", transform=transform(1, b, 0, 1, offset_x, y2 * s + offset_y), **bg_kwargs, ) for i, j in np.ndindex(5, 5): ET.SubElement( root, "rect", style=f"{colors['blue']};{fill(rs)};", transform=transform(1, b, 0, 1, i * s + offset_x, (i * b + j + y2) * s + offset_y), **kwargs, ) # face 4 (right, grey) ET.SubElement( root, "rect", transform=transform(1, -b, 0, 1, 5 * s + offset_x, (10 * b + 5) * s + offset_y), **bg_kwargs, ) for i, j in np.ndindex(5, 5): ET.SubElement( root, "rect", style=f"{colors['grey']};{fill(rs)};", transform=transform(1, -b, 0, 1, (i + 5) * s + offset_x, ((10 - i) * b + j + 5) * s + offset_y), **kwargs, ) ET.ElementTree(root).write("logo.svg", encoding="UTF-8") sparse-0.18.0/docs/how-to-guides.md000066400000000000000000000000201514474157100170430ustar00rootroot00000000000000# How to guides sparse-0.18.0/docs/index.md000066400000000000000000000024321514474157100154700ustar00rootroot00000000000000--- hide: - navigation - toc --- # Sparse This project implements sparse arrays of arbitrary dimension on top of [`numpy`][] and [`scipy.sparse`][]. It generalizes the [`scipy.sparse.coo_matrix`][] and [`scipy.sparse.dok_matrix`][] layouts, but extends beyond just rows and columns to an arbitrary number of dimensions.

![Sparse](./assets/images/logo.png){width=20%, align=left}
![Sparse](./assets/images/conference-room-icon.png){width=10%, align=left} Introduction { .card } ![Sparse](./assets/images/install-software-download-icon.png){width=10%, align=left} Install { .card } ![Sparse](./assets/images/open-book-icon.png){width=10%, align=left} Tutorials { .card } ![Sparse](./assets/images/check-list-icon.png){width=10%, align=left} How-to guides { .card } ![Sparse](./assets/images/repair-fix-repairing-icon.png){width=10%, align=left} API { .card } ![Sparse](./assets/images/group-discussion-icon.png){width=10%, align=left} Contributing { .card }
sparse-0.18.0/docs/install.md000066400000000000000000000007141514474157100160300ustar00rootroot00000000000000# Install You can install this library with ``pip``: ```bash pip install sparse ``` You can also install from source from GitHub, either by pip installing directly:: ```bash pip install git+https://github.com/pydata/sparse ``` Or by cloning the repository and installing locally: ```bash git clone https://github.com/pydata/sparse.git cd sparse/ pip install . ``` Note that this library is under active development and so some API churn should be expected. sparse-0.18.0/docs/introduction.md000066400000000000000000000074071514474157100171110ustar00rootroot00000000000000# Sparse This implements sparse arrays of arbitrary dimension on top of [numpy][] and [`scipy.sparse`][]. It generalizes the [`scipy.sparse.coo_matrix`][] and [`scipy.sparse.dok_matrix`][] layouts, but extends beyond just rows and columns to an arbitrary number of dimensions. Additionally, this project maintains compatibility with the [`numpy.ndarray`][] interface rather than the [`numpy.matrix`][] interface used in [`scipy.sparse`][] These differences make this project useful in certain situations where scipy.sparse matrices are not well suited, but it should not be considered a full replacement. The data structures in pydata/sparse complement and can be used in conjunction with the fast linear algebra routines inside [`scipy.sparse`][]. A format conversion or copy may be required. ## Motivation Sparse arrays, or arrays that are mostly empty or filled with zeros, are common in many scientific applications. To save space we often avoid storing these arrays in traditional dense formats, and instead choose different data structures. Our choice of data structure can significantly affect our storage and computational costs when working with these arrays. ## Design The main data structure in this library follows the [Coordinate List (COO)](https://en.wikipedia.org/wiki/Sparse_matrix#Coordinate_list_(COO)) layout for sparse matrices, but extends it to multiple dimensions. The COO layout, which stores the row index, column index, and value of every element: | row | col | data | |-----|-----|------| | 0 | 0 | 10 | | 0 | 2 | 13 | | 1 | 3 | 9 | | 3 | 8 | 21 | It is straightforward to extend the COO layout to an arbitrary number of dimensions: | dim1 | dim2 | dim3 | \... | data | |------|------|------|------|------| | 0 | 0 | 0 | . | 10 | | 0 | 0 | 3 | . | 13 | | 0 | 2 | 2 | . | 9 | | 3 | 1 | 4 | . | 21 | This makes it easy to *store* a multidimensional sparse array, but we still need to reimplement all of the array operations like transpose, reshape, slicing, tensordot, reductions, etc., which can be challenging in general. This library also includes several other data structures. Similar to COO, the [Dictionary of Keys (DOK)](https://en.wikipedia.org/wiki/Sparse_matrix#Dictionary_of_keys_(DOK)) format for sparse matrices generalizes well to an arbitrary number of dimensions. DOK is well-suited for writing and mutating. Most other operations are not supported for DOK. A common workflow may involve writing an array with DOK and then converting to another format for other operations. The [Compressed Sparse Row/Column (CSR/CSC)](https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_column_(CSC_or_CCS)) formats are widely used in scientific computing are now supported by pydata/sparse. The CSR/CSC formats excel at compression and mathematical operations. While these formats are restricted to two dimensions, pydata/sparse supports the GCXS sparse array format, based on [GCRS/GCCS from](https://ieeexplore.ieee.org/abstract/document/7237032/similar#similar) which generalizes CSR/CSC to n-dimensional arrays. Like their two-dimensional CSR/CSC counterparts, GCXS arrays compress well. Whereas the storage cost of COO depends heavily on the number of dimensions of the array, the number of dimensions only minimally affects the storage cost of GCXS arrays, which results in favorable compression ratios across many use cases. Together these formats cover a wide array of applications of sparsity. Additionally, with each format complying with the [`numpy.ndarray`][] interface and following the appropriate dispatching protocols, pydata/sparse arrays can interact with other array libraries and seamlessly take part in pydata-ecosystem-based workflows. ## LICENSE This library is licensed under BSD-3. sparse-0.18.0/docs/js/000077500000000000000000000000001514474157100144525ustar00rootroot00000000000000sparse-0.18.0/docs/js/katex.js000066400000000000000000000004611514474157100161250ustar00rootroot00000000000000document$.subscribe(({ body }) => { renderMathInElement(body, { delimiters: [ { left: "$$", right: "$$", display: true }, { left: "$", right: "$", display: false }, { left: "\\(", right: "\\)", display: false }, { left: "\\[", right: "\\]", display: true }, ], }); }); sparse-0.18.0/docs/logo.png000066400000000000000000006724451514474157100155260ustar00rootroot00000000000000‰PNG  IHDRคค]#าะ pHYs  า~tEXtSoftwareCelsys Studio Toolมงแ| IDATxฺ์y|wa๗๑ฯof๖”dห๗}฿ฑใ8N์ุ‰ฯฤนI8 ”ถด ”ปจZ่Cฎ–(NG ”คO -<Bศ}XพวN๑}HŽ๏SฒคฝๆzXIถ›\๖Xใ|฿Jซ™อj~๛yอึ„aˆˆˆˆˆˆˆˆˆHTŒ‚”ˆˆˆˆˆˆˆˆDIAJDDDDDDDD"ฅ %""""""""‘R‘H)H‰ˆˆˆˆˆˆˆHคคDDDDDDDD$R R""""""""))‰”‚”ˆˆˆˆˆˆˆˆDJAJDDDDDDDD"ฅ %""""""""‘R‘H)H‰ˆˆˆˆˆˆˆHคคDDDDDDDD$R R""""""""))‰”‚”ˆˆˆHDŽ๗๊ฦะx -ฌ…ี5uzFDDDไํJAJDDD$"ว๏บบ<๑ h0ฦซญฎYrฏžy;R‰HGjง0%"""oS R""""yUjะ`Œ[S]ณ๔ทz–DDDไํ@AJDDD$"g RํSชญฎYVงgKDDD.d R""""yอ ีNaJDDD.p R""""yAช]ภbc‚š๊šบตz๖DDDไBข %"""‘7คฺ}ฦ˜ฺ๊šบz=‹"""r!P‰ศ›RํฆDDDไก %"""‘ทคฺ•รTMuM]ฃžU‰#)‘ˆœต ะoก…ตPaJDDDโFAJDDD$"g5HตS˜‘R‰ศ9 RํšŒ๑jซk–,ิ3-"""]‚”ˆˆˆHDฮijะะฆ๎ี3."""]•‚”ˆˆˆHD" RํฆDDDค S‰HคAช]@ƒ1ฅชk–ีiDDDคซP‰ศy RํSชU˜‘ฎ@AJDDD$"็5HตS˜‘.@AJDDD$"]"Hต XlLp[uM]ฝFFDDDขฆ %"""‘.คฺ}ฦ˜Z…)‰’‚”ˆˆˆHDบdjง0%"""R‰H—Rํฎถ0ีจ‘sEAJDDD$"ฑRMก๑ZX ฆDDDไ\P‰Hl‚T;…)9GคDDDD"ป ี. ษฏฆบfษฝE9คDDDD" `ูT\๓น†ไ๘ตX๖ฝMy+คDDDD"็ eœูŸ#9fXvƒปkEmbฤ•๗jTEDDไMอ-คDDDDข๋ •ฬ’]๐y’ฃgƒฑpท/%ท่{/†ญ๛jชk–ีitEDDไ อ-คDDDDข๋ •ฎขโฺฟ#1b&‹า–งษ/๙A๎,6ฆTซ0%"""ฏ{nก %"""8)+ƒ์ตObุๅๅ ต๑Qrห0ส—๏)L‰ˆˆศ๋ค %"""‘Xฉส>dฏ;Cฆ‚1ื?H~ลO '^}ใภภSS]SWฏQ‘ำQ‰HฌƒTทT\๛yœA—€โฺ!ฬ}„ล–3Qเ฿gŒฉU˜‘WR‰Hœƒ”c0ู‡3`"Rx—VOXสฝ๖+L‰ˆˆศ+(H‰ˆˆˆD$ึAชืฒ >‡ำo<„…็๎งฐๆ—„nu฿GzwZX ซk๊u4ˆˆˆผฝ)H‰ˆˆˆD$ึAช๏*ฎ๙vŸั๘ไŸ๙ลตC่฿ุ4…ฦ[จ0%""๒๖ฆ %"""‘8)gภEdฏ์^# ๙?กด๗o พ๛ึ๎8 มฏถบfษฝ:BDDD>คDDDD"็ •6ฬOcW"t๓ไ฿Ciห“เ{g็ฆDDDVคDDDD"๋ 5๒*ฒs>…ีญ?aฑ…\]”ถ-ภ;ปค0%""๒ถ  %"""‘8ฉไุ๙df} ซฒ/aก‰ึงฟ‹ปsนyภ€ลฦ”jซk–ี้ศน๐(H‰ˆˆˆD$ึA๊ขศฬ0VE/‚1rO}ท~„มน}`…)‘ ’‚”ˆˆˆHDโคR“฿I๚Š?วสTดก๕‰ƒท็ˆj.ฉ0%""rAQ‰HœƒTz๊๛H_ง˜T%A๓!Zgผ}๋ฃ฿ภฟฯS[]SWฏ#JDD$พคDDDD"฿ eHO3าS฿‡Id๑›๖‘{์xทœฟMR˜‰5)‘ˆฤ6H‹ฬŒH]๒nL"|7ญ~ศฮ๓ฟmๅ0US]Sืจ#LDD$Fำ )‘hฤ6HY™ซ>B๊โ[0vh=ญ|๘ห]c๛šBใ-ดฐ*L‰ˆˆฤƒ‚”ˆˆˆHDbค์ููŸ$9๑FŒeใA๋รwœ8ะตถSaJDD$6คDDDD"ื eœ™นท“špƒw`s9Hตํšฆzึ,ฉีQ'""าE็ R""""ัˆmJdศ^]Crฬ|ผhyจ–ฐpขkox@ƒ1^muอ’{u๔‰ˆˆtฑ๙…‚”ˆˆˆH4bค’Yฒ >OrิU†ธ{_ค๕กZยR.; 0%""า๕ๆ R""""ัˆmJUQq฿“1ƒ0๐๐vฏก๕ก; Rผv$ มทฆบf้ou4Šˆˆœ็๙…‚”ˆˆˆH4bค2ฉธ‹$†]N่ปxปžฅๅกZ ฆ๓ศ€ลNŸ!ตUผฏNGฅˆˆศyš_(H‰ˆˆˆD#ฎAสส๖ โฦ3x ก_ยฑŒึGพ๋ฑp๚ฃโ_[lU๖ช๊ttŠˆˆDKAJDDD$"ฑ Rฝจธ้qN"๔Šธำ๚๘?วy Œ3h•7‰ษVด]\|—5™ูŸ\ซฃTDD$ขณฑ‚”ˆˆˆH4bค*๛Pq๓8วบJ[ž"๗ิwb<6$†Lฅโฦ/cาU-‡)ฌล~}Ÿ1ฆถบฆฎ^Gซˆˆศ9>+H‰ˆˆˆDใ๘]ื„q\wษ๊ึŸสw|ปฯ่rฺ๘(นบปc<6$†ฯ โ๚/bRอ)ฌบŸโ†‡สฟ|…)‘s}:V‰ฦษ+ค q SV๗T๒5์^ร <ล๕ฟ'ฟ๔‡1ž[$F]Eลu_ภ$2M๛ษ?s/ฅอOtพ]เ฿ีฆu๔Šˆˆœๅำฑ‚”ˆˆˆH4š๛ฏCศNBฏุ>#aส๎1˜Š[พc0a)Gqไ—8พaู$วฬ#ปเs'…|…•Ni[ซoะoก…ตPaJDDไ์Q‰ˆtW่n_Bi๛Rฃป cึตร”s•ท~ซ๛ยb+ลตฟ&ฬฝ๑ห!9~WlX๙ๅ?ฦนโฬฃ0%""rV)H‰ˆˆˆD'$๐๐์คดๅ)J;W4๎ๅdŒ๊šaส๎=ฒคช๚[(NŸQ`':~[๐๖ญงด้ =/ๆ›บฬv;/ฆ๒ึฏaRU„นF๒ซƒโ‹ฟ๏8‘&5๕df€ทoนล๗เฺ๚ๆ๏4 ม˜าmี5ห๊tค‹ˆˆผŽ๓ฑ‚”ˆˆˆH4Ž฿uuเ๔ฟgุ4’ฃฎย๎5,ปใ6aก๗ๅ5”^z๏ภFยbหy฿ngศT*oพ“ช ศฃฐ๒g7<฿ p2K๚ฒžAผ=kษีดญ฿yภbcJต S"""ฏq>V‰ฦ๑ปฎ O]สt ‰‘W’>ปzpง0ไŽแีฏขธ๑1C[ y๎ฤ๐+จธ๑c’Y‚ึฃไ—„าฆวโ;NUž็คงพw๗r‹๎"hs๖DaJDDไŸคDDDDขั~…ิ+-OŒ˜Ab๘ C/รช๊ถำ๑ป ๙๎Že7?Apดžะ+Fพ‰QณจธแK'Eะ|ˆ๒Sฺ๒T|'ภ้*23n#uษปpw=Cฎ๎n‚ฮƒฦ˜š๊šบzฝDDDN9+H‰ˆˆˆDใd๊˜Šัฆ,›ไจู$†Oว<ซฒฯษ+ฆย iฅmu”6?‰฿ด|7ฒํNŽฝš์ตŸo Rษ/ฅm‹ใ;ฮT“น๒รค&ฝwวฒrj9r๎4๐๏3ฦิ*L‰ˆˆดคDDDDข๑๊ ี1%ฃ=L™d–ฤจY$Fฬฤ0ซขSพYเใ7๎กด๙ J[4‚ภ?็œp=ื-ุAำ>rK„ปcYlวมส๖$3๋ฃ$'\@ib๒uwไŽŸ๛W˜)ฯyคDDDDขqๆ ušIZฆ;ษ1sI ฟป฿8ฌlสแ Bฟ„dฅMใn_B;็pN—št3ู๙w€ๅ4๎!ทไธปž‰ํ8X•}ศฬ8ษฑWPฺ$นล๗NDถ a่ia-ฌฎฉkิ+CDDŽคDDDD"๒F‚T;ซขษqืเ ›†ำ{&ำ Œ@Xlล?ผโฆวqw,o๛Fพณ?ทK]๒.ฒsocแk ฟ๘๛ธปWวvฌnศฮ๙$‰Qณ(m|”’๏[ฃ€ฆะx ฆDDไํHAJDDD$"o&Hตณบ$5แZœ!Sฑ{วค*สa* ‹อxทP๐{]+ม๗ฮ๊vงงพฬฌO€1๘Gv’[|žตฑซzูนท“~ล ‘_๒ƒ๓๗M† S""๒6ค %"""‘7ค:#Ÿg4ษqW“|)V๕`L2[^c*๐ '๐๖ญงธ๎ผ—_8kž๖งdฎ+ภเFฎ๎ผ}๋c;vฯadๆNb่e_-๙ฅ?"๔K็wรšŒ๑jชk–ซW‹ˆˆ\่คDDDD"๒Vฎze˜r]Lr‚๒ย็๚—ร€๏ไŽแ๎~žโ๚฿แ๒g‹†๔๔ฟ 3ใ/๐n!_w7Mฑป๗Hฒ๓>ƒ3h2…็E~๙!๐บฦ4ใี*L‰ˆศ…LAJDDD$"o-HuL฿85L%†^Nrยต8'`*zaœ4ฝม‰xปืP\ ฑ†7๗p–Mfฦmคงไ๊๎ฦ?ด5ถใ`๗Cv8. ๐ฯษฏ้9]MQ˜‘ ˜‚”ˆˆˆHDฮN๊˜ฦัฆŒ!9z‰1๓p๚รd{`์Dy})ท@ะดท~ล 4|๕฿!ถCๆสž๚~ผฝ๋สA๊ศฮุŽƒำูyŸม๎7)<๛ไŸนฏ๋npภ‹ฦ”jชk–ี้U$"" )‘ˆœ ี1ฃ=,;Ib์|’c็c๗…•้– _Fพฦ=ธ;WP๐{ยB๓ซด๗๎คศ\๕RS๏ๅ็ษี}๏อ_qี8'‘v๏Q†ไW”ยs?๏๚ฐุ˜Rญย”ˆˆ\คDDDD"rn‚TวดŽŽ0•ช 9แ’cๆ`๗†IU–ฟ‘/๐๒M๘G๋qท-ฆธ้ัSพ‘๏๔aส$2df}œิไ[p๋W‘_r๑=ฑg๐”r๊9 ย€ฒฃ๐/ใณ S""rP‰ศน Rำ;ฺร’Uู›ไฤ›IŽบซภถoไ| w๏เfํK)m}๚”๕“:‡)“ช 3๋ค& €ปs9น%? hฺqH ฝŒฬผฯ`๗Onษ๗)พ๘๘ํHเ฿—ž๒žฺฬ;๊๕๊‘ธQ‰H4A๊ี์žรHNผ‰ฤ๐้ๅoไs’B่—[ใํ฿Hi๛RหO&!&UEv๎งHNธ€าถลไ— ๙Plว!1bูนทcuพGฎ๎.ŠŠๅพค/}/™ซ>zvขจืซLDDโBAJDDD$"็+Hตณ๛Ž!u๑-$†\†Uูlh[๘ผ๙พ ”ถ>๗๒ ''‹™jฒsšไธk(m~’ฒ%h=qHŒšEvฮงฐบ๕'๔KไžฅอOฤr_า— ™ม?ถ๛พงถ๒๏ฉืซMDDบ:)‘ˆœ๏ ี~ี“3`"ฉK3d Vฆบผพ–rM{๑๖ฌฃดu'E๖บ/3€โK_๑cย\clว!9f.™9Ÿยช์C่ษ=MJ๊bน/้้NๆŠ?หม?ZO๎๑o5นื/ดฐVืิ5๊U'""]•‚”ˆˆˆHDฮ๊˜‚e“v9ฉ‹oม0 “ฎ,ส฿ศwผwวrC[INzวษ ตA๒+~JX8qHŽ_@fึวฑ*zบyZฦ+>ฎ™™&}๙สA๊๐vZŸ6กญะOaJDDบ,)‘ˆt ี>ด0NŠฤจซHMผ ปฯLชขํ—!aฎ ๘ห˜l์ƒ(<+ ซƒฐุqH^t™ซ>Š•ํAXสั๚P-๎๎ีฑ—ฬฌ‘พ๔}`ู๘‡ถ–ƒิแํ'o 0%""]”‚”ˆˆˆHDบ\jgู˜TษัณIŽฟปฯhL"]]เ—ฟฯv(ฎr‹๏‰๕8ค&ฝƒฬ•…ษt',4ำ๒๛/ใํ}1–๛’™๓)าSฦย;ฐ‘“฿ม?บ๋ี7 h0ฦซญฎYrฏ^‰""า(H‰ˆˆˆDคหฉv–ƒUั‹ไ˜9ๅ0ีk8XNง›๘วwS\๗;J›Ÿ ,4วrR—ผ‹ฬŒaาU„๙ฦrฺท!–๛’๗R“o-ฉ}๋ษ=๕/๘วฮ S""าE(H‰ˆˆˆDคหฉvvป[cๆ’šx#Vท~ดลณwืJ]ฯ–rฑ‡๔ฅ๏%}ล_`R•ญGi—๑lŠแL"{u ฉ‰7•ƒิžตไžใ{^๛oŒqkชk–VฏL9/ง1)‘hฤ&H"5๑&าWVU฿ฮฟ‚ๆCธปืเ6ฌยน/๛”พ์คง“ฬ4ขๅ๗_./7ถCลีŸ%9แz0w๗jrO/$hฺ๗๚๏#`ฑ1ฅฺ๊šeuz…ŠˆH”คDDDD"ว ๅ œDvงฑ๛Œ฿%๔]L"ฆ|>ม‰ธ๕ฯโึฏยmxฎห๏Sz๚I_๖r:ฑŸ–ฟŒdG&๒NŠ์5Ÿ%9nA9HํZIฎ๎{'ผ๑;S˜‘จฯc R""""ัˆcJ ฝŒฬ์O`๗E่)ฝ๔&U3d*VEฏ“7 ใ/ใ๎X†[ฟ o฿๚.ปO™™&u้{1‰4๑=ด>๔ง_ผซOไ“Yฒื-ษ1๓สAjว2r‹๏!h>๔ๆ๏4`ฑ1AMuMZฝbEDไœžวคDDDDขห 5b™ซ>V^เ๗ศ-๚.~ใ^ฌส$Fฯ!1ไRLช๊ไ„‘”ถ-มฝ๏เ–.ทO™Y'uษป0N ่.Zบ๘๎๘MไSUT,๘‰QณภJ[‘_๒‚ึฃoฮ>cLmuM]ฝ^น""rNฮc R""""ัˆe5‹ฬUล๎1|—ึงพƒxVe/0Ve#fโ ผ“ช8๙‡พ‹wxฅอOแํ]ืฅ>—{;ษI7—ƒิแmดx๖ฉโบฟ'1v~9Hํ]G๋c฿xk๋.'VU฿r:0ื=@~ๅฯ 'ฮอ4…ฦ[ha-T˜‘ทJAJDDD$"q RฉI7“žAฌช~„ลVZ๛:๋ิ)%aชะ –ƒ3pษฑ๓ฐ{;ัqหฐ”รmxŽาๆ'๐n9;๋ฝฑ้/7|‰ไู่`'pwฏ!๗ฤ7 ZŽฤ๎xฒบ bม็q_ ฯŠยช๛ ‹อ็๖ฆDDไlœ‘คDDDDขห uษปI_ฌส>„…fZZ[Œ:ฎœฆŠญ'…3d*‰‘WbW้ธeX8ปke๙Šฉ#;su กโ๚/‘yุ๎ฎgศ=๙ํณป๎RD์Cศ^๓9œA“ „ยšขฐ๚็„ลึh6 -L๕ฌYRซWทˆˆผQ R""""‰cJO}?ฉฉ๏รช่E˜kค๕ัฏท…ฅ?ด+ง„)ท€IfH ›Ž3๔2์๎ม:ฆ‚–รธปžกดๅI#๕็๊“ศPqร?6ญคถ/ฅ๕้๏ž›u—ฮ1ปื๐r0ยยชKแ๙_–rัnH@ƒ1^muอ’{๕*‘ื}NV‰F,ƒิด?#5ๅ=XูญGi}์Ÿ0ง\้๔SM:ย”๏a’Yรง“zVUฟN๛ š๖Sฺฑ w"ฃ „nL~ำUT๐%Cฆ‚ฑ)m]Dฎ๎๎sท๎า9d๗C๖šฯโ๔ O~ๅฯ(พ๘Bทp~6HaJDDศ9YAJDDD$q R™ท‘š|+&SMะ|ˆึ'พ‰9eMจื9ๅค#LVถ‰ก—แ นซข7SพYโ7๎ฅด๙ ห ๗zลณบ?Vถ'7| gะล`,J›'ทไ„ล–ุON dฏ์>ฃภ๗ศ/1ล๕ž๕็์ h0ฆt[uอฒ:ฝ๊EDไŒณ)‘hฤ2H]๕QR“nฦคซš{๊)ƒSONจŸฉ่Mrฤ ์ae{ด<ฃ๕ๅ0ตk%‰ƒเปgeฌชพT\ฅ๒ว€โ†‡ศ/q๔s; œA“ษฮฟปืpBฏD~้(ฝ๔ก_๊ฐุ˜Rญย”ˆˆœvV  %"""Xฉ9Ÿ"uั๕˜d%~ใrOใ$ฯส}‡^‰ะอใ๔KbไUุ}ว`eบw|”/๔Š๘‡ทSฺ๘(nร๊๒7๒[zLซz0ืง๏ุ๒บK๋ ฐ๒฿ฯ฿ว‚ฤะหศฬ๛4v๕Bฏ@~๑๗)n~โฌลปณFaJDDNCAJDDD$"q Rู๙ww &Yฌพค’ูณ๚aก,ง#f`๗Iw๋๘(_XสแุD้ฅ‡๑๖ฎ#ศ7Bเฟฉวฒ{ งโบ/`๗Ex_๘V?ๆ๖&$Fฬ$;็SX–rไ๊๎ฆดm๘^ืเ€ลฦทUืิี๋ฟˆˆ(H‰ˆˆˆD$–Ajม็HŽ™‡Iค๑์ ท่.Lช๒œcจธ๎๏;>ๆVXs kป๋]U๔:$วฬ%3๋cXU ‹-ไž.ฅห๒Ud็\เ฿gŒฉU˜y{S‰HƒTล๕‹ฤจY;‰wh+๙บป1™๎็๔1รB3&S3๘ƒง`U>yUVดร๓ล ใVFพื9งuL$ปเsุ=†บ ฯGแล฿tซŠ€ไ๘dฎVeย|ญO ๎ฎ•o๚๊ฑศ)L‰ˆผญ)H‰ˆˆˆD$–A๊ฆ/“>c;x๛7’[๚ร๒:O อX๚ใ ž‚3๐bฌชพ˜d0เ{อpw?Oqร๏ ŽฟL่•8uั๔ำqOกโšฟล๊>€ฐุJ~ลO(พ๔p|"ฮ)Ro"=๓CXูžนcไžnร๊7|ีุy๘w%Nฌญใ4๊ฟ„ˆศ‡‚”ˆˆˆHDโค*o๙*ฮะห1ฦยปŽสŸbฅปEบ aกปืœA“ฑ๛_„Uูใคภ@่Nภญ–โ‹ผๆย็‰แWฝบฆ|UQแนฅ?ขด๙‰ื}…UW’บไ]คง+SMะz”ึวฟ‰ท็…X๎Kๆส6%'^ฟะุ‰…&Uฅ0%"๒6  %"""‘Xฉw}g๐%xปŸงฐ๊bาU็e[Bฏ„ำ{ฮ )ุฦbฒ=0vยฐ”รo‹ป} ล—!ฬ7qบซฅฃg“{;VE/‚|#๙บ๏Qฺถ„ืบฒช+JO}?้ห?€IUดข๕ฑฦท!–๛RyหืH ›˜&w๗๊…ญ~ia๕gžR˜น€)H‰ˆˆˆD$vAสXTฝ็8&†-Vd IDAT~๙*ค5ฟฤค+ฯ๛ฆ9}วbšŒkVบ;ุaฑh=ฅ-OSฺ๒$ก[8u‡ส๋.อVฆ;Aหr‹๎*ฏปC้้$}้๛0ษ,ม‰ด>๖ ผ›cน/U๏๙6ฮภ‹pwฏกๅท_j2ฦญฉฎYrฏsˆˆ\˜คDDDD"ท e์$•๔œ~ใ}w็ Š๋~{r๑๓อNb๗Cb๐ฅุีƒห฿ศgูxนใ๘ทPฺฑ”าๆ'vศšx™+?‚IWœ8H๎้มฝ&†ณxCfฦmค.yO๙๗ะ๚ศW๑์Œ฿พX6U๏๙N‹สแsื3ด>|g๙w ฦxต S"")‘ˆฤ.H%ณTฝ็;ุ}Fzล๒วแ6>‚Idบฬ6†^ ‚€ฤศ™$†\Šี}@๖BฟDุzoFJ—เ๎\Aj๒;ษ\๙aLฒฟqนงพ…ทw}&ห&sๅGHMพc'๐ํฆ๕แฏเ฿ฟ7$‰4•๏v[๘tqw,ฅ๕ฑ๊|#…)‘ Ž‚”ˆˆˆHDbคฒีTฝ๛ุฝ†บJ[žขดuฦIvนm อ˜T%‰QณpMฦช๊W^๘< w’„nŽะ+•ืœ2ศNZ๛ฑ†๘Mโ™นMrยucแB๋ร_!h9ป}ฑ*z•ณ^ร KyJ[ž$ท่ฎ?G‹)ี*L‰ˆฤ—‚”ˆˆˆHDbคชS๕ฮยชHXhก๘าCxปื”ืi๊โยRป็pฃga๗•๊ถ aฦ@AหarOทู๖ฉ1q๙†:“H“๗’ใเุHหรต„น๘}1ีญ?•๏๚g์๊!ๅ๐น๑qrKพ๚XaJD$ถคDDDD"ฏ eฐ{ ง๒ึฏcu๋G˜?Aqƒx๛6”ปML„พ‹ำo‰aำฑ{j๛†ภถ๐]ผ›)m[„ปsA๓กŽ}๏๊aส$ณdฏ,ษ1s o฿:Zช%,ถฤํํv!ๅใฌz aก™โ†‡ศ/๑ป›ภภSS]SWฏ4""19(H‰ˆˆˆD#vAช๏*o๙*Veo‚\#ลƒhk Ÿy‹0๐pN"=ๅ˜TUวoส Ÿร?ผwื3”ถ/%,6w<]5L™T%ูŸ#9j>๎ห/ะ๚p-ก[ˆ์#ฉผ๕kXU} ๓MืŽ3๗พนป ๛Œ1ต S""18(H‰ˆˆˆD#nAส8‘Š›๏ฤส๖ h=Jqํเู็?,ถ’บ๔ฝ$วฬm๛Aว๗h S-G๐๖oฤ๕ ๎Že„~ฉใน่jaสคซจธ๎ $†ฯ \ผ†ีดโฒVงใlภ$*nGฌlฯr๘|Wžๅู๓ะปำยZX]Sืจ@""]์  %"""ฦ๏฿†^ฑ}ึตใฑH ›Fล _ยค* šQX๓฿M{ใ;v’ิE7’9|w๗ ซAjโ8รฆae{žผbสอ4๎ลณw็ ผ=kO}rฮ๛ุYูžT๘8ƒงzEหi}๔k1|7bH ™Jล ะ>SX Š/๖์=F@Shผ… S""]์  %"""ยณ–v,ว?Vพ>ฃK†)c‘y%ื}“ฬœุOน_ถŠ๏ฤ7ไ๘kI ›พKiว2Z:&™ล๎;–ิไ[I šŒษTwMXlลoƒท{5๎ฮๅx6Ÿz็m์ฌŠ^T๔8'•ƒิถ:Zf ล"1|:ืฑ-|คฐ๊?)n๘ู,…)‘ฎu P‰ˆ๏…๑Jใ๎\|7๘ํktฑ0eู$Gฯ!ปเ๓˜Dš q/…ี?'h=฿‰o"Cj๒;หW๙%m‹i}์Ÿ:žซข'v ค&Œ3h2&‘้๘ฐุŠd'nรณธปž}ลZZัUี—Š›jq๚'๔Š”6?I๎ฉ๏ฤoP,ป>ฏ๛r๘lฺOู๛(mz=f@ƒ1^muอ’{๕OIDไ<ž—คDDDD"Sžx๙ฑ]”ถ<ปsA๓!N~”ฏซ„‡ไธซษ^๓YŒฤ?พ›ยs?'ฬว๘ยc“ž๖ง8&๚ฅrฤy๒ฏธมช์‹3h2ฉI7แ๔Ÿถsr‹-๘‡ถRฺนฏa๑=็gxบ๕ง๒wb๗C่(m|”\๑ห!9ฆ-|:)‚ฦ=ไWŒาึE็ฑฆDDฮ๏iYAJDDD$a)šd๖ไ|่ฎ๒S;–4๎:aสvHMธž์ผ;ภv๐ึSx๎~ยbK|Ÿภ#{ๅGฑ๛+_Uด๑Qr‹๎:ร,ูย๊>€ฤเ)$'ฝงฯจŽ…ฯย\#มMธ;–ใ๎^Cะ|0า}ฑชQ๙Žฏ`๗QR"ทไ๛๑!9๖ฒืMG๘ฬ/ ๎Žeัmƒย”ˆศyก %"""‘โ{ยไ่9ุ}วt๚8XG˜ฺZGiว2ยๆC„~้<‡‚ฉI7“{; ศ ซ๎'t๓ฑ}C฿#;็SุฝGzEŠ๋$ฟไฏ1[ถฐ{ '1lษ๑ืb๗–~ญว๐๖mภพoฯฺ๒7๗E1<=†Pqหืฐ{ !,ๅ(ฎ{€๒วoPN>๓หทู่ท%`ฑ1ฅฺ๊šeu๚o%"r๎)H‰ˆˆˆDไ๘]W‡vŸ18ƒ'“5ป฿8Œ“:yƒถ0U๎Žๅๅ๕š:?x’h'IMพ•ฬœOะV๒ซ๎‡๓สŠภ'3๗v์žรล๓๚#Žภ้=’ฤศ+IŽU=ธ๓]ทลฝšาถ%x๛6›ฯ้ฎุ=‡Qyหืฐช•ƒิฺ_“_๙ณ๘ฝฑ“$'ิ)|ๆ—w๗š๓xœ(L‰ˆDrP‰ฦ๑ปฎ๎˜xู}F“6ฤˆุ}ฦ`้“7๔]ผร)mzwืJย\cไWL'Ejส{ศ\๕Qผ›(ฌ๚Oฝ๘@วษˆ๓ยฏศ?s฿{^i์>cHŒšErฬ\ฌชพข๙๎ฎgpw,ล;ฐ‰ฐ”kKฮๆย็v๏‘T๚uฌช~„ลV ฯ7…U๗ว๏อˆ“*‡ฯูŸ =|ๆ–|o๏๚.pผ(L‰ˆœำs€‚”ˆˆˆH4สAชs˜p๚ร6ฤ๐+ฐ{ ็ิ5ฆBฏˆxฅ-Oโ๎XFoŠ์Š)“ศš๚>23nภทยsI—๚&ภ7( B*-VU_ยRŽย๊_ดํำ›x~’YœHŒžCbฤLฌสง๓‹๏ม;ฐฉ๋ldเ฿gŒฉญฎฉซื1‘ณxP‰ฦฉWHฝ*L๕ฟgุ4รงa๗ŠIUv.t๓'ริ๖ฅลf๐ฯํ•J&™%}ูHO`9์YKa๕ฯมXฑ}ร0คโฺฟรช่UŽ8ซ๎ง๐/฿ฺ๓”ฎย8‰ไ˜y8C/วส๖8๙หภวoƒปcฅmK๐ํ:eZ˜ฒ๛+ฉlOยbsพ*~oFN>su฿ร?ผญ๋mฌย”ˆศู=(H‰ˆˆˆDฃs๊˜Žั)L ธˆฤ๐+p†^ŽsX็+ฆ<แํ”6>Jiว๒๒วม‚sฆLช’๔ด?#}ูเ๎^Ca๕/0ถ฿กโบ/`ฒี„…f๒ฯGqํœ•ปถฒ=q]Lbฬ<C/๋ |c ”ถ>ป}๑—O๓7ฆœQy๋ื1™๎g}_"}3rš๐™ซปh}ืh…)‘ณsP‰ฦ้ƒTวดŒW^1•= gะ์žC;‡ฉRะVŠล๕ aฑยเ์NำUdfF๊’wเึ?Kaอ/1N"ฦ3_Cลu_ฤคซ๓MไW;ล๕žี‡ฐ*๛เ ™Jrฬ\œม—t6ลภร;ดาฆวp๋Ÿ%8qเŒใZœSyหืฺ๖ฅ‘3๗R\๗ป๘ Iช‚๔ดv Ÿ๙บป๐๏ฺ้ะoก…ตฐบฆฎQDDฤ9@AJDDD$8HuLฯ่ฆ^Lr๔œAcu„IUด&$,ดเฺzr๑๓b+gk'“ฉ&3๓Cค.พฅ v.งธ๖7ใ+คŒ• {0ฉ ย\#๙?ก๘ารg๋;=๗V๗$†_Ar๔์~ใ;-Z๚%›(n| ฏแน๒ท)žแ~ฮฤr)•7ๅไพฌ)ล ลoLาUdฎ๘KRSS>ฮ๊Ÿ%ท่n‚๛ใฑ S""o  %"""ืค:ฆit Sƒง5ซฆบ ,_1e „!aพฉฆ6?Žปc๙) hฟyVถ™ซ>J๒ข(m[Liƒ๑RNš์ต‡If Z’_cJ›?าi์^รI ›Nb๔์#;‡ฉRo†rP€์œฟ&1๒JŠ/=oโ;w4ฝจ˜7`;M๛ษ-นง|%Y4ฮซ‚โศซp†^†}@ง0ดลน‚าฦว๐์8ํG0“ใฏํืwวฒุษซย็ๆ'สAชุ|aผ่Œ)V]ณฌNED^qfT‰ฦู Rำ8:Ž3IŽปง฿xLEOŒS^ซ(๔Š-G๐lคด๙ k^ืฝ=“™s;‰แำ(ฎท™7uตUWau๋Ov๎ํ`9๘ว๗_|nรชจง฿'วอ#ฏ"1b‰ม—bU๖9นFWœ8@i๛J›Ÿภ?พ“มLMผ‰์š“qm๑=ธปVฦpL๛)#ฏ*g/=B~ษ๗เีaq†Z[JDไ4gD)‘hœ ี1ใd˜2$F]ีฆฦaฒ=1v Aหแ๒S›ว๛โ๎ฃฬ๎9Œ์ผOใ ™Z/ฆํ*ซ žO~`๕Fv๖'มX๘วศี}๏ๅ็ฯื4ผใ97v’ฤู่$†_3h2VE/ฐ์ถํ๖๑›๖Rฺ๒4ฅ-O4๎BR฿Bvงมr๗ซ๛nรsฑซz0ูนMb๘ๅใlƒไ—ะ-\0ฏ{)‘3œ คDDDDขqn‚ิ้ๅ;$G]u๒ฃ|™`ๅoไ+ๅ šโํ‰า–'๑๖ฎ?ujH{$ฑ{$;๏38ƒ&Px—ธ๕ฯal;žQภ๗p๚#sๅGภ#;สAj๏บ๓=๏xฮMช’ไ˜น$†_Vถg๙›|๘nŠฅดๅ)’cฏ&;๛mW{ํ&ท่๎๓ื<ป็02so'1๔2 >๓K•ะ/]0ฏ{)‘3œคDDDDขYjŸ่9)ฃg“ฟปฯฌtUZE!a1Gpb?พ๕”ถ.ยทกs(่;†์ผ;p\@แนŸใึฏย$ำ๑Œ^ gะd230๘‡ถ–#ฮ]n[ญlOใๆ—รT๏QX™๊Ž0–rx6_ย<“ศเU—NWฝลC9|~gะ%ๅใ์๙_‘_๑ใNOŒ;)‘3ฬSคDDDDขu๊˜๐%ณ$Fอ"5แ:์>ฃ1ฉJ0VSญ{q๗ฎรถ๏ภfœ~ใศฮฏม๎7)<๛ๅ •ฎŠgp $†^Nz๚๐l"Ww7ม-]v›ญชพ$'\Gb่ๅุ=‡bาสใ๘„‡ฑๅE๎้…x๛ึวn\์>cศฮ ฮ€‰V‚ส๕Zeฏ:๖คDDN??Q‰ฦ๙ RฟT%ษัณINธป๗HLฒฒ|ๅM[๑๗เํ}‘โบ฿aeบ“™๗œ€ŠŸโึฏยช่ฯ(เHŒผ’๔ิ๗เํ]_RGvt๙mท{#9แ:œม—`๗‚IdOฎ1Eyแ๚าQ\๗@์ฦล้?žฬผ;p๚ ๐์ๆ>โmŽฏ:๖คDDN?/Q‰ฦ๙RภLu9L_€{&™m็LXlม;ด•0w ป฿x์C ๐ษ/7†็ฐช๚ฦ๓ษw $Fฯ!5ๅ=x/ฟPRวบ๒TSรŒำ<ษฑืเ นด<.vขใwA๎๎5ื=€ทcl†ล0‘์ผฯ`๗„ไWŒยช๛/จืฝ‚”ˆศฮr R""""ั่*Aช< 4XฝHŒšu2L9ฉถwะa)ถำ๑ณ“฿ยทซ๛@N๗ญ|]> ธ’ใฎ!u๑-ธ๕ซศ/น๘ž8Lู;=฿‰‘3ษฬ+์#;๏ฃW$h>Œท{5ล๕โีๅ๗ฬt ูyŸ.๏K’_c k๋‚z+H‰ˆœแ์ฆ %""".คฺYvG˜JฟถNน๒ฆป})๙ีฟภsส:R๑ Sก[ 9แ:Ro*๏ฯฮๅไ–€ iœฆ๎ฯwfฮงH_๚๒พyล๒oํdพๆ š๖โ6ฌฆธ๗'๖wู๑J ฝŒฬฑ{ƒ0 ทไ‡ื๚‚z+H‰ˆœแฌฆ %""".คฺู ฌlฃf“บ่:์ž#ภvNพฉv๓๘ทเ6พOPS‰F,‚T›ไ„๋ษฮ๚8&[ _Žฦ:๙&ปุ‚h๋ษ0]:L…n๔”?"1z6ล ‘_๙Sย\c&๐ษ,ูนท“ผ่+(ผ๐kŒ“ฏ„=h2ษ3ฑช—ฌ7| w ๐J๊(m~โิ{UIvgHŽ_”ฏ*ฎฆmํฏะ+บy’cๆ’1ซช&‘ ก_"l9Šw`#๎Že”ถ->๕ž#ฏไุ๙df}ซช/กW$๗๘?ฟb›โOAJDไ ็3)‘hฤ)Hฅ&Lzๆ‡ฑฒ= '(พ๔Vท'‰ีc(v๗ๅ+oฺ฿t[;"‡xะต?}๔eLbุ4 ฯ’ยช๛ ‹-๑›ภgบ—ƒT๛วทBฏ„ำ{8‰ัsฐ๛Œฦ$2ํฃEXhฦ;ดฏ~ฅํK šž›ใl๊๛HO๛ณ๒•xนFš๗ฟ๐nน ^๗ R""g8)H‰ˆˆˆD#VA๊Šฟ$=๕}˜d–เฤ~ร;Kญฏcvicา0ษ4ฆข7vU_ฐNฎm[๑๖ญรพ” ุY˜2v‚๔Œa๗ a@n๑=7<พปใศ๎1”์ี5ึร๒๖พุ้สดือฒ! ฑz#9fv๏ปฃ•!Aฎภ&๚g)ํXJ˜k<ปวูๅB๚๒t\‰ื๒ภลฟp(H‰ˆœแฌ %"""8ฉฬ•E๊’wc’Yฦ}GwพŽ uสZC–ƒIU•รTฆGyฉNaชo฿๚r˜*4แซฏฮฦคืI“ž๙!์žร ๐ศ-บ‹โฆวภ๗bwูฝG’wGวzX๙g๎ร?ธ™ทดฮS๐ูป๓๘ชฎ๛๎๗Ÿ=žIณ„„˜gฬŒcใyสิดiฆฆอmฺไ6M“fhฺคฉดฝiโไIœฆMำด้“ฆ7O๛คNว‰ ƒ ๐Œ™ัŒ„@๓pฆ=ญ๛วBƒ ^ฟ๗๖ห>G็œฝืึพึ๚ญ ;„Uท {ฅำวซ’=xํฏโ6๏รmฺNฟผขk?@tๅ{FGโ ๔ฯ๐ปฏซ๓^)!„˜เ,”B!DnไU ต๑ฃD–>ˆfล๐๛Oโ๗4รฅŒ ป˜Œ ฆ0L๐\Œฉ๓/ ฆœษ—qŽ๏De‡A๙Wงำkฝ้Caะโป$Ÿ:ฮัง!๐๓๎82*็ฟ๕˜ี‹Ez๗๗ร็ ์;ๅf@)ฌkฑ็†^\=าžก`่ ^KธMฯใถ์ ฿VŽณ›~›ศŠw‡#๑:้๐{[ฎซ๓^)!„˜เ,”B!DnไS ฿๔q์ล๗กYQ‚พ6ผžfpS—ีd4˜า๔p*Ÿ ‹ŸT\Lน-๛qO์@นู+Liั"b76zq สห’ฺ๒Uœใ;@yw™ี‹ˆo๚รฐ–RคŸ๛nX| ๎3ๅป ๖์ Xณ7 Vž{1๐ ;ร๖jูผ๗M๏วุ๚นแํแHผพ6’?๛โU/คžkH !ฤ๗f ค„B!r#ฏฉอŸย^xš!่m )/fปœœ1e วJมŽฃลK0`X็3Cธm/แฟB‘/#vใั‹ชQNŠไ“_ฦmฺ yุ6k—ฟๅcSๆBเ“z๖;จกำaˆt…)฿Gณ"XณึcีฏA/จ8๗bเใดใ6์ยm}ฏํๅหุฦY๚@8ฏง‰แŸผ6๏ IDAT9ม@วuuK %„›%B!„ศ| คw~kmhfฟท%œฒ็eโงŽŸสงวKมŠกลKะๅcŠiC๊รk ๗ุ6”๗ Ÿ>zษ4ขซ฿‡^X‰ส“ล_แถ๎ฯห@สช[ElใวยํพGj็ทQร=จซX‡K)ะฃa05}%Zฌxฬ‹~Oฮ๑xญ/เuพไฯ฿๚ ์E๗ YQฎใ ?ƒืีy/”BLะ+@J!„"7๒*บ็ Xs6ข6~O3~o3xWjEผ‹Sv-V‚ž(Lฉt?n๋K8GŸF๙.šnpนลป•็`Tฬ&บ๊=่จ๔รO<Œw๒UR!๐kฤšนŽุ†฿ร(ซGyYา;Ž ู A ดkzผkึzฬiKั"็^ |ผ3วqoวm{ๅ’Vห‹฿i์w ™ผฮ#$Ÿxˆ`่ฬuuK %„R$B!„ศ ค4๗} kึบ0๊n M๛ฮžqมTขอŽกลŠะโc‚)ฅาx-๛pŽ?ƒ๒=4ไRร$ๅf0ซY๑k่๑2‚T/ษŸ๙eไ™Lฌ9‰ŒาZ”›!ตใoQ้h7l๔xึœ ˜U‹ะ์๘นํe๑Oล9ฒ๏ิมptw ึ[ร@ชใษ'Aฒ็บ:๏%Bˆ zH !„BไFR†Eม}Yฟอฐ๐ป๑๛ZภฟZSยฮ ฆ ฆ„มTด-VŠfFFž์‚แnึp?ƒ 4รโ‚)•Mbึญ"บ์hฑ‚แฎp5ทฎyyู๓7[๗แฐ@ป“"ฝ[ูกซถBแ„๛ีsPnณj๖[1*็ขYัsฏ;)ผฮร8‡Ÿฤ๋VŒถ•rRh‘ฌ้ซ0gฌม(ชLษ†]8'v[๛Aฬ๊ล ้8 ฯ‘z๚kจl๒บ:๏%Bˆ ๎H !„BไFR…SI๗็˜•๓P* ่n GH]“80>˜Š W…#ฆฮ†S† Jกœมเ)–ธ ฯA3m‚มำDVผ{mhVฟง‰ก๓)Tv8/ฃ่ช๗Y๙๋่๑R‚แž0 <&วЁc‚)฿Eaึญยช]Ž^T๚ู`J๔w€E• ็ศึp๚แ[อqr@J!&ธcH %„B‘yH•ิRp๏1*fกฟง™ ฏT0y~คล(ช‚HAX=R€ฆ[ ”“ย๏kรk๏ไ+ƒงˆฎ๙ึœแjnง1_ŸFน้ผ<Žขk?@tูปยzXรgH=๓(ŠษH>fŒฅ@aีฏฦฌ]Ž^Pš>๒>พW)œ†gIm๛*=p]๗H !ฤw ค„B!r#_)ฃ|&‰{พ€QV‡๒‚พ6Vฎํ”ฐ X1Œข*ดH!DโhV M7!Pูaพ6ฦ]˜ตห1k—ฃ&ฉร ไsy;'ถ๎รDnxZค`๐ฉํ฿mฬ(ฒษ๕ธq๎wi:zมฬ้+1k– วหF~wHe‡ศ์wœ†็PC](฿น.ฮ{ ค„b‚;„RB!„น‘7Tๅ<w)FI-สอเ๗ท๔ถ29Vฃธ:œฦgวั" จภEฅะ ;(ถ—๏ฯ‡Cw๒Plร๏Yršวh'ฬทA7&w๛Œ ฆt ฝh*๖œ[ย:ec Ÿป๎FœCฟฤmูึ๙๒ฝผ>๏%Bˆ ๎ H !„BไFพRf๕bw zq *›$่ภ๏mar#[ป•ย(Ÿ‰^\ฎบงแtCM~_+ร๕‚dO^G๑Mว^xwXซท…ิŽoฃ™‘ผhŸณŒŠ™ฤozขltๆศ?PูaผำGqฏํe‚ฬ ~^ถ—RB1ม=[)!„Bˆศ›@ชv9‰;?‡^X‰ส โœ kHๅSเนhv ฃb6zมดHœัฐรอเตพ€ฒ็๘Tf0ฏถ-พ๙Sุ๓oG3m๎FR;อŠๆี6ƒงA$๎8œ๊Œdณใแ ‰#SUzฏูCฟภ๋8ˆr’“ซ–ูฅ‹H !ฤEI %„B‘#๙HiX๕kˆ฿๑i๔D9AบŸ`เAษ|์๊‚C•bTฮE Pn•๊ร;sฏe?ฮ‰จl2/ถ)qื็ฐๆl ๋a9Fz็?Œn๙#๎Fณใ$๎๚ยŒ YQ์waV-ผpฤT_nห~ฦ๘gŽ_ี`J/จ เ`”ีฃฒIœ#Oแ6๎]%0šลฤจ˜M์ฦ‚fเ9Fj๋#๘o3 {ึอุ‹๏ งhF‹รขTfฟทท๕Eœ#[;ฏZO)!„˜ ฯ!”B!Dn ๓{”9ํฌk1งSš>๚z๊ ‹gŽื๑:AบTฮaดุอฟKd้ ภ๏mม๏m/“ง{]G/šŠQ9อŠ๔Ÿ$ฝ๛๛จห ุ”็€—A/™Žฝ๐"ม”๏๔ถเ6๏รmืu+?•O/ฌค๐]_C/ฉEe‡ษ|ฏ๕EะดอN„๛ว๗ 2๘ a;5‚sl;nร.”—พโ#ฆ๔ยJโท}kๆM็ฉฎ9ฏeuๅ6ศ@/ชมฌZš†ืy„ฬuลฟFe†F uฯ ฆๆ^ธ*_O๓h0ๅtŒuv้ก‡Q9‚ท=^ŠJ๕“y้?๐{๓ฏ]T€ฝเN์w‚ p›๗’๒UTzเ๊>X1๔ฒ:"Kฤšน=^2ฒG‚ฉŽpๅห†]x'_๛—ผู`J)!„˜เš,”B!Dnผa 5ๆแืžณs๚ ฬiหะ‹ฆŽ 7*3Œ฿u็่Vœฯข๔ซ1ฅN%~วgฐ๊VRm##p๒ดฯจ›่EU˜ี‹๐N$ณ๗_ฏZ๐0˜ฒ0ฆฬยž{+ฦิ๙Nๅ๋i ๋ƒ5ํฦ่ผฌัgfอ +ดhAชฬ Nะื–ํ๘ุKยัJจทaษญ_Ee“นyŠbL™Mไ†ทcี.G‹ŸkC'ฎœุ๚nำผS‡ฦ›—{.H %„\‹%B!„ศKคฮฑfญว™สงWL ŠUvฟซ็ศœฦจฬเ˜ฉFoŽ^\MโŽฯbึ.Hอ฿ฎ›่Eี˜ี‹๐NพBfฟƒฎ_ีฏ=L™U๓ฑfm‹ชŸLy a}ฐฆฝจdฯ%Mร4งฏ เ‡ั"ษ2๛xๅ ็’๏YฌY๋A8วwฺ๚สอํjŽzผc๊|"K฿†Yณ-’8ื†ู$~o๓่ส‰~wรุว(.5˜’@J!.N)!„Bˆy3ิYVZฌู๋1ซกUฌฆ ย็๎œcqžEฅ๚฿๔o4Jk‰฿๑9ฬš%แhžvำG๒wง๋ึศฉ0r[_$๓ย‡6ฆFืีค2C`F0ซbอบฃbึธฉ|๘.^ื œ#[รขฺฉ_LY๕kI๗%4;N0Mf๏†ป๒ฎY”๏]๙X3ึ†ิัm$ท>rอŠ็๋…•˜ีKˆ,นฃf šaŸ๛ญูpDขธทy~_ุ๋ว)(˜’@J!.N)!„Bˆysิ๘^ซn5ึœa0U8อއ+๓ฉ•ฤ๏nยix็ุ3c–ฒฟtFY=๑ป>9u~X{ #ฟ)รฉช…ธอ๛ศผ๘#4ำฮEW{ดํTfอŽcL]€5sF๙ŒฐํF(/Žv;๚tX<ัpฦšตžฤ=_@ณขCgH๏๙Tบ/๏šE๙.ฑ5๏วœพ็ศ’[ฟvmk•izQ5ึ๔ุ‹๎ญ;6๚›GpO<‡ฒŸ`่๔ฅmซRBq๑หฎRB!„น๑VFH]LญยšฝณfqLYฑpZเ‡5ฆzšpžร9พ}ฬˆฉ7อa”ฯ$q๗ŸbL™Rํ๙=eฯˆ WaN]€ธ‹์ห?†œRถ]L%0ช`อผ ฃ|ๆ๘โ็gƒฉรOโ6๎&ศ Œ+\oฯDฎฯฃ™‚มSคw•สปfQพG์ฦ฿ยœv>ูƒOฺ๖I๒„คc”Lรฌ[Edษๅ3ระ๗์oO๕ใuภixฏํฅ7\P)!„˜เr+”B!Dnผต@jด๛ฦุPษœถ {m#มTUXcJำ!๐ฒรแสnปqŽ>=fฤิฤม”1eNH•ฯ ฉพ6ฎใ๙ปำอFq5Fๅ|œ;ษพ๒šน]oฮฆฬš%˜๕ซ1สgิ )/‹๚ูCฟภm~• Wฆ›;‰;?†E0ะAzื๗ยข๖๙ฦ๗ˆฎ๛p8•2๐ศxœิ3฿šdOJ:ฦ”ูX3nฤž;FiธSAฒ๏ไ+8วwเตฟึpป ค„b‚หฌRB!„นqeฉ‹3k–bฯ฿ŒYณtd*_, ฆ|— 3Hะ‚ำด็๐Sa]ฃฐ+ศ๙ม”1u>‰ป ฃt:สห๔ตWฬ9ฯ˜Q๔โฬสน8Gท‘=๐ำqแฯ5่‚sA05}ๆ๔•ฅำวOๅsR๘gŽ‘=S๖์ฤo๛#0,พ“คw#\B1๔I'๐‰ปS็ƒ๏‘y๕1าฯ~gr>06Fๅ\ฌY7cฯฝฝธzฆ w……ฯ๏ภ๋<„rRใ^—@J!&ธพJ %„B‘W3:หฌZ„ฝ๐ฎpUพยส‘S๘Azฟทฏe?ฮ‘ญฉณต‡ฮ$fี"๗zqMH๕ถเ๗4ๅ๏Nทโแฉ)sp?I๖เ/ฎq ล๛]e†ะbล˜ตหฑj—ฃOC‹ฤGพ๎:ˆrำX๕kะ"๘ฝ-คŸ.uตทษD>๑ลจ˜R/'้]฿›NV ฃj๖์XณืฃL๗z0ุ‰ธ็ฤNำGQ^6Vๅ?\๖ษษP!ฮปฎJ %„B‘นคฮ2ฆฬ%ฒ๔ฬฺe่‰Š๑มTfฟปฏ๕%œใฯ ;ณf)‰{พ€^XN๋i"่mษ฿n'0Šk0*f}็8GถL’@jดKฮธ`*^Š9mYL•L;ทขbเฃ|7,ศฎ้#ิw๒ฒY”Rฤ7~ ฃ|๘.™๔๓?ศจHณf)ึ์X3ึข'สวn~_;๎‰ธ ฯโu7ขผดŒBˆ‹]O%B!„ศ\RgSๆY2LU.gฏ•ฤ๏mมk{ ็ุv‚มNฬช$๘K๔D9สMใw7๔ทๅogืN —ิ†ม}๕'8วถ„<“๎ืr~0eีญฦœถฝธf$Dณ๊››!๓โ๐Z๖ฃE ๓ฎmbท|ฃดๅ;d๖ฟd๖0ฟŽญhVํrฌ9ท`ีญD‹•œ{1๐๑๛ZqŽ๏ภ9พแโเ!น !ฤyืQ ค„B!rใZRgณย`ชnU8•ฯ)๊ํ{™žfใฯ]>๔โ๊ฐ~QOAษํ์F ัKฆa”ีŠ์ห…sb็$ คF5cƒ)ฝ ณ~ f๕Œ’i`Xฃ๏T™Aผ๖ืpN~wใรFๅ‡ไ („็ $B!„ศkH 9Œาุ้Kภžu3Zแ”ัSจ€`ธ •ซH!*3Rƒช•๙&ug7R„^Z‹Q:Pd^๘n๓๓hV>7็˜*ช"ถ๊=•๓ฦผG…กbชฏ๓0nรshั‚Iพi๑>^8ๅeI?๗]ฒฏ$฿Žฎq็„^8ซ~ ึœ˜5KฦcษP!ฮปŠJ %„B‘ื6๓ญieuุ‹๎มžu3zQ่f๘ฒ Fฆƒ p›๗ก2>„O๚ฮnดฃt:zษ4P™?ฤm{9ฌร”?[(‚ฌyทป้CaSyYPA*j:สwPษ‘`๊ฤ‚แ๎ษ;•O7‰฿๖I๔‚ ”›!ฝ๓๏ษพxพ>R;'๔’Z์Y๋ฐfmภจœ‹fE%Bˆ‹]=%B!„ศษHyˆ6 Œา:์๙ทcอบ9œv6˜แw7เถพ„fวั sย‡๐Iู•`”ึกWCเ“๛ผS‡ฮ– าXsn!บ๚ฝa๔4 œB/ฎF/ฎ>Wฬห ๗เwฤ9๑,*ี7&˜šํฆ้ฑ?…/C9)Rฯ-ฮแ'๓ัjพ5*faอ\‡5๋ๆ‡อช…ษP!ฮปjJ %„B‘“+ำ!4l๔’์น›ฐŽ˜ฅP™ažfผ๎tำ˜๐!|าm[ผฃฌฝp*้]„฿p6ไๅคฑๆl$บโธMฯ“๓}๔X1‘Žฦ‰•ŒิS('M0t๏ิAฦจtไ ฆฬ‰อŸB‹• ฒIRฯ<Šsd๋๕๒ˆ5n฿S็=\๔›๐\…โผซฅRB!„น1Yฉฑขซ฿KlGFK1nUท‘"็~ื‰p4ŽฎO๘>i:ป๑rŒฒ:๔ยJ๐=Rฯ~‡ ฟ}์fๅ ภšตŽศฒwเถ์#ฝใ๘}'ม0ฑgoฤ^pFๅ<๔h&(…r3ƒง๐ฺเ6?ึฃบึม”%q๛ฃE‹PูaRพsl๛๕๖จ(”๒.๛ไฮ‡ไ („็]%%B!„ศ|ค์E๗ฟํะฬ*r3h๑าsซ๒ึ.๒ป๑NEทข i<„Ozขฝฌ>ฌUไ;คŸ๙[‚แฎ<€ ซ~-‘ฅเ6๎!ต๓๏:ฮํ}3‚5g#๖‚;1ฆฬA†ฃม‚ๅฆ :๐:เ6ํE9ษkLiv‚๘ๆKe2 IDATOกE P™A’O๗ฤณืๅyฏ”pู'w<$W@!„8๏^ ”B!DnไC นแmฤ6~ อŒ t๗oD—ฟฃ|ๆธSสwz[๐NYQl๒’า ฆ„TขๅeIm•๊อฯŽปวฌ_Cd๑ฝ8'v’๙‚กำพืŽcอน…ศ‚;1ฆฬF‹ŒชWู$@^๛ซธM{มหไ<˜า์โท1šGฅ๚I>5ฦืๅy/#ค„b‚{RB!„น‘S๖Vผ;œฒgX'I>๙7x‡0Jk1๋oฤž;ฦ”Yฃดa$˜๊;‰ืyอฐC`Rl^85 คโฅ(7C๊้ฏฃฒC๙y™Q์Y7c/ผ ็ุ6าฯ~๗WŽ๘าb%ุs6†ํV1-gt*Yfฟฟ ฏ5ๆน ฆhฑbโ›?‰fลRฝคถ<‚ผ๗บ<๏%Bˆ ๎QH !„BไFิบ้wภ0๑๛ZIm^ว๋แ‹†‰^8ซn๖;ย"ฺcฆ๒กพถpฤTด,(šn^X…^>=VŒrR$ท>n:?;๎บ‰5o3๖อ8‡Ÿ"?ผแˆ/ =Q62•๏Œ๒™##ฺ*;Œ฿ำ‚ื๖n๋KธW7˜ |๔ข*b›>Žฤ๎"ตๅซธญ/^—็ฝRB1มI)!„Bˆศ‹@๊ฦ฿"ถ๖ ›๘=Ma ีy๘ผคŽ^4ซvyXซจjแ๘` ๐๛;ยฉq^– wMถG/ฎม(ซ?W<{หWQพ“ง=w {แ=ุs7=๘้]„J๗_โฮ0ะc%a0ต๐nŒ๒็ฺM ฆšq^ฤk{๏ชSส๗0ส๊ˆm๘0:M๒ฉฏเ|ๅบ<๏%Bˆ nkH !„BไF>Rฑu&บ๚ฝ ๘]'Hn™ccปŒ &๔โjฌฺX๓nลฌZ„fวว}^0E0ิnš =›ำํั‹ง…มหH๑์ิ–GP9 WLนแmXณ7}ํงค๗3*s™Su=Q†=็์๙ทฃ_L แ๗4แถผ€ืฺฆ”็`Vฮ%บ๎รฃตส’[พ‚ื~เบ<๏%Bˆ‹“@J!„"G๒"ฺ๐๛DW:h:้ฃคถ~ ฟปแbH.Lอ€YฝxL€ ’=CgภMค!Gฃ”๔’้แฉH‚ ีG๊้ฏAเ็ๅ๑ฃ|่ส_วšq#ูW#ฝ็_Pูแ7๗#S0ํY๋รSๅ3มSด>3ˆ฿ˆฒฏUP๊ŠSสMcV/!zำ‡ะ ฟฏิ–ฏเ:t]ž๗H !ฤลI %„B‘#๙Hล7‘e๏ ฉSI=užๆ_ีd\0UT9m)๖์ ˜5Kะb%ใค๚Pร]จ์๐H0•ฝชฃ—ึ…”'๎&ตํ‚ ๒๓ |"ซƒUท€ฬKAf๏ฟขœิ[๛\รย(šŠ5{ค๘yY=่ฦ่ห*;Œw๚(^ห~ผŽpำ[ ฆ”“ยœพŠุš๗‡ตสz[H=๕7xง^—็ฝRB1AB)!„Bˆ˜๔”ฆฟ๕D–พ 4 ๏ไ+คถ}ฟฏ๕R˜qมTa%ๆดeXณnฦœถ=^6!=3D0ิ๛*SzษtŒŠYhV”`่4ฉm฿ไชญwต)Et๕{1k—ู๏d๖u…Šดkfฝฐk๖†ฐ๘yู ะดs_?LนM{๐G๊Šฝ™`Je†ฑfDtีo†TwษงพŠ฿uบ<๏%Bˆ ๎;H !„Bไฦคคt“๘mDd๑} iธญ/’ฺM‚๖ห้^rA0UณkๆM˜ำ–กTŒXw’ƒจT?Avผ+L้%ตSๆŒึ*J=๓ญ|๎บ]>ฬiKศ์W2/ๅfฎ์ท˜‘p5ลน›ฐ็ŠQ:๔1S๙ฒCa0ีฐ ฬQ@ปฌ`Jeฑๆl"บโืยโ๙ง’๚~wใuyK %„o$B!„ศษHif„๘ๆOa/ธ3 คš๗’ฺ-‚มSoๆำL%ส1k–`อ\‡Yป ฝ` h๚น‡v'I0ิ…J๕dมsธ#™ฦR~_+ฉ‡6fิO^ัuขซ?€Yฝ€๔ž๏“}้?Q^๖ชzษ4์9ฑๆlย(ซ฿fู!ผฮ#ธป๐NEณbhฆ}ั๖+H๕Yx'‘บ‰ืyˆิ–G๐{[ฎห๓^)!„˜เ>#”B!DnL๚@สŽ฿วุ๓o4†็Hํ๘vXŒอ*cƒ -V‚Uป kฦ˜ำn@/จ_H;›$H๕ ’ฝแช|^–ทL้%ำ1*็„ลณปI?๗ใB•ผbุDืผs๊|าปพG๖ๅฃฎrxอŠข—Lวž}3ึ[1J๋ฦOๅsRxฏใ6ํ!H๕ž7สํย`*H๖Y๒‘ฅ„ตสฺ_ k•๕ต]—็ฝRB1มE)!„Bˆ˜๔Tค๘ํŒ=wฮฑํคŸมp๗•ฎhๆดฐfˆUป ฝp*ึน‡x7C์B ๗ค๛มsห/Fn”ึaL™†…ๆ8้]8ฎ`w^1"ฤึ~ฃr. Hํ{ฒฏ|77ว‡A/ซรžฝk๎-%ำ/ ฆฺ_ลmฺK๎›p๚e0Cdู;ˆ,พ7 คฺ^"นํ—954H %„W$B!„ศIHลKHฌY7เ~Š๔sŽzนฒ฿ฤูQ3šวฌ]5cm8•ฏจ อฐฯ=ฬ{‚แTฒ‡ ีพsYซไ้ฅu˜#”ืyˆฬž๏ซ‡”Ww+Ftํ1*f Hํ๘6ูื฿หํ๏0#3ฑfoฤšฝฃxฺ…ซ๒uผŽธ› 3pA0${‰ฎx7๖‚;@ำq[๖‘ฺ๖่›œ:๙I %„O$B!„ศษH้ฤo4ึŒศพ8้฿Gฅ๛ฏVW”ั้\บŽ–šฑณf zQ5š=๗P๏fย๚Rษ^‚dฯHฉ7ฆ๔า:ฬสนaญข๖ืH๏๛Wด| ค"Dื|ฃ|ฉํ’=๔$ต๙=vฃlึœX3oย(ฉ=/˜ย๋8S้ั•Uฒ—ศ๊฿ฤž{kH5๎&๕ฬทโิะษK)!„˜เ>"”B!DnL๚@ชp*๑;>ƒUท €์ซ‘~จฬเU๎‘j ฦSkรU๙ช†ม”# ฏยโ็*=H์ ง๚ฟj*ŸNูซœบ‰๚"ู—๓์Gๅ_ว=Zސ*พKr7pŽlภฟถฟหŽc”ฯฤšฝkึzŒ’i็ฌOแ|ทแ9Tv˜่š๗Rฮ๑คw|; ฏCH !ฤ๗ ค„B!rcาR%ำHiฬฺๅd^฿d๖•ฮUื”s#ฆ ฌ๚5a๑๓๊ลแT>;JกTLฅ๚†NS็ํ^M™ฒ7; คšž'๛๚ฯ!p๓๒๘ัใeDืผฝคๅeIm}็ุ3—5…๑jถ™fF0ฆ.ภšu3ึฬuลีใGL9)ฆ็q›vc/บk๚ส0:ฒ…๔ณ฿ฝ SC' ค„b‚;ˆRB!„น1ู)ฃฌž๘ํŸฦฌY(2๛ฬ‹ๅคrEelธdีŒ˜ชY<2b๊l0 œ4*;Sƒงฦ๘ึอp„Tล,ะ ฯโ†rำ๙ูqOT[๓~๔โj”›!๕ิ฿เ4<{ntูตuŒ ฆชcฯ€Yท ฃจzJŠ้~@C‹‚ฆ“}็คŸ๛nƒฯ’@J!&ธsH %„B‘“>š2—๘ๆObV-ฅH๏๙>ูW๋8็Skฐfฎ GLWกู‰0˜ |”“Be†Rฝแˆฉภรย(ŽQRฮัm8'vLธ๚dงV]๓^๔ยฉ('E๒—$ ค.l3อŽcV-ยšฝs๚Š‘`สบเ/ฦ=คw~OำuyK %„1$B!„ศษH™U‹ˆ฿๖ Œสy๘คw}์kบๆฮ๘`สœพ2}Sณฝpd*Ÿ>Le† †Nใ๗ตขY1๔ยฉSf‡Sร็๘3y{่%ำˆฎ|za%*;D๒‰ฟฤm}‘ ฆ*NŽวŒั฿ฅE˜SŽSซ0Šชฦ˜"๐p๗=๐3๎†p5ล๋ˆRB1มB)!„Bˆ˜๔ิดˆ฿๚‡แ7฿'๕์฿ใล$ค&๘ฝำWbฯูŽ˜*œŠfลFƒฉ =€฿‚Q\ƒ^4ะศ๘)ฮฑํใV๏ห'zi=ั•ฟŽ^PJ0๓‡๐ฺ_crRฃฃฟOณb˜ำn๋Gอธ๑‚vP™Aๆ}d>฿ำŒJL๒mป4H !ฤw ค„B!rcฒRV*bท฿ๅ3PžCzว฿แ~ ๅ;“zฟšำW`ฯZ9ํ†ฐ๘นMC๙.šf€aูW#{เg่…•yyๅณˆฌ๘5๔D9Aช—ไใ_ย;u(_;8.™ี‹‰฿๙YŒาบ‘้†jช|Aชฏe?ูƒ?ว๏iAe†ศ็`J)!„˜เฮ ”B!DnL๚@jๆ:b?ŠQZอ-œcฦ Ÿฤฬšฅุ๓n ƒฉยฉhvl|ะ1ุI๖๕'๐ปŽ“‡Q9่ฒwกลK’= ๔ฯ๐ฯฯฟํ(ŸIŽฯ`N]€๒‚พV4+ŽVPfFFฅ†ฮเตฝL๖ภใ๘}m#Eฯ๓ฏ$Bˆ‹“@J!„"G๚ฝ]Mๆj{ฮ-ฤ6^ธŠ›“&๕๔ฤiุ พ—W๛ูฌZˆฝ๐nฌ๚5แh(_|‚T/~O~วAผ๎†ฐ๘y>P ณf ‘ฅoC‹ a๘ฟ4/ ›ี‹‰o$Fล,”“&๓โ†บฐ๊VbV-LAฒท๕Eฒฏ” $สI“Oม”RBqqH !„BไHz็฿+ทีI;ชล^p'ฑuฟƒ^4•&น๕ฆ็๓'ด9Oไ†ทป้Chฑโ‘d€pๆ˜๏ค๛๑ป›๐;แ>AึŸšฌs๚J"K๎G‹ œb่'Bะ2๏ฺลฌ]NึO`”ีฃ|‡๔3฿"{๐h‘BฌY๋ฐfฌลœบญ อฐร?๒]‚d7nำ^ฒAะืŠ๒๒!˜’@J!.N)!„Bˆ\=˜บiๅwภ9ถฏ~wรค๚}‘%๗ฝ๑ทยขูฉ’[&\ล-๐๓r›ำW„มGi]8า&;Œfวัฬ0ไPพ‹J๕ใ๗4ใ|ทใu4 E '฿ฑใปX3ืYt7š]€฿฿ฦ๐cB0t:๏ฺลช_Klำ`”ิข4ฉ฿ฦ9๚๔่ิP-Z„=็ฌ๚5•sะโeฃ#ฆ”—%๊ยkK๖ะ/๑๛ZGF๐Mg ค„โโ$B!„ศแณ)€r3๘gŽแู‚ื๑z๘P= ๚d‘e๏ บๆ่๑ฒฐh๖“_ฦ;๙ จ /wถ5c-๑MG/ž†r†ษพ๒Zผ๔\๑๓ณำย| ‡฿ำ„ื๖2^๛ซ€6ฉ‚)ๅ9ุs7aฯฟอŽใ๗63_Ÿ%H๕ๆ_ปฬ@|ใGั‹ชQN’ิ๖oโ฿92๏\๑s=^Š5wVŒŠ™h๑า0LT ผ ม@n๋‹8ฏ?฿rางH !ฤลI %„B‘ณP!ซฮmG{๘งแ†ื@ว5]๙DVฝ=VL0M๒—w๊๕I–ฝึ์ ฤo๙za*3ˆsl{2ฉ-V‚^:#Q†Aเค๐ป๐NพŒืZุažม”rำุ ๎ยžwšล๏n`่วŸAe‡๒ฎ]์y›‰m๘zA%*3Hj7pwMx์๋…•Xณ7`ีฏล(Ÿ+ง๒ฉๅฆ ๚รS~J0tf๒๗H !ฤEI %„B‘#™ฝ?Pึฬu่e๕Œ ฆ4ฉC8GŸฦ๋8@0p๊šŒ๖ˆฎ ัๅ๏B‹ v’ล_โ>F>ฎl`ฯ฿Ll๏กTคpwซIคแ๔ฝH!zแ๔x9ๆHƒ#มิqผ–๐ฮ฿นฆม”rRD–>ˆ5{šaใ9ฮ๐?…๒ฒ๙ื.‹๎ k•%*าคถ>‚ผ๏ yฝฐ{๎ญ˜๕k0สg G‹@7!๐Qn ฟ$nำ^œCฟ$๎š4+”B\œRB!„9า๗ญ•9mV*ฌ๚ต่euใƒฉ์0^็!œ#[๑:^G{ไ0˜Šญ๛0‘ŽIเ๗ท“|โa๎&๒6Ztฑ›/๔x)Aฒฏํๅ‘m9ป=่&šE‹กTŒ1ฅTzฏปฏy/~w#สM_“`Je†‰ฌ|7ึŒ›ะ ๏ิa†๛tญ€Y๚`Xซ,^F์!ตๅ+ธm/]๒H<ฝจ{มํXuซัKงฃG ร0ั๗ฒƒ}mธอ๛pŽlม”RBqqH !„BไH฿ฃ›รŽ—ฆaึฎภช_ƒUท ฝคอŠŽ †๐Nฤ9ฉƒษžœSฑ%ฒ๘pJXo ษ'ย๏;™ท๛;ฒ์ฤึZฌˆ`่ ้ฃเeนhภfXhf-Zˆ/ร(œ:fฤ”Be๐ป›p›๗โwศy0ฅ2ƒDืผณn5šfเuผฦะcŸหห๚^ั๏&บ๚}aป w…ตสฺpนมงQZ‹ฝเ.ฬบUล5h‘่FLe๑{ย๖rn#H๕]ณํ•@J!.N)!„Bˆ คF{b:Vjฬ๚ีXำWข—L?b*3„ื๑ูCOโŸ:Dธz5ฆ4๘ฆ?ฤ^t7šaใw72๘—๒rท‘ "บ๊7ˆฎ~/Zค€`เ~_*3๐ซฬฐะฬš@+šŠQ0%œvถMฒC๘] ็‚)'•“`*Hป้w0ง/ภk{…แ|^ถLtอ๛ˆฎ 4;N }๒ฏ๑:ผ้ฯ3สgb/ธ#1U\…fลAำยUำ๘]'p[_ภ9ฒ•ฮ๙๖J %„ฉ%B!„ศ ฉั'jซn Vฬฺe่ล5c‚)…JเuผN๖ะ/๑N ชฏt0ฅฤ7 {ํแœฎใ$๖ลk:ฒไญ๕r๕ฐ&ึŠw‡#พ:๚Oข2ƒ—ธ?ฌp*ŸE+ชย(ฌL9)ฎใธอ๛๐ฯG9ษซL้โ๋?‚YsJ๙xญ/0ณ?ฯว†!ถ๎ท‰,{'šร๏?I๒—฿uโ-ฒ1e‘E๗`ึ.WQuจ<•๊ร๏ƒD็ุv”“สูK %„$B!„ศ ฉณtkๆMa0Uณฝธ๚\0ฅ‚T^๛ซ8‡žย๋<„rำW.˜2Lw|k๎-h่x‡ูฏษˆ’+B7‰ญ๛ฐ&–iใœ"่mE9ร—9šGณ"hS0Šซ/ ฆบรSงขZคเŠoN๎'พ๑0ซขทiษ'G>}่ฤึ.‘ฅo ฅท•ไ/ฟทๅ ตปY9{ัa0UX9z)7ƒJvใuภm‡{bgN‚) ค„b‚[‚RB!„น๑†ิhMรžณ ณ~5fอ๔‚J4+h๘ษž0˜ฉ1ฅ<็-ืาฬ๑ป>=k= ๐:0ำ/ไๅ*n๑ ฟฝไ~4ภ๏oว๏m๗Mบ‰f'ภฐะ่%ี็V์#\)ั๏iฦmฺƒ฿yๅ9hv๔ŠmŽJป๕˜•๓Pพƒ๐ษ'ฟœํข›ฤ7~{๑ฝh†N }โแpeษ+๖„ฃก6ฦิyDScŠี+/K0ิ…๚pL5๎รซD)!„˜เr-”B!Dn\r u–abฯฝซnFีb๔ย)hฆ haแๆd7ษWศŽS%ฏTvAงะŠ‘ธ็‹X3ึ Tึ(๚ูฎ^อชซษ5#ฤ6๖ยปะ4= คzšมหผต>L้zAลyำ+รฐร๏iฦk~ฏใ สwฦฌณTf๘mŸย˜2ๅfpŽ๏ ต๕‘kร&v๋b/ธM7๐ฮ#๙๓‡†ปฏย—้hV4œสทไ0˜Š—ŽŒpS(7K0|ิก0˜jฺsUX ค„b‚หดRB!„นqูิู›ลšฝkๆ˜S %สGBึวI๖เถฝ„s๐—x‡ฯ>_wD$๎๛ ฌ้+Qพ‹ืฒŸแวฟ”ฟ\+Fถ?ยžทเ$~w๘ฮ๚-RšSฅำว˜ยw๑{[pwใu@ธเ๊r)'EถOb”ฯD9)œฃO“ฺอk3ึ*iฏ๓ร?•๎ฟŠ_ชฃู Œส9D–>ˆYฝ=QšžCn†`๐4ฉƒธMฯใตพpEƒ) ค„b‚หณRB!„น๑fฉัŽ›วž{+ๆŒต˜Sๆข”„ cชOพL๖ะ/๑ฯฟผฯŽRpร˜ำ–…Sย๒ตFั˜}ฟำุsnเ๗ฤ๏i G‘]QzXฬ\=V†^^?>x <พ6†็p^ รรธ์oQ^–๘ๆOa”LG9ร8‡Ÿ"ตใ๏๒ธ]6‚Rธํฏ‘๙_ไฆศธฆฃลŠFjLƒ9ํ๔x  …๛ุอ žย๋xทy/nห>๐ฯ/—๒ŽถRBq๑หฒRB!„น๑Vฉัœล^x7VŒ)ณัb%ฃฃs”›&่ภm}็่ำ—ผz™+ฆเมฟ‹fปY†g๓ณFัูํ‰’ธ๋sX3oF.Ao[HฝลZ[ฟ๒;ฃE่๑ฒpฤ”?๗bเใ๗Ÿฤmzทe?่šฆ]๒g+7CโฮฯกWฃ2Cd‚๔s฿อรvIธ๓OฐfฎเถฝL๒๑/กฎิศตKก่ฑŒฉ ˆ,บณvY8ฺํ์พ๖ฒxm/ใถ์รm{้-SH !ฤ๗ ค„B!rใJRฃ9;Žฝ๘^ฌบีณัbEhบสG9iผึpŽnร๏i๚ีฯ่๑R ๖`Lrำ8Gท‘z๚๋๙ษ‘ธ็ฯฐ๊ึŒRญ๘ผูQ.—๛(…/E/ฉ GP๘๘ง๐š๗โ6?BCำ๕7L•M‘ธ๗‹่…•จ๔ู?%ฝ็_๒ฐ] IgX๕kQม˜ฉกืโ™DำัๅS็?_6.DT^– ฟท๕Eผ–}ธํฏพฉ`J)!„˜เ2,”B!Dn\้@jดC/!ฒ๐nฌ๚ต่ๅ3ะ#…`เ๛(gฟฟฏ๕ฒ‡Ÿณšู๘j=QNม;พ‚Q1+ฌQtd ฉํๆo'7^Bมฝ_ยฌ]Ž๒‚žๆ7 ๅฎ๘oˆ๒ัโ%e๕ใFแ ม`'nำnๆฝa0๕+FL™! ๎ฝ ‚ ีG๖ีวศ์๛ทk—XqX<ฟn%ส›$SC5 ฝ`JL-นณj1Z$qฎฉ An๋KธMฯใw3ข๋ƒ) ค„b‚หฏRB!„นqตฉณ๔D9๖ขปฑfฎร(™ บฎศ—$่mลmูsd+มpืธjฝฐ2 คส๊๙ูป๏(9ฎ๛ภ๗฿[U{ฆ{ยƒH3)f‚$DQYTX{u,ู–d’`ฏณฝึP–ร๓yปฦฺฒฌณ๖ฃd[ฯkหส –@`ŽˆŒม Ožžะฑช๎}žˆ ™๎ม๏s%Q“บBwU}ฯญ[ฆœงฒ๗! ปถnืต“j!๕ึNผ•Wู‘.C๖){‹qยKƒ1จXทuรไญ}€ Sใ}๖Vพ๎'1กrfฮ1eยฉ๛'ู„. Q~๎‹”žื๚.ษ&Ro๙ชk1A๐#ไฟ๓gต๓๚2ํx+ฎ บๅx+ฎœฆ‚2z๘8๑g๑>Npf฿ด9ษๆSค„bžใฃ)!„Bˆ…qฑƒิไEuช…ุ5๗Yw+NถI€r1ฺว”ฦฺI›?‚๋ซ^ˆฏคแ‰“]…)S๓ Š~ถnืตำฐŒ๔[จ‚X":†๊^MกชO็sšVแ$›˜˜Pcะcฝ๘วžถaส/ฃ\0˜าธQาo*‘EPz๎P~?๊oปคZHฝํผWฺ u๐‡ไฟ๗—ตv‰„“]…ทb ั-ฏวkฟfฦD๕&ฌุธ{๔ ๎'z€'vv˜’ %„๓|ฺJB!„X ค&/Wป๖ํDึ„“iGEโ€ฒaช#่ย?๖•ƒ;!(ั๘๓/Nรr;i๖พJ๑๑ฌuํ4ฎ }ง์-ˆ~=tŒp่Xmผธh '‘EE“จdNผัŽd0=Opโy*]ป1…aงค฿ฺ‰Š5 ว๛)=/”๔ต๚. หHฟํOp—mย๘%{k่ชv_ov5ส+‰^๑zผUืL><&ยิ1*Gvใw?I8pdฮ9ฆ$H !ฤ$H !„B,…RฦNvีด0ตrrด‡ ส˜bŽ ๗:wŠ่ๅฏลi\)RzแK”ž|ฎk'ำN๚ํjoAฌ‡ฃk%HMˆ$pRญจH•hฤIdภ๑์ืŒA็Ž?Kๅเ!'u฿๏ b)๔X/ฅ'‰๒K฿ชฟํ2+V^๚6…‡?]๓ฏmZƒื~5ั-ฏว]~ขcพ IDATลู#ฆปm˜:๚8z่๘Œ9ฆŒ๑%H !ฤ\g(ค„B!ฦโฉ‰+j7ณŠุีo#ฒแTบerด‡ ส˜J†‘HSศQ|๊๓”_ (ต8O@{ีกƒ๔;'ำnƒิะq๔๐ฑฺ|ฑ^ 'ฝlž0ฅัใ่ nำj;Bjไ ล'คฒ{uท]œL;้wnำLฅ@๙ว_ง๘่฿ืฯ~ีฒพ:b๊>e—aซLPถaชk7~ืc„ร' ๔e„”BฬC‚”B!ฤYิ eOPnงฉรฮ1ตVœTหTภ BŸสกvnŸ—™งฆรA๓Zา๏ { bู>ipั็๚‰/:Šำฐ IขโiœDธSaสn=ึgƒิ‡๊๎=0;–_2ลวก–ฃuสซˆnพwล–ท๒๚„ƒGฉzฟ๋1‚แc4ฺ:ๅP!f•HB!„X‹ค&OQ‘nห:ขW฿Odอkpาญ œษ๏0…ฑ'๑ปŸย?ŒXป๚ณ๕ฆึ ค฿๙แคZ0ๅ1๔ศยมฃ๕ฑฃ8Nใrฆb จD#ส‹25บ&8๓ฅง๘3v{ิษ9ฝฒฮฉj(,=ลบพ5ิm€ท๊Zข›ถแฎธbV˜ ป(๏}่ไถ_๋”O@!„˜u6"AJ!„baิNš<DEธ-๋ˆ฿๒๓Dึ:ใซ&(cฦ๛ z๖แw=ŽiL9?๙ณตฆๅ›ix๛Ÿฃ’YLq=ฺCX๋#คฮฺ^Ÿ;ŽใแคZ๑V_g}โ] ํƒž}T๖่c5ฆe›Hฟใ/p’Mv๒งฟ@้น[2๏qw๙f"ซฏ'ฒq+n๋†‰9ฆ:ๅP!f’ %„Bฑ@j9HE.ป‹ิๅละ๙A๔hNบ งaูิ7้=ฺƒโ9ฃOœ|ใ—&N+ฉฅ0ๅu@๚ญŸดOฅ+ฃsgะน๕zสF๒Pฆ<ŽฉPฑ4*j'ี6AS&่=€๐‡TŽ>aPsKโญุbCa"ƒ)ๆ(>๕ฯ”_๘า’{ฏ{ห7ใญพศ๚[!ภ[ถนS>…bึัM‚”B!ฤยจ้RWG๊พ฿ืC็NQ|๚_Žฟ้ฝD:n@ลงพY‡่ั3๘วŸล๏zœเฬLฅ0qzI-„ฉศบ[IฝๅQ‘:?„99Uงg์ส‹น์.ป๚sง1~PvR๚hข:วฟ\ S๛๑๏ขาต{Z˜Zmใญบ–๔ŸBลา๖iŽO>H๙G_[J—W3ึฑปl* แงWง| !ฤฌOL RB!„ ฃ–ƒT์ช7“ผ๗7ภ๑‡OP๕ท๘Oก’Yผe›‰^๙&"ซฏ?kฃpด‡เฤณ๖ibง\3#ฆ"ท’zำN๘99]งg์.*09วW˜;‰:(T"ƒ“jEล’เฦPีง๒™ ‚ษ๔ย?(•#ปj"LEึผ†ิ[@E“่ ฅ'คผ็›K๑2kr<ะผ}Wง| !ฤฌOJ RB!„ ฃฆƒิตo'นํื@9„Cว(>๒w๘OM~I6ใ.ฟœ่–7Y๓T,=๕รFฃGNใ{šส‘„g^ยๅE]ž้sb้๑~t๎4zฌง>wวลIถเu@8|; އrLขขITฒ ๅล์S๙œ`์ฤ๔๙!ฆบร?ดkQ็Šฌฟิ›ศŽ\๏ง๘ุ?Pู๗%พ— %„s“ %„Bฑ@j6H)E์บB๒žŠp หฉใฯž๕ญNชwลbWผoอkPัไ๔Kot๎•ฎว๑>NุณoัยT๔ส7‘บ๗7ํ-ˆc}v„ิXo}๎8އำฐฏ*๔๐qยi”™๑m& Q‘„ Rฑ4N<ฎŒ_ชŽ˜:‚฿๕•C;!๔'ทBM„ฝ์n’o};rmฌโ๎ฯR9๐ƒ%พ— %„๓œ~HB!„Xตคโ7W[P„‡(<‚S/ฮ๛#NชoีตD7฿‹ท๊zT,5œp๘~ืฃ๘GŸ ์;8ํVพ…ปๆ~;โหqัฃ=่‘S่๑๚qงฉoูๅ„Cวะcฝ(ว๓Q^•ศขโ 8ฑ†j˜ยŽ˜ ่;ˆ฿กำขแล15cไฺ่Š~–สก‡—๔๛^‚”Bฬs๚!AJ!„baิlr<โ7 ‰?@ะ{€โรŸ&8๓า\งLNร2ฆ6mรkฟo˜v%ฎ s'๑ปว๏ฺMุwhมFLลฎ)’w ”šœ?J็๋sวq"ธญ๋q[ึvฃวPŽzู3:DนQ{+_2‹M3-Lๅ‡z๗แ{ฟk7ฆ46็6พfŒ\9Maื฿แwํ^า๏{ RB17 RB!„ คfƒ”๋‘ธ๙็ˆ฿๚>‚3/Qx๘ำ„ฝ^๎4’™ajy5Lƒท๊Tlz˜2„นS๘‡wแw=J8p๔"‡)E5๏ž๑ฅsงGNa ร๕นใธถMธM„ƒGซAส9งuat0ฆœx#(๛ณ&(c Cฝ Ž?CๅศnL17๏v~ตฆ\ณ“็ฟ๛ษ%พ— %„๓ก$H !„B,ŒZ Rสฟํฤozมฉ)์4แภ‘s๙iฮ SซฏทaชšYท๒ู นC;๑ป#์พ8aสq‰฿๔žษ_แ๐I๔ศฉYกฅŽธQถธMk์๒ ta๒ƒpNAjj; œศT˜Jfซ}taˆ ๗มฑง๑ปG†ๆฮฏT์บw‘ผ็ใS“็?้9็*[J$H !ฤ9k2๘Wฆโ7พ›ฤึ_e'ฯ/M8|๒•6f„ฉL;‘ต7ูp;๒-gฯ15tœJuฤ”:Ž +ฏ~yf๘ ‡บันำ˜๒X}๎8^ทe-n๓:ป<Gะ๙กWคฆถ“ั!J9จD•nลIdง} ๓C„ฝ๛ํSวžBœ™w;Ÿซ๘อ?KโŽูๅ่;Dแแฟ!8ฝgIฟ๏%H !ฤOุฃiœl;nหzป<9HM0Z9ฆRอี05kฤ”_"์;€d7‰็f…ฅณร”๒b$๎0ฑ๋ํญ”ฏl๒๚#AJ!ๆ9พIB!„X5ค–“ผ็ใD6n ผ็woLi๔bž†2#Lตฌ#ฒแN"k^ƒบมŽ˜ช”ํˆฉ}฿ล๏ฺฮ‚็_žT ‰{>>ุ๔๐ ‚#–๋rฟQฑค&&5๏?‚)^ 5มhBกRMจd NrฺS๙&ถO*‡~Hp๒Eย#ฬ5JJE$ถฑk฿ผฺษ๓๋‡)!„˜็๘&AJ!„baิlสด“ผ็Wˆฌฟ €๒‹_ก๘๘?bส 1 ๘ฌ0ีบศฦญD:^ƒฒ๖์05ะEe๏C๖ฉ|…a0๚์ๅiXf—งุยIยพƒ็u_Mฐวqฒซp›ึุๅ้?‚.ๆชGM2:Nฒษฮ3•ศ€ใN}=ฌล?ผหŽ˜๊;4c๛จXŠฤึ_žผ•า๏ฺMaืgf=ฝo้‘ %„๓฿$H !„B,ŒZ Rnำ~…ศš›(=๗๏”žฆRXศำRf„ฉถMD/Šืq#n๓T,=๙=ฦ/ู0ต๏ป๖ฉ|…ŒŸุยมฃ„GAืiJdp2ํำ‚ิaLqd๚ ฅeย”ยIdQษ&œDธSaŠ0 >Fๅะรวž&่‚ะGEโ$_๛๋Dทผธะ“็ื. RB1ฯ๑M‚”B!ฤยจู ีบไ=ฟ‚ท๚zJฯ”ž๚gฬขL>3Lyห7ูtชkqณ6L)ฦ`*ใ๖Vฑ฿งrไัษ[ ฆ~u2ฐฝะน“็4TMžฐ'špณํ8ูี„}ซฃืww2a(œD•lฒธ‘้฿aoต<ด ศ#˜ržฤœœซฒ๛{{ ๆ&AJ!ๆ9พIB!„X5ค–mฒAชJOฅงฟ€ sฮฅ9ยิๅฏ%ฒ๊:œL;*šดท‹)๔กฒ๏ปT๖ทi ษื:^ว ง~„๏ฏ฿ •lถA*ณ 0„ฝ1•<‹คฆถ }ภฑa*‘A%›Q^tฦw‡]๘วŸลkปlrป”๗|“โใ€)ไ–๔๛^‚”Bฬs$‘ %„Bฑ0j5Hy+ถธ็ใx+ฎ ๘๘?R~๖฿0aฅNW™ฆV^E๔๒ืโต_ƒ“Y‰Š$ภq ัๅQ‚“/๖!ฒvผ๖ซ๐=moq3a]๎7Nช'ำŽ“ic๚ยขฉณทฯD˜RัสโdWUoตฌ Œ Q^ €๒K฿ฆ๘ศg0ๅ’~฿KBˆyŽ ค„B!ฦ๐_รฺZ{]ชkH๕1ๅ›(>๚YJ/|ยZQ4+LญบŽ่ๅl˜j\aร”ใ—1ๅqT$f'DวฮUDX™s๔zเคpWโdV‚ัฝภ/ิุซœฆ*–Fลา8ฉ–™aช*์;D๑‰ Nฝธภ๓•-, RB1ฯ‘C‚”B!ฤยฺqwง2v2ต๒šผŽI๕หธm—†ยรŸกฃฏึ่-nณยTวD7฿‹ื~5NชMT+“O็๓?‹)ƒฎำR้eจL;nใrะA๏AŠ5๚j็1•h@ES๖้|ีH8A๕แ}‚สม$8บ@Ov\Xค„bž#†)!„Bˆ…•ฑ-ซัk%LEึBb๋/แถฌฃ)์kส{พYW'ฒๆ&ข[^ทโJTCสšรศ”FGz0ลฆฆN…ฉ^žำฐ'ณงa„A๏~ห5ชงญ[Sืh7ณ?{—ื๙AฃSู๛ยกcK*LIBˆyŽค„B!Gญ„ฉศ†;HlEฆ5  ?๘+ส{‚:@8|โฌ๙คj;Lู๕Vเค—aย a๏{ b}\nLฎ[S)โดฌรอฎbยŠ ‡ ะ…!‚๎ง(๏๙แะq;y{_ฏHBˆyŽค„B!Wnวถฌ1fŽ๛ล๘๛ัM๗ฟCธMซ!๔ษฆฒ๛ิร่ก9—็Š๛H๙œt›F‰ฯมT ่ฑ>ยแใ๚ณๆ•ชอ0ๅdVแ4ฎภIทb‚ฒ Rฺฏปํbทyœ= WŸศCESเz฿‰$8๕"ๅ=฿$์?\ืaJ‚”BฬM‚”B!Dศํุถฮำนะa*บ๙u$nœL;&(S๘๎_ุ‰ภ๋Tt๓ฝ$n ]žr=ึ‹Jdpp<ภ`ส๔่iยมใ`fฯ•U[aสษฎฦi\Ž“jล๘%ยพ5:ฟืห3aˆบ' ส{ฒ“ž'ฒ8้6T,^ๅFช?`ะลa‚S?ขฃฏ๖ฤ๘ฅบ›œ^‚”BฬM‚”B!DY่0ฝ๒M$n}Nใ Œ_$ะŸโw=Vท๋/บๅ$n{ฟ]žJยPั+฿„ทl“}โ›r˜ Sน“ƒ](ิไD่ีSej!L9MvฉT3ฆR ์;8๋–ร๚`ดถ๋?‘c๐ปŸุ‰่ต†jœRฑDSaJ‡่า(มฉฉ์๙A๏>๛Tพ:นŽ‘ %„s“ %„BQฃr;ถn3&ฺ‰ร=๓๏ฤฎนŸ๘-?‡“nร”๓ไฟIcOืํz‹]6ป< ห0•๙o}@Eโx+ถูp'nFT4m”1˜Jžp๘$aa”๋ีT˜ršืโ4,รI6ืูwจ.ƒ€z*‘œz”Qด ่ตถฃฆ’YT4Y Sีฏ๋]!8ฝ‡สพ๏ฺŸฏj~™%H !ฤ$H !„Bิธ‹ฆbืฝ‹๘M๏ฑs•ฦๆ'NพPท๋+v;‰฿๔^ป<ๅ1ฦฟ๑ };๒ฦq1Aฏm#‘uทแถmฒฟM˜า8a๎a฿a;Bวq}yๆu8 หQษฌ}}ฉฯ๙ฝœึ๕8‰,„>้=Vlด—&“หeรT 'ูlฃT$†rc6๊"่oริ๑g1Aํ>uP‚”BฬM‚”B!DธXa*~ใป‰ฝๆvN1ว๘ืˆเฬบ]Og/ฯทฃmฆzr<ะ!nห:"ทโถnDEโSกAแsฦhงs:I๖โ nหzข—…ดฆอ#eสc„Cว1ลภTGN]n๓Zœl*–B็ะƒณžX'ั4ชqN"3m.ฌW๗C๚จh'†Š%มูษ่™ฆz๖โŽส๏-สญ|ค„bžใ‚)!„Bˆฅใ•„ฉไถ_#zล๋Qฑแ`7c_๚ML!Wท๋ นํืˆny*š$PฟA*žมiXnoฅ,ๆ๛T'4ฟPื#ช:b*…Š7ุIะใี๙ร ฦ/ฃว๛โw?๘aป]/2 RB1ฯงถ)!„Bˆฅ+ทc:cL'Ž๛๙พ'๕†฿%rู(/Nะ{€๑ฏฮEฝํbKฝ๑๗‰lผ ๅลz๖QฟQ‘่๙&๔งยิ๚qณซgสW%์F็‡PฎwAFLน-๋pš์$๋:?€>ม…‹8 ฤ€J6ู[๋โvr๖p ๋"…ตj˜ŠฤQ‰,*€kœN&(cฦ๛ zœx–ส‘G1ฅ‹7˜)!„˜็ำZ‚”B!ฤา๗ra*๕ๆ?"ฒ”%8๓ใ_}LฅPทหšzห'ˆฌปๅFฮ์ก๘ฤƒฏz„ิl& ˆฌฝฉฆVอผ•ฏ4F8pฤฦ +_ŸNหฆ”E็๋4HTช'ŠŠฅ0๙ก˜œ]ู[๙"qT"ƒŠ7ฺSี‘m&ฌ`ฦz๖œxŽJื๎๊œ`zั%H !ฤœŸาค„B!.ี0ตว}วฤ—~'๑ึŒr\‚S?f๋ธ ท2],้๛oอM(วร?๙<ๅงฟ^๔ข-(วล๋ธศ†ญธ™•3oๅซŒฃว0ลtiโy ทu#NSส๑ะ…!๔๐I@ืี61Zใ4,วI7ฃ")tapเ(สqโ’ฃC”CลQ‰ N"สฉnร f| wม‰็๑>ฮ^ธe— %„s:KB!„ธ๔ไvlfLด‡{า๏๘sผŽP8๘'žcBฟ^OoIฟ๓ฯ๑V_o—็ุำ”Ÿ๗‹ค&ุ[ฤDV฿@dญ8+ฯšcJ๕bJฃ่า่y…)ทํ2คpะลat๎ไข<-๎Uญญq2+q’อv.ฌ|5Hน๎‚๎Fk”ฑ“ž'28‰์d˜"๔ั๙{+฿๑g๐=๋{๕ห.AJ!ๆT– %„Bq้สฏปทฅ๕W‘Uืc0O1ญO‚๊๓ไึ‹‘~วŸใญผƒฦ๏zœ๒ฟŠrฃ ๒๗MเฤRx7โuX15๓V>=)ๆะฅ1~าH4งคVกPvR๓ั๊o„Tˆ›]J6ก\{๋a8ุ…r#‹ฑ—`ŒA9ž<™ลI4UŸ๘่$ู่W Sฯ วz_๙ฒKBˆน?%H !„BB›1z‡฿๕ุu๙‡>uzŽจbiค–mฦ˜๐.ส{Z๐๐aดฦ‰ง๑V฿€ท๚ฬŠaJ—F0ใ˜B]Ÿ?L9nFฬjŒ ํ(ซ๑๊m)ธMkชAสณOป์Fy‘ล[0”rQฑTบ'ž™ Sฦ  Cง๗{ ิํ่ด๓]v RB1๗งฐ)!„B1กฒ๗กไฟ๓—8ฌญวื๏$›IฝO๑ฺ6bBŸสP9ธso ›bŒม‰7เญพHว 8 หf…ฉQฬh/บ˜ร”๓–g7‚บa*HๅNV'ฎำ •jF)ฏ… 5ใฒศgผ•jž9bสtq˜๐ฬ^*Gv๖ ์>}@‚”Bฬ๙ษ+AJ!„Bฬ–q๗Œ๑๊.L9+H฿)ๆต˜ Le฿w๑ปƒ™<{~F‡ธ้6๖kˆt\“^6mŽ)ƒ.Ž GํSฆ<aล~ษ‹แ6uT—งB8ิŠ&F_l&๐q›ืขา-๖ึรแเฑ R“—G๖?c จdNชe*Laะ…aย๘Gv๔์#<๚“—]‚”Bฬ‰+AJ!„โไvlหj๔vgGv๛ฮา_ๆปทWรTฆNmq›:HฝํฆL%OyฯทN>_3ฏะh›Y‰ื~ สซpฺฆFLUoำ#gl˜ ส C;Bชy-ฦ/๖ึ~dทeNชwฯ's IDATc4&?D8|l‘ๆ:ท} *Zฝ•/ู<-L)๔์ว?๒ม™ฝ/ฆ$H !ฤ<Ÿดค„B!^DˆRฦ>f4#F;.…05็๒ืhDp6’~ห'p2+1ๅqส/~• ็ฅš|ญNใrผUืแญธ'ีn5L้=ฺK0pSชNŽŽ๑ g๖ข\ฏ๎๖!Tp[6เค[0:ฤไ ‡Oิอฒจd3Nชkœฆสy‚žฝ๘]ป N๏!่:{ู%H !ฤŸญค„B!ๆvN!FยT ู*ผๅ[Hฝๅqาm่bŽ๒‹_&์;Xรgใnฆทผ[์Hœ‰H่โ0*GES˜๒8มษPฑTํ;&๐q[7ุRaS&>นhs{๗๋7ฅTช'™Eล@MjสyยพTŽn๋Fคาไญ‰j‘็๖:๏ๅ0ีง๒%›P‰ Nผqฺ\`ี0ีˆสแ]6L ว% RB1ืกO‚”B!ฤ”W=™ทๆ˜RA็%ฆึUริ๛kโ9.‘ŽIฝแ๗Qษ zฌŸาs†ฮฌฃณsทuส+q.ณ#ฆฆO~>>ˆ>Ž }Pn5่ิ๙ผ รฉR•"บ0ˆํฉป 5น<ฺ •ศ Yฆฆ~h"a฿aฎGฉt?๑@ๆ็?ื)ŸฎB1๋'AJ!„โ"ฬn 0aˆr#จD#*ˆJdง?A๐ S>m…b& RB!„ธ$]๔5›ๆEฅ*ณน๔ืํึmฦD;…bึัA‚”B!–ขšQg]น†ŸSJufท๏์^๚ๆโ„)MปแงI๚~PŠ g/ฅ'>_ฟgœฆ’๗*ธzฌ฿)ข\w๒L่ƒ๒p—ฃb จhๅFํื‚2„๛dพ  S“?ปPaJrซA*)ๆGฮ@Jy^o๋ย0ใ฿ค)!„˜๋่ AJ!„KInวถ๋qvิMˆ:๋ ๖า SC;๎๎TฦŽCๆ‚œุฦRฤoz/๑›~Pง~L้้ฆฆ&S:ฟ}งi ษป?Ž‹๋#:†Rjฮeš˜PiXŽŠ7‚ณ#ฆ”0~*taSฮ/`˜Rเxธห/GyqLq˜0w‚โ’<า…ใ฿~@‚”Bฬut %„Bˆฅ ทc:cL'Ž๛ฅq%{i„ฉŽmY~!ย”Š7ธๅ}ฤn๘)‚ฯQ|๚ (ืซ๕ใ6ฏ#ฑ๕—@)๔hฏ RำFGอล„!ส๕P้V๛DพX#ธ`0-E%oรTฅ0m\ฌ0ฅภเ.lo5, Žœ‚ ผไ?—tq”๑o}B‚”Bฬut %„BˆzถไBิYWดฆฮ๙ฤ6‘!q/ป๖ํ๘วžฆฟูงะี#'‚ฒŽฤฒปยhแ๐qิ9-ย่ๅxจT *‘ม‰ฅม๑ภLPฦ๘EL%ษaโE S (๎๒อ(7‚. ฃs'!ฌ,๙ฯ']c›,AJ!ๆ::HB!D=Z๒!jฦU-#F;œูํ;sK|ปf1;^ษvu’Mฤ๏๘0ฑซ €๔qส/|&'๓ฎ3nฏํ2โทฺUกGฮๆNN›œœN๗1Z[๙Rอhฤ‰72Œ_ฦT 6L†0~้"„)^ oูf;Va;กฟ๔฿บๅ<ใ฿๘# RB1ืัA‚”B!๊ษ%ขฮบบฝคยิyog'ีBโฎ_&บ๙u€ม?(ๅ=฿จ฿9คoลUฤo~ฏนS่‘ำฏ0ฐ)Œ16L%›Qษ&T,5๙U”0ๅผง0Œ Š(72๙ณฏ.L)ˆ$๐–oๅ  C่ก`‚%–5ๅc฿๘C RB1ืัA‚”B!๊$Pผโ‘3KŽ„ฉ99้6wŒ่ฆ{CๅเN*๛ฟ u{พ๋เu\OฦwๆNกGฮ œWุชqษฺ0•jAEโ“_5ASว”ฦl˜ ห L)T4‰ป|3 0๙!ยแใ`ย%V5•"c_ RB1ืัA‚”B!jๆf—wฆ฿ท.b๋6cขs…)'ำN๒ํDึฦP๛mรป๊vY1D7n%vอ่แ“„ฃ*HM^ุ๒b8ฉT";kฤT Sทqช0„ ๓Sฺ@,=ค ร่มฃ\œ'๚ีุ6๔หŒ}ํ๗$H !ฤ\G RB!„จญเ !๊œOไœ†ๅxํืYs#nำšc*‘ํTฑิƒK?9;LนM$๏ ผีืƒั”๗|“สมขผh}.คึD7฿K๔ส7ู>‰=s‘&iWLL>๎คšQฉf”;ตLPถฃฅJฃvฤ”>0ฅu5Hmฑฟซ0D8ptฒ…-e&จ0๖ี฿• %„sy$H !„ขŒ}แ#Yฟ๏€„จŸx๖ฆPัNชล†จwโ6u โ”ล ~๑˜๏๏t6=ธิWGnว0ฦ๋ฤaญผ–ไ}ฟ…ท๒*ค^2•?Dลำ๕นpa@๔ส7ฝโ>๛ฏร'ะฃ=x„ิY;(<;ว”“jืช +˜โฆ8‚.ไภ?1LญQัค.€ฐท์IBˆK๛”F‚”B!ขอ/nืนSฑง3ๅ=฿ดOณฮฺส‹ฃ’Mxซฎ%บinv•}Zšฦ/ข๓ƒ่แ๘'Ÿว๏z๒˜=ั™พ๋มฅพzr;๎€ำryg๒ ฟฝึ[พtH้๙/R9๘œdS}พ/BŸุ5oฏNาแะq๔X๏ER“;œ Sn'Š“l™ฆ|L1‡) ฃ‹#`ยyริYAjด‡0wฅ–~‘2aภุW~[‚”Bฬuค‘ %„BˆEผ\๛จN`-ฦ`*ยม.ฎว(๏๛ฆ“U„ืรI6แuHtใV–uvฎŸ‰”ํผ<น“๘'žล?๒˜ฝตk‚ๆaฅ*ูํ๎\๊k+์?ทํฒNtฐถ๔ฬฟR9๘Cœ†ถ๚|w>๑ ‘ wฺe[ะ U} ZุkฤIทฺ:žช#ฆ 9L1gGLaPฎ7ต๏b0aˆŠ%๑V^mwวI๔X—ฤRค„b3 RB!„Xh๙ฏม"๏้ŒฌฟmญJdf_cสใฝ๛๑ปง๒าท1aๅR=UรI5ใญฝ™่†;lˆJ6W็DR“ฃTยI‚๎งจ…๋ŸBา SYB{๑ษฺ๎™q2ํuน&๔‰฿๘n"๋n'HM-€ S m8‰&˜ OajSฎ†)=ฎŒQัิไฉpฐSฬ —;ุ่ฑ/–)!„˜๋,G‚”B!สไ|?žทึm]›YEdำ=DึˆŠ5ฬfขK#„=๛จIๅภธFTLp’Mx๋n%ฒ๎V–u8ษfT$Jat€)ขGNใูmCTaย๐ึั%ฆŠ}ถด็kฟๅ5m๘uOี฿DRกO์ฆ๗Y๓๛ฏCว1c=เธ‹๖’l˜RจxNช'ี2๓๕„!บ0„) ก‹9ะ6:ฉDf*H๕ฦT  %>6Z3๖ๅ&AJ!ๆ AJ!„๔‰งg|ม๑๐–]†ำด–่๗แญุ‚Š&gฐะ๙!‚ำ{จ์6๑g—๔บrR-DึŠท๚z–ต8้6T4eCT่cJc6Du=Fๅ่ใ๖‰g~^ษ9%ฆr;ถeษฌ๘=7ู๖๑บ Sa@–ŸณO ยกc่ฑพE!Uฝt`"xN„)'‘E%›ๆSล!๔h/ฆR@ล&Ÿฒ๔์ฟ่%ู'AJ!^ๆจ"AJ!„/lfLtืฝ์7:ฒMธห6ป๚m8M(/6ฒย=โ9*/}^ิ.!“#ขV]‹ำผงq*šB)ฃงBTp๊E*‡A๕c*ใฏ,Dอฆรฯ)ฅ:ณwv/ํq:•j3งq๙{Tผกๆ_ฏ Cทฝฏภ๊ฆว๛1HM^B03L98ษ,*ั„JfPntj‚2ฆ0 Jแ4,มษ0ก_หฑะฦพ๔›ค„bฎฃ‰)!„B\๘ ญŒ‰vโpฯy`uฤ”ท๒jbืฝ'ฝlฦ<5`0A=ึKpYJ/|;Y฿'cฑ4‘ wโญผทe=Nร2Tผๅxำnอ;Cpz~๗่ฑ>t~ฬE]"aชฆ’ธƒี‘E†pเ(:?XC!gV˜R.N"c'Ofg„)Œ๊S๕‚ำ{0•๑“ฃ/Uค„โeŽ"ค„Bqแ.๔_aˆšอ๕p[7Y{3ฑ๋…“ศุGะOปธ5~ับึ$ฅ็รN’\?ง`6Dญฟ oูๅธห.รi\‰ŠฅQnคขช#ขฮผDp๒Eย)๔x฿ไœ<•„ฉฺ`4‰?„ป|36Huก๓C58ฒhพ0ี„“lš•A็‡ะ#ง œ˜Cj้^HBˆ—9zHB!ฤซฟฐฟ@!jฦ.6L5uดุu๏Bล’S_ณW{˜Jžp่8แ]”u;ŸRอžy)T"Cdีuธห.ว[พ'ปzฺˆจSC๔๔ผDpfฏฝMkฌwฺล๛ฒaj{v๛ฮRวพ๐มm&t>ฅโษ;ฯšรl‘%๎๘0ne` แภaLqdrคQ ๎เฬ SN2ƒJ69ฆฆ t~]ฟ\นฅw]b Œ}้7$H !ฤ\G RB!„xฅ.|ˆš็"ืuq[ึป๊-Dทผ‰ฯบ๊ำ˜๒8A฿!*๛ฟOe฿wj์Œห†(oูๅx+ฎฤ]ฑทy *ึ`GDU_ฟ9Mะณฐ๗a๔h&ฌ,๎kืŒ์ppv,๕05๒ู๛ทaขŸrฒ+๎ฌSŠฤึ_ฤmYFงำ•ฦf4ูฝฤ`z˜Rั4Nถ'ู|ึwšฐ‚) ฃว!(MฟKfŸ’ %„/sด %„Bˆ๓•ฑm1ฆว}‚žธDธ+ฎ vๅ›‰lธcึ๙ h.ž~‰๒๏แy๔ฌ ไ…พ0w’Yึ vDิสซp›ืข’M3Cิh/a๏>‚พC„ฝะ#g?Dอv …ฉŽญH,๛7ป๒๊E Sส!ฑ๕—p›ื‚ ๚A%_O—€AWŠธMkp›ืุงf–ฦPฎ‡ŠMญ[ใ—0ลœ-(.โ{๖ย’ %„/s” %„BˆsฟP_œuึ L2k'>ฟ๊อxํืฮบ•ฯ€ั๙!‚S/R๓M‚S?Z๐ q•ฬเ6ญล[พฏj๛ไผdผ่ไญ†fฌŸ ๗a!‚ำ{GN/ฮญy็ใ’ Sw€xห'ฆ๖ŽE SŽKb๋Gq›Vƒ๚_จป๕hย`rย~BŸเฬKฟˆ“iวiX>cฤฃ J“#ฆLPFฉ๚Sค„โeฮ–$H !„โ'_˜ืFˆ:๋z=ณฏbWฝทํ2T4มŒ0†่๑~ฯR~๑+„]ไ*ˆ›]…ป ผีืแถl˜ข ˜๑‚C„‡ Ž?gC”๊kงจ†ฉKแB{2Lตญ๏P^tแฐ!yืGq2ํ†}ชฃ‡๊‹ั!ฒหQ‰,มฉaJฃจHยŽŒงQ๑ ส‹MŒ_ย†ะ๙ALPฉ๋05๚ค„bฮs& RB!„˜Bผ6CิYืํ-๋๐V_O์๊ทแdWอธฐƒ }๔ศ๎')ฟ๘U๔่™ RoภI/ณ#ขึ„บ'ู„๒โฃม/ขว๖ฦ๏~Šp่8u[’ๆ˜RAgv๛ฎ—๚๛aไณ๏๘ˆ“Y๓?U<•^?่ลlj\ }ย–๋nฝญ๑VlAลา` ~๗ใ`@EbvŽ)/ŽJ6ฃb)๛7mฤT%oGLๅ‡ํˆ)วฉป๗Œ)!„˜็I‚”B!fหํุ–5ฦ์จ๕5›ป|3‘57ป๊-จT3v4Kuฤ”1˜ Œ>Nฅ๋qส/|S~๕๓๑จX 'ูŒป๒*"๋nฑท&ฅšmˆย@ฅˆฮŸ ์=€฿$แเัฅทำ\"a*ทc[–ฬŠ฿s“mฟุaJE$๎๚(Nร2LXฉฉJญ4๎ฒMจx#่ิ‹เ—Q‘ฉัf6L%์๛6šBE“จHŒ‰นคLiฮ1Uฒ#ฆ—z Sค„bžใœ)!„BLฟุึ่ํสxqศิ๋rx+ฎ$ฒ6ขWพ '‘ืe*LiŒ_"์?Bๅะ)๏๙ๆ+˜ทIก"1TผoีuD6ฒ'ี ฃณ2บ0„>Aะณฯ†จธepัI˜บ@๋Qฃ6HฅZ0Aู)ํืแฺRธญ์-{: 8c;ฺษL~}ฦS๙"‰๊ˆฉด฿^ ”ฒsร•ว 8Š. bๅบ5ฟ๔ค„bžฃƒ)!„B,•5ƒใโญุBdใVข›_‡“lๅL}ฝ๚„ป g•—พMๅ๐ฎsบฐฦ๕pโxํW฿ผ'ู\ฝMPM>ฦ>ฬ$8cฎวป/ฝJsL){v๛#_Y๊๏ฆZ~๗BN|nย'Jโฮุ ๅ—{๗ƒ ๋๐Šร|บไไคๆAๅzgฟฟf„ฉ$Nชbฉj˜ชŽx ty Sฮcฦ๛1aeŽ฿U;$H !ฤ<‡ RB!ฤฅkI†จg: Iเถฌ'zล}D/ป•ศุั“W]ฬŽ๒K฿"8๙ย<ฟหAลาxซฏ#บ๙uvDTฒลVคL่cŠ#่‘ำ๘วŸกrh:wRv2อรJU:ณนฤ฿K๋Tช๕ฯœฦๅ๏นaสL;‰;>ŒJf1~ัސชว ๅx6H%ฒvคWฯ>œgพ7.Sa*@ES8ฉ๛4M/>9Gœ +”1ฅ1๔h5ฆ$H !ฤ<Ÿ๖ค„BˆKฯ’Qg๑(œtNฆุีo#ฒ๖&l4˜ฆtˆฮโw=Fy๏C„}ง~<ึ`Cิฆ{์dๅ้6๛จ๚‰UG๖เw?‰hW๕ฉy!u?a๙…$a๊ผฟˆผŽฤํฟ`CNฅ`GHีใ>ๅFq›:์rLŒ๔ามฬ0<๗—a*–ฦIตขขIpฃL<๑ะh฿>ฝฒ<Žํลhฺํ€‹O‚”Bฬ๓)/AJ!„ธด ํธป๓’ Qg๙8ธูี8™•ฤฎ};^๛5๖ษ_Sย=ึKๅะรTํฤอฎ"ฒ๎ึjˆZัสq1:œ Qวžม?๒ˆฅแ—ภhูัๆs)…ฉDห?;ูwพ’0eสye—“ธ๕}จDSฮฃ๊peธ1ๆ5จx#ฆR$์{พo\ฆยThรT2kฃTผa2>™ bรT%ํึD˜’ %„๓|บKB!. นwภฏ‡ตrคp›ืโ4uฟ๎]ธหฏฐ#žฆr„!ฦ/`"8ž}๒—๋M…จ‘3vฉƒ?ฐ!ช<^%ฮ‰ๆaฅ๔๖์๖/,ํ๗ึm*ฑS็ฆLiฏ*โท*ึ€)๖ฌฯ ๅ%pšVใฤ1•Aฯ^”z% 2-L้kฐŸวR8ฑp=ะ”0~SฮฃG{ฝจaJ‚”Bฬ๓ฉ.AJ!„Xฺ$Dฝฎิป๒Jโ74nSฬธp5SฅCti=ฺCpf/~ืn๔h:?do?ฏŒ?ง”๊ฬn฿ูฝด฿‡็ฆLqฏใFโ7ฝKcŠฃ‡P๕ค"I์jTผSฮ 5๏Q็วhƒo€Xoภ‰&ม๑์C *LฅhGL๕ฑXaJ‚”Bฬs&AJ!„Xชภขฮ๙„(–ถ“žoผ ทช๊E๋๔+Zฃ C๘]Sz‹่ฑ%D]0—P˜"๖yทฉฝใๅย”. Yw+๑ื *šฤs„‡ฉว"ฅขiœ์*ึสc=๛/Xš|‡pโ๖พXI€ใ‚ํhฉาจ S๙!ภ,h˜’ %„๓$H !„Kํ‚WBิ9Ÿy1ผuทเตmย]~นล‘ศฺงxM^0ฯ|"Ÿ)๔๎งฒ?ฉ์žฌฤ น=Yผๅ›?็ต_ฟ๙gป—๚๛”xห'็ Sz|่ฆป‰]S6H† ๛€S‡A*ึ€“Y…ŠฅะฅQย(วฝXอFฉxKู0ฅ” Sฅq๔xŸ T•"8๎cs‘ %„๓|bKB!–ส๎ึmฦD”uฌั๎๒อx+ฏย[q%n“ QxQ0ฦ>ญ+?สฑ#;"qฮz"_1Gpz•=฿ภ?ฌฌึW,าx+ถุmฒ| ns*ั๔9ศvๅEsK๛}[ Sm๋;&ž ว๚‰^qฑk฿Š&ัลบ๏p)*‘มษฌDES˜โA฿มA ผ8*วi\aŸฬ ti 3ฺcoศ ส`.๎oค„bžOj RB!Dฝ_ะnfLด‡{dmผชŠ%q[6ุ๘ฑ๒JผึีQQฬฤœ3c}} z๖ู[ค‚๑›Kdใ]จX’™a*@็๑=C๙G_#์?$ซ๙|ถHฤ†Aทm#สซq[ืใ$›ภ‹M„มณ๗Av^็ๆsฮ๎ฝo็t#gฬ”DRเHVฒdำดฦvูซ‘ึตฎ™ู0ฦlีฎ]ต;ณPีxw๕ฯjผฎ๕ฬ์he{g'ุ–-K'ˆ”(RL`‘นsบ}ำฮู?ฮEฃ@“ ˆะแ}J*ชิ$๎ํ๏๛}็<|฿฿;{๙P:๎กฬ_\ีbjๆ_}แะ๙มฎฒ๕ fv„pื็ศ์๙*ศE‘s›ฑUื‚n๊ฉตN‘Žž\Px_ฺ0)*ศบ๗ะุuux5˜ส ถZ„ธŠญ๎˜˜!%‚ฐฤ>@„” ‚ ฌLDD}€ Oฆฏu=^็Vž]x[ัu-(?ƒลBTยฬ‘Œž =A:yขข#Qย:ฒ2~^T˜ใช˜r๙La„x่*/{Li๒ส+3Œ.\ล๓๑;ถโตoภ๏‹ืพะ>ฝ็ลเุI’หo“ŸI&Oา–C๙‡งW๏wzžๆ๎฿ึAใฉ6f๖>Cธ๓35!5E2vzลEHYcะ ํ่ฦnT˜ร–&๏q+ฝlšิก๊[ั(/ผ๒1ี9lyโ 6*v1%BJa‰™)AAXYค“g๗W_ำƒั้็>nห3rAkฃ“iD็{๑;6ใ๗WQญdP(l\ฦฬ“ŽŸ"=N:zชvpอ๘`kAY2{Ÿฦ๋z˜ฒiŒ™นL|โ0•W•dโxญx๙>‚มG๑:6ก: ฌsทถฆ0ŠฉPJ ›FFคS—ส้ไ้›ž{ๅŸญv1e0๊?๑?wLณ๒3๎šฬ\บใํeทk บฑะแZ็ฦI'†๎ชบ๚^Rฐึ;IV฿žๅ‡˜j[šคโ*ง0ทๅuEH ‚ ,ฑO!%‚ +†ภAเใ6HวNQy๑I.ฟญฮษีYธž๎ ฒ IDATมษ4 ;๑:ทฌปฏ}“ซภ ฒ5๑Qม”&I'†HวN’ uญ=a๎ๆ^@๛่ฦN2;>n]ฟ8cสZla&ฯR=๚ทT_3๗šk/@ืทใตo xฟ{;บฑฎN'ULq S‡š4ฐ•ฅ[จLaขฟ๛ืข๑แ๏ฌๆหฝ๓ื๙`๋ƒสฯf:u[ž†4ZQฟƒ5)บฉะŽ r˜นฑšา๗๐=ฐฦIฒ\kv๙ภๅรU ุา4$ีšTpbJ„” ย๛5R‚ ‚ฐผ)‡<˜ศฏ๒{wตแฺ6ฉ’\|ƒส ุ้ilณ–[ฤTX‡ฎoลฺ๋Nฐ!ผŽอW[ม”‚ธŠ)Mb&ฯ‘Œ น๔6ค*Sk/่gะอฝdv,บฑJฝ@L%าั“DGš๊ต๖ฤ๓ัูftห:‚uเฏิ… ๋Pสรฆ‘ Š&˜๒”Q&yฉ&ฤงžIฮ<๗๙ฯ~c•_ษมไ๒;›ญฬŠ๒ƒ๕ฦmš ›๛jB*‹™รL • ฉ๗}oฦ‰&ะแ2ฆฒ ๔๗ื”งœSทvo!%‚ฐฤพM„” ‚ ,OฆํดึD๛_Vู2;>Mธ๋ณn๊›ฐHLU็ˆ‡^ค๒โ’ฮ\rU&kiCใgPนfผฎm„?vUDYืš—D˜าf๚<้่ โ๓G ญขฒP›DT%๕9tฎ<๏๊๚XƒŠ$—฿ก๚๖&>๙๊_ํฃย:ผ–~uฌ‹ส6ขด‡5ฉห์IcฌI0…Qle๖ฆDิuื?ฎŸ๙้šS3๚ƒญO}=่฿๗ิ-KิปŒMผ|?ชก๙ึรษณหBHอฟGcQJกฺั๕ญจฐ…a]ฆ<-Maใ ฤe>จ˜!%‚ฐฤM„” ‚ ,/ฎŠ(๏หื๓›zศ๗ยMO ปฎๆŸ€๛7๚ฅIโS?ฆ๒าฟรฬญ‹ๅจฐฟk;แึงๆ3‰Tญฬ&ถด_ธ๋๓lxd๗rS6‰g`^HNž[–ำญต(ช.๏Z๙๊[Y˜gส3ุาดซ่Kชฌ˜!%‚ฐฤถA„” ‚ ,›Cๆ’"๊Zผฮ-d๖ม†วn >LaŒุ่๗จพ๑-Lqb๎`4*ศโw๏ ๑ฉ๙Œจy•&ุส,fv„ไ๒[$็^ม&Tฆแฮj+PŠp๛งท<‰ส6]m—QsE๙&f๚ยjXะบกpำใ๘9 ‘หปj>k]€|a SwํOwจฝ๔ช˜๚แฏไ่๐๊พg<พ?๕๔๏.g1e“ฏe=ชฑฅLa”tjy ฉ๙๗l†Rู&7•ฏฎuAล”ล”ฆฐฅ™Zซi๔พŸcR‚ K์DH ‚ ยฝ>Tผˆบฟู}ฯเ๗๏ฝฆอค6๑m๊<ีทšุ่๗\สjุผ๘ผždv|บึšืแBล•ฎUเ13—H.พA|๎ืšํรบย&U@‘ู9‚Gœ [ะ„I0ณรDวพOๅ๕?c%OLTนfยญOฌฏu=ชฎๅgjBข๊๐qชELa„ป‘sfใ ษน#oฤ'๎7EL; )S#:Oฆ์ฺ‡[ฃย'ฆUL)N`หWฤิา‚U„” ยทXR‚ ‚pฏ‘nดปฒ4อๆฯ 6~„์พ/โ๕์Dyแb1WHGŽQ}๛ฏˆ‡^p๓ฏย-Ot.1eำฏe=บก”ยฬปช@ฅVะ•U51U๏rฆ๊Zิ”ฆฐล lTยš˜k3R‚ K]EH ‚ ย>4>u-™]Ÿ#๓๖ต|ฉbชZ$นp„สkJ:zUฌ\9l-c1ฅ2๕๘=ป uQM=ตpl—IDต„™#น๑นWฐi‚าmษ%บญZํฃณM„;?…ืฑๆX,ฆ’๑ำDoล๒Ÿศ็„>Aะw^๛FtC'„นซ“๓ส3.จ<*บ5JขZะฝ๛œญ-1๕ไW‚mŸฺrS6Mฎ )lMH]ญVเ•uญฉ*l@5ดนv้˜าvnUL-ธˆAXโฎ*BJA๎ึ!๑ฮ‰จkeAv๏/๎๚,^พฏ–/ต`โ[e–่๔Oจพ๖วค“็ภšซ‡ญe$ฆTX‡฿ปxํ๑๒ฝจl3ส ฐึ@Tv"jไ]ขำ?F้Zภ๛-Ljปซ่/฿Kธ“่–๕๓ญmตยฦUาัT_3ข‡—ืฦ1ศโ๗๏ซษมอ่ฦฎZ•š็ชิสณ˜าค›˜g“žiฒฌ>WWลิ~>เ๐ะ๊พ็ิฤิŽOvช…๎ๆ๕NSผึ๕่†vฌ5NTฮฏฐ ฉ๋พ n’dถUื‚ฮ5s]+_e[šํ1๛วญ)A„MEH ‚ ย>%u บฎ•ฬƒฟDธe?บพํบ‰oฆ<ํฺฤŽ|sYŸ+?ƒ฿ฟฟo/^๛&ผ|*ืŒ๒3XkฐQษ#$>๙ถ:ก“"+kฆ๑;ทl๛$^s7่ลm4Gr้-ชo~‡๘ฬO๎ํ[ ๋๐บถ >โึคฅ฿ษม+“๓*H*˜jัฤซW2uฬฒฝ6ฎ\~็oใฃ๓Wป˜*ลo^vื~C…ูเฎ_gc๐Zะ๕ญXc0…Late๛จซwY๐|Tฆ•kชต๒-จJ-ฯb*ณฟ๛ตฏ6๓ < Aฎู_ˆA„;วไก'mu-^็V|>๐k1™Ÿ๘ๆฺฤLqœ๊๋฿ข๚๖_aซ…{ท)๑3๘}๗แu๏ภ๏ŠnY‡ฎ…c_QvnŒd๔8ษนW0ลI@กย์ŠŒX“nมฆ'œ8\8‘ฯLy†ไยkT฿ษ…ืน›ีF*Sืพฟ~็ผถ NzกQQ37ๆฺ๑ข2ฆ:็ฆŽYณrฎSำ‡๖็3~้๗ฮํฯM1eลk@ืตธA ณ#ุโจUtq•็*ฆ2 จ๚tvแํbf‡ฟช›zสQแšง)AAธ‡ฟ'ฟbญอภryOมเ#d๎{ฟg*SฟHLู$ยฬSy๙฿?|Wƒต•โ๕๎ฦ๏ฺ†฿ตบMณ๒3n๚•ึผฑ“$_วF{MซสวV‹„;?Cธ๙ Tฆ๑š‰|)ฆ4E|ๆ'T฿๚้่I๎ค˜RAฏc~ฯ.ผฮญ.'ฺ๊5)ŒLกณMุ4คฒขDิuื_ฤิมXt RI3;Œ-Mญ.!u๕f^ˆสิปVพlำ•Ÿ|8(OFA„kn›"คAแv๖–Ÿˆบ–p็gศ์YWํไฎŠkฑq™trˆ๒5ษล7๎์&ฤฯธ๖ฏ๎ํN|ดot-/AึIธŒ™';Ir๙wต)ส V๕gศZKf๛ฯlxฬ‰ร…'๗4มฬ๘!ี7ฟ™แถŠ)/ภk฿่ไ`๗—U฿Aฮ<*cๆF1…๏…ุจฤrnอ๛ภื?ฎŸ{๙?$'Ÿ๛ว๙‡งW๏ฝj`ธ๏™ฏ๛žบ“ม็ึ‚ืถkฦฦeฬ์e—1ถชOXNL้l#dะนWA”'ค ย5ทKR‚ ‚p;wห_D]Kๆ_$ณ๋s่ๆ^”r5๘b+ณ$ร๏P~฿’Nœqงสต๙rxญ๋๑:ถเ๗ํY =ˆจโ้๘i’แw1ำ็ฑf๕‹จE‡๘$‚คL๖แ/แ๗ํEe๊ธv"_:}่๘จพ๚วุค๚แ^P๛nMฺ7แ๗๎v-“]ึDT\ม'0ณรฎ ส ฐๅ–๓tฦ‹)LTโ ฏ฿้นW™ˆฉ[ถเตo@e›]‹็ฬๅ{ฺ|ืพรฦธI{:€ด๚ี`รGส“Rแšง„)AA๘0‡น•'ขmย:ฒ*แึงXvoแD>‹)OŸy๒›T>”˜RA๏รุ๋Lะw^็VtCปQ0/=า๑3คฃวI'ฮ`MฒฆDิu‡ฺธ‚ ๋ษ>๘หx›QaŽEกษI„™๕ฃใ•kยk๊ม_w?มบั๙>Tถ้ชˆŠJฎ0ฑฅILiL,—พ†)LTโw๚_4ƒ?ี~ฏ๛๐bJาฎB*ำเ„ิ๔€ฟ†!%‚ฐฤSB„” ‚ แl5‹จk 6?Af็g๑{wฃย๚ล฿า„tโ4ๅ—๑ษ็ฎ฿\๘Tฎูตๆ <‚฿ตm>h^DUfHg.“ŽŸ"96*ขย:๙ ๔ฮ#x`ใใ.๓น*ฆ ถZ$พ๐ีื„ไา[ND…u่ฆ๛รkY‡ส6ขด5)6.A9)Uœภ”ฆ\›žp6MˆO=?’œy๎ท๓žฦjฟ๗บ˜R <ผฮMจ [™&บฐๆ>W"คA–xJˆA„๗>Œญ%ตx— ษ๗s„[žย๋ฒธM ‹+ครG)๔%น๐:x>*ฌw<?Šืต ุ‰ ๋œˆชต™้K$c'I.พŽ-Mกฒ๒AปU มภร>‚ฮ5ปvส+˜Sž&9๗2ัฑ ;6=ŽืฒU—w-‘ึbฃ’“O liSšu“ุธB|ๆงkDL=๙•`งฟnyข๓‰)/tRAฎVy~อU‰AXbซ)BJAnt๘Zร"ฺ๊อ‚Ÿ!๛๐ฏlx ฏuเšjœฺDพหoŸ1^๗Nฮ-่†NWฅ=W}Sรฬ\&=N|๎elyFDิmย&˜”ฬฎฯl๘ˆปฎืดZฺ4†$rาฐ–อeใ*ฆ2ใชขชฬคาšwKk b๊ฦืลZ”Ÿq~SžฦLžuำ็ึ"คA–ุcАA„…‡ญƒึ๊oˆˆบมฆ!—'๗่—A7u_|ŽIฑ6E)ดv:ี9la”d๘โ3/ธึผLƒ\ฬท*€ถ2 aŽ์}Oใ๗๏ปพีท็ปา’gM ี"้ฬEQท Wˆ‡^9•œ•?๐ฃรซ๛^YS;>ูฉ<ฦ“1เ‡x]Q~ˆ-อNœฬš๚\ˆAXb#BJAฎˆ({ํ}Yฎฦ{ฃ›{ษ=๖e‚‡Qนfฎถ๑X๗ŸคŠ™ฝLr๑Mขำ?†4F๙ู5wฝ‹[:ภbฃ บกฬ๎ฯ9 ไjหณ`ฌล'HGaซ%ทfศ~๐vbใ ษน#oฤ'๎7Wณ˜š>ด?๏m|์wฒปพ๐*ฬ^7ำšิๅ๕ํฯร–gHวOญนฯƒ)A„%v/"คA„ตŒˆจธq๐3x›ถ์ว๏ƒื6X›๔‹ค‡I1ณรT฿๘ษิ9W5ตฦฺt๎&ถZD7uโ๗์ม๋Šn๊BePฺฏUIฉkฤ”uแ๔ใงIg/CR]ฐ†ฒ7ผm๋ฒ†ฤTๆั/พ฿น™…bสฆ)˜”`๐ะ[ž%;นุaฏDH ‚ ,ฑฏ!%‚ ฌEDD}ภ Cล๋J0๘(^็ผๆ>Tฎๅ…W—J/ฮ.lT";E๕อ?วฦPaR%u๛ฐ•*ˆ฿ฟห๎ส๗กฒอnržMฑ•Z6T\F5tข;jqA8}‘ŽภฬŽ€I!uึiญ‰ฉŽ-ฟฌ2๕.ป,M6~”r-{ใ'ฏi%]ˆAXb)BJAXKˆˆ๚€… ‹ืต ^วtK?บฎๅgฐˆ+˜โคkŠJ๘๋@7uฃฬยใ8ถZ$~‡๊ซโrค$ะCaฃ"สฯโ๗๎ฦุ๋Šืบ•หปœk\ˆ์ษๅทH.4 xˆ`ใวะ]ตp๚+ ›ถ— ฟƒ-Mอฏ›p›ื-ฎ\|ใ๙๘ุ๗~-เ๐ะjพฯ†๛ž๙z0๐ศSfv˜ฬŸwฟiŠd์J๋5ต๎"คA–ุgАAึำ‡๖็ ๆ€R"Wใ&6~ฏ{~ฯ.Wี:€ฎk… &šโ fnœt๑้ŸNวฬ\kศ์}šฬ๎ŸญIฑ2ึ`หณฤ^ฃ๚ฺ?ท OธlTๅแ๗์ภ๋Šื6ˆฎoE๙Yฌ5•I #คร๏_8‚)ŒขณM‹+R”Gฐ๑cƒป5]No0ๅi’Koน๊+/@ฤิXวธB|๒น?9˜yเ—†V๋๏9๓๛?7˜}๔ห3๗โ—มb‹“คCาฒ'‚ ธ-‰)Aa53/ขฌMณ\‘๗ม๓๑{vใwn]$<r๎็qลbŸ&>*frˆtbW1บกฬฟDธ๙I'=Vใ˜Sœ >๗ ั‰gืZ๗ฮ-aฃ `๑:ทเwnqีj ํ.ดฐq37Fr๙’‹ฏป๖;/xoแง4แ–ง๐B็๒‹ฅ•I1ลqโ๓ฏBšึู3~x4์์^วfผ๖ ิุƒสฯ ญโ_|์กt๚ยฯ™ะาฒ'‚ ˆAV)3ฟ๗ู|—(๋‰ˆบฉsฒ‡ืพ ฟ{~ฯNผ๖่๚ถ๋Eิฤ’Ko‘ŽŸ"?J๏๙วzํษ>ซ๘๗ปJ๙j‹Mcฬฬe’ก‰†~ส’ฃใื06*ƒM๑Z๐:ทแwms•g™:สM3,NŽž น๘:้ิP๊ฆ+ฯlAšyเ‹๗ฃฒ ,*_Iาูaโกะูfd"฿ญฟTถ ะ ภo฿ ™:ื*Yš$น|”ไยkŽ;ุ๘ซzhต^†๘ฬ๓๛ฃc‡p๓ใ๗ซLšY~R‚ 7F„” ‚ฐบ๐ีBฬ ˆ‡^:\<าŸ{ูm[ า^๊ ์ตฌว๏แZ๔บถกฺˆR โ*ฆ4I:q†๔๒;$ฃ'œˆช>ะห๋"๓เ/ใwmuมๆjqจถ™ขz๔oHวOฃ‚ฌ|Žำโบฉฏk~๗ts*ฌGi›Dุ๒้ฤษล7Hง/b“Jญล๎^ฏR@e๊ษ<๐ห๘;PaŽลb*&น„™นŒM*Dˆ˜บ™๏—ส4ๅ…่ถAฎˆ[)` ฃุธŒ2kฬฆ0ซ/ั?ส8<ฝZ/ห๔กว๗‡ปž`ร#ปื‚˜!%‚pcDH ‚ ซSฯ๋บึX{ภฆQ3&มฦˆฯผ@rแ5โsฏˆ˜Zˆเ5๗บชจ]๘ฝ{ะ๕ํๆPJปส›า$fโ,ษ่1’แwIวN`+…๕ฒแถฟGf฿๑ฺjโi˜Šสค#วจผ๒ฐฦ ๕pำG7ฌf1%BJa‰])AaฅSหฏsวAฟ{๛€nDืๅม2_ษaJSDว@r๑ษล7ืด˜R~ุ…n]Oะฟฟw7บก๓5™:G:v’ไา›$ฃว?ดˆZ๐@A๖ฟOธใS่|_ญฝL-"ณ$—฿ก๚๖_AZ]3kcฅ^ว=x-จlณห฿Jlต€™พH2r 3užด0rหQ๏๛^โ ~ฯNยญOก[ึ_ณFWฑลqาูa7•ODฏC๛.ืหฆเg๐ZPu-๎ชE%lตI[žมฆษ๛Jืต#ฆžJฐํำ_ ท<ันล”)A„%v…"คA„•|ˆฑึ?ˆงts~็6ฝxmƒx๙uจบผ;ิ%Ulu3;B|ๆ'$็_!>ฦZj9R~U฿Šื6Hฐ๎ผ๎]่ฆ.TX็DTcห3คำ็IGO’\|d๘šw๓oHฃยzฒ มฆว๑šบOไ|~Uข7ฎ6>›ฆ`ท6เตฎGีต ผkาฺg๗2้่ าษณ˜ยศไเ๗๎"ฒีุY`51e 6ฎŽŸr!๊6]ป7#ํปI‡iŒ ฒxํPนฺ'.CTr๗กา6>ฐH\sbjว';WSฆœ)A„%v"คA„•xhฑึ?ˆf`๑กะCืทใwo'ุ๐ผŽM่†ฮซญ2IีŸ:Orแ5’ GHฦOCฏฝขrอxm๐ย๏ูn๊tYDJcMโฒlฆ/Œ"9๛ษ๐;๏V~๛ ฦkYGๆ_$xุฉ๋+Q (ฬ์0๑™็‰Zฎ‚•qฟaeฒžpำใ่ึAt] สฑึ`ฃ"ฆ0†™8C:v‚tf๘žH›DTw|š`ใวD>ฯc‘˜ชIFŽb็ฦืฏด^ฦ &k๑:6:Uห_ณq •ฑฅ 'ซ>dE›*q|๒_ญ๛๔;ซ๙ฒ๒Ÿ}-™ชยlฐ~R‚ K์†DH ‚ +…%Eิ ‰บพ ฟwมฆว๑;ทบ žL;Dง1้์0้่q’หo“\z3}WVฯล๒|Tุเชn6<ๆZ๓ปP™Š}ฅlf˜trˆ่ฤa’Ko;9ง4~๏ฒ๗"~ฯnTฎษตVบc8XK:yŽ๘ฤaโณ/ืฆมญศญส๓ฑT˜%ุ๘8^ บพ ๅgฐXˆสต‰†CคฃวœˆZญ‹ถR?Cf็gqk ˆ)“bสำตฯQดบ๘”/@g›PูfTฎ•mD)ฯ‰๏คโZ๔ๆฦnฉ"๊=ื!MˆŽ~w4>๖7ฟ•?๐์7V๏~>๓่—~฿๏ฬJS"คA–xœŠA–มไ‰งญ ฝฏˆบ/pbชแๆ'๐:ทึ„Œ๏าiB:u–ไ๒;ค#๏บlž™หฎลfฅข=”Ÿq"jำND5u_QWZภ ฃคใง‰O>K|๖e–O๛ข"ุ๔1ฒ{ฏs๓๕๙า˜tไ๑‰’ŒžจMƒ[[ฎZvYŠ ๋]_็–y๊jไYโKoaf/Cฒ2ดlฅ€ชk!ณ๓3๘}{ิธyyˆSลqฬ์ฆ4น,‡๑s฿ฑlบ.jhG‡๎๗ทILŒฉฐ…‘R๕ž๋P-xNฤิ @„” ยป#R‚ ย๒=ˆ<พ฿ฺ๐ š ‚,*ืL0๐0มๆ'๑7Aฦe'ก<ฌ‰Iวฯ^zห…xŸฦวWXล”ญ๑ฺ6n~๗NtsฯUe D%ฬุ้)ข“ฯŸ} ฬ๒อษ์Yย]?‹ื6xดทจLrแัฑ๏aๆ&–yฦ”ยฆ1:S?๘~ื6tC‡“iสรฆถ<ƒ™พH|แ5โณ/ก‚\-H|๙b+ts/แฮOใwํpSๅิีpzLJ:uŽt๔*˜ฦงœˆส4ข๋๒่ฆ7%๒Jkmrž-Mบฐrญ๏:ฌ%1๕เฏ‘฿ณ๓๓+-๘\„” ยOWR‚ ย๒;xuƒ‡^ถ k"ุ๐‚มGX๛ฐมy ึฆnฒๅทI.ผN:1ไ˜หพยCแตฎ'๕Y๎ตŠจฦ๙\—1sฃ$#ว‰O=Gr5lมŠุ(ฒ|‘pื็๐š{Ÿ[‹ญฬ~ž๘๘a๗EpSฒ ช 2๕ใu๏ภk์rEฺs"ฃZฤฬ^&9๑้็๔๋Vฤบ\ฉชณ•^็VยmŸภุ๋ไDอ‚|ฉt๊<6*aๆฦ!.ญผ’๒P9ืšง›บœ,ิ|จป)Œbซณุ4ญ‰จ{๓ฝฒี"ัฉ็ฯฤGฟ๓๋๙?:ผzŸ๛ร}ฯ|=่฿๗ิJS"คA–xฤАA–ฯAใฮˆจ๋~uyt};แฆแ๗‡n@g›k็็ฤUvŒŸ"=N|ๆา‰!ฬrmฏ}'ขถŒซบi๊vYY~ๆชˆ*Ž“Žž >๓๑ล#ุ๊ค+ญZEก2๕d๘%ยŸชิO๒œ IDATŸ/ฮถ37Nt๒Y’‹oบjœ{<๑อV‹จl~฿^ฎํ่ๆ^ท6ฺวฺิ šย(้๐;Dวƒ ผ0+nmๆลT๔Gฐ๑#่–๕ตVDภคุธˆญ–ฐี้ิ0+`€๖\>TึUEฉฐัU๊Yฺ๋+ #ุJkSิ‚๊ฝ{ญ‰ฯ๔ญ่ํ?๏DL-DH ‚ ,ฑ‹!%‚ ๛ƒลQื7๋ะ๙>|พ๏ฏษํฺ๕’ˆtrˆtbˆ่๘๗]ลTฅp๏^ˆn ๘1ผฎํx-จ\ตxY๋ช6Šคc'ˆ‡^$น|[žยฦU–OVิญ ห“}์+Nzไ๒ืd%ค3—ˆO>G|๑อEcwMT เe๐๛๏ร๏‰—๏ซญM‹j S!=N|ๆyWฅฆผ{.ะn๏:๙๘;๐ื=ˆ—๏Eu๎;e๔]žu-Š…แๅ|~EDe๊]‹^. sn๒a\ฦงฐ•ูZโ!ทพWkJLํ๚ทƒ ์^ฎbJ„” ย{ZR‚ ย=tCปห‡‰Jุ๊้ิyฬ๔Eขc฿%8ƒญ๏๕ผถ ƒโwnAทฌCืทข|—Ÿd“ ฆ8้ยสO˜t์fnฬ…ดฏฆ็ฝาxmƒไ๛ ~฿}จLใขเsา„t๒,ัปG2rฌึBv‡•(…฿ปวIยถม๙ตq“๓\~W2rœ๘K`ฌ“P+>[i‰๋‘DุธLธ๑ฃ๘,SI-3kๆฆ<ฝฌBฯUฆ‚:—Gืตข2๕X,ถ:็DZuŒqŸณ2Epํˆฉว๗‡ปžๅ(ฆDH ‚ ,๑!%‚ ƒรAkํAด๗ๅๅ๔พtC;^๛FยŸuีSM่บ—๗•0ล ฬิ9ฬ์0ีwฟ‹™<{w‚ฯ=ฏ}Ax[๐Z\%W˜C]™ฮVœ "z‘t4fๆ"ถZbEWDมเ#d๚UผŽอต‰{ ‚ฯใ*ุ้Iขท’tๆโษfบ"^๎๘][๑ฺ7ก: ศ:IW0sใคc'‰ฯ3;์ควมV  }ยญ๛๑๛๗ก:็ืษ&Ulq‚t๒ฌk%ฝ—ŸUkมZts7:ฟ•krี†ี9๗฿ส,6*ก<ๅฎEตH|แศข#฿๕รCซ๗๙ฒฤ”)A„#BJAธ‹…ๅ)ขฎE7uใun!ณใS๎ะŽฮ4:1—k“๊Nb ฃDวพ™พpg‚ฯ=ฟ}^๗Nฎmxํœ์ธ"V’*ฆ4M:q†ไ์หคgแ>*ฎฎŠจ› ณ๛๓d๖=ใrดNไณอ‘\>J๕ญ๏`K“ทIiะะ‰ืพฏs+บฑึ;•T]ตฺุ)’ G\n’ึ+Zh|(R) ๊Z6~ ฟwOญzฬeLน<ฆQาฑS คw1_สฯbJSxอฝxํPู&๗žH(•…าjuฌลSมถฯวpห๗ZL‰Aธ1"คA„ปp0X"๊jŒ๛ซืา๏ฆ‡m{ฎZชฑรตวi๏๊!zไ]า‰ณD'่ฆˆŽรด๖๐Zึใ๗์ฤ๋฿พ ีุ้*|ฎศŽา4f๒,๑๙ืœˆ?…ญใ*“{ฝz^Hๆ_$ณ็ จ๚V7epมด7Sš"น๘:ี#ๆBฤ…ก7น8 ”ซ k้ว๏ู…n์BePฺร&ฆ4‰™TฺUวY ~ˆื:เ*ข”r•P•Y๗ญฮaญA)ต6ึbญ‰ฉŸ์ผ•Š"คA–x4‹Anฦพ&ข~sี<0ณx๙~ผ๖๘ใตmภk๊ฉy ‹5‰ ญพ๐:ษฅ7‰ŽฎUฬฤaZiผ|^๛&]x];ะM]‹D”-O“Nž'=F:rŒdไถ<-ถ๗ภk@๖ก_!xคVณ J)MHง/๛ษลื฿#_ช&น :฿฿wŸนf”๖ไตส,f๚"ษๅทI'ฯaซ…Zหค์ฑW†$~๗v‚มGั-๋]kฌ็AšbขDeW 8s้ึ'*ฯญฏIA๛x›Qู&”า˜๘Šˆชb+ฌIWmEิ๛ฎET‰“ัwฟY}๑QภแU{s)ลo^vื~C…ูเnฝฆ)A„%ั"คA„ล๔กyƒ9 ฌM๓ju}บuฝ›vืทฏcบฉ่าุUx”ฆˆฯฝB|๎eโS?r•้ ฆฉi่&๙}๗แ๗๎พฺฅjำศ*3คS็]5ิศQาแw1ฅ)๙ฐ}}dež]W3žŠAšŒžpม็“CN\]๙ฉ1(@ทฎ'่฿‡ื6ˆสต ะ‰จ๊fv˜t๘]าฉsฎeำZ@ชข>ฐ ฑฟw7ม๚๑๒W'๒™ฤU,•ฆฐ•ฆ0สM‹>ํฃ‚6‰Pž็‚๏๋Zka๓Ulต€+ุส 6Mคญ๒สZฌ15}h>๓่—~฿๏ฬS"คAnŒ)Aแถl๎Wปˆบ๎ฌเD’ืตฟk‡ o๊rบ$‚4ม–ง‰‡^tbj่งW,x>บฎีๅD๕๏ล_wๅaMญkุ๊้I’Ko‘ ฟ-IEิ-ใ๙„[?Afื็\…ŒŸ]$ฆl‘^~›ส‘oขผSœtญy๋จMฮk?S I/a ฃ$c'1S็HงฮKEิํ!II•`หว ึ=€n๊Aีฆฺ$ย–ฆIg.ธษ}๏ีซ}”Ÿqž็ใwlAี/Qqษ‰จาิผฌnฐ"ฆn"คAnŒ)AแCmๆืšˆบๆ1Šฎoฏp๒บwเตฎG7ดสUKE.'>๛ษลืIงฮฃ๋ ึํร_๗ › —mtํ}i‚ญ03—IวOŸ•ไา›ุ๒Œ|ุnืŠ…ud๎๛yย-๛ัญ๋›ใdSR%?-Mข›{]^XเDqSœ ?M2~ 3}้๖ๅ ๓ุJึl๙ธซl่@9ภbใ ฆ8N:1Qqqฆ๒ภ]+eใwlB5t8ษ›VฑQ—ฑฅIl\ฎ… ๏ปQ%ฎผํ“ž~แZอb*๗ฬ7ƒ}O‰เsR‚ K์หDH ‚ ทฒy_"๊ิl~ื6‚G๐zwฃ;ัu-ต›๐fK“ุจ‚สิกฒอตษlพkKŠŠ˜ย้๘’ณ/Ÿอe wะAf฿/nzฺุ้*Yะสgบa›จXœภL'>Jrแ๘™šฬ๎ถR@7vl~ฟk‡›ศ็g‹ส˜ูห$c'ฐฅits P™tSบกํชˆŠซ—1ล l\u+k‘&DGฟ;๛›฿สx๖ซ๘ู6๎{ๆ๋ท[L‰AXb,BJA๘`๖'ฟbญHDิ ซจL~๏}?Jะฟw^<ก”ซฒY8uอššˆ%8C|ๆโกฑqE.ๅ@{๘ศ>๒k๘๛\{ ญ-ƒ™ฝLt๊วD๏สฯ,ส™๎<ถ:‡ืพ‰`๐ผŽ-.P ๗'.cๆ&ฐIkBีตึDT&q๛ ฃุD*ขnฯZ‰N<'b๊"BJa‰ณ)Aแๆ6่O~ลZ šน๏ƒ๖Qaแ๖Ÿ!ณ๋3่–u(ิ\‡›ฺv%‹ศฬ\&:q˜๊YZ๓๎๖ๅ‡่|™=_ภ๋†—๏Cež/SiB:uŽ๊฿ยฬ-–Šย]รFผฮ-51ต ir๙ๆภค˜๊,ถZฤ'jaๅJ.ํ^‹ต#ฆ๖…ป>Gม†Gv1%BJa‰™)Aแฝ7ไ"ข>(^K?แถOโ๗‡n๎Eีๅ)d_[7Ao๘(ษๅทIวO“N_tc่…;ด๓ัx๙^ย]Ÿร๏ฝ ๋]๕ŒI]6ธึ0ฯcก˜ฒI•t๔8ี7พญส lTๅ‘{7๐;ถิZ-<‰ๆง๑ูjuอฯ…ผี"ั๑gฯ‡Ÿ๚็มฦ}c๕>฿๎z๚woUL‰AXb[&BJAธ๑\DิE7๕๎๘~ฯNผๆ^—yใ…\™โf“ ˜ผึกดW‹+2˜ฉ คฃว‰ฯฟJ:vาจฃ’\ิถใQx๙~”ทืUDๅ๒N<ูิeอ’N]ภฮCX‡ืฑฏu}-ทhŽส$฿ ๚ฦŸcำXZม๎6*ƒ๒6>Fธ้๑ซk7฿ kAk@aS'ฅlRล'ฑqQึ่vฏGฃผะMBฬิป{šะš๔ ๒3‡W๏s๑ึฤ”)A„%ถg"คA„E็๛ลฏ˜j๕ ‹"ขn๊Iชั ํ„;?ƒ฿น า็ยฬ 5ˆNž%น๐:้๘I=๘๐:6กฺ]ๆI\ปั๔—'u๚'$ฃ'0…‘-bตv?แก›z6 ๆฎŠยา$fv[™Ee๊km•ื_+กูมภC่†ะ ฤ“I1ฅIHๆฐฉ\๘!>*๗|>tc:ไ~WฐๅLyส}—ŒA…9tC'*^ๅNึชmฅ€™ฅPZหE ๋‘ฆ บฑไๆk1;้n+3& 5fnœ๘ฬKozm}$๛ศ—ฏึ๋rณbJ„” ย!%‚ฐฦ™—฿๏๕ูyฃJIR‚ 7F„” ยe๚ะใ๛ญ ข๙ธืพ‘์_$๖ PkSˆซคำ็I‡฿%:๑Cฬ๔ELir [ฏe~^—-tEt„uNtค1ถ†ืฝm„๙C f๚ษุIโฯ’NŸ_[2D{xอฝx;Wd‹จฉ $็_ลฬ^ฦฤU”า\[๕พ‡@@y!แๆ'ะM=่ฆn๗:~าุeQŸมฬk'ฉชsฒ™ษ6โ๗ํล๏Šืฝร–g›\ฅYc+3nšแฤYผๆ'‘>๔=†4Aๅ๒x[\xฝบ:FัFeา๑ST฿ฆ8.ูEK]วZkžืนฟw7~็VT] hJ๎็Qษ $k?ธ@4]ืโZ2รWง=ืjฑU๗็›าŒศCภZ &Aeš\^Ce๊jmฎั|ušญฮaญฉUพฯYBiืๆ๊๙ฤD' :๒อ_ฯ8<ด:Ÿฑ๛๓™Gฟ๔๛~็๖gฎˆ)R‚ K<"DH ‚ ฌ ฆํ฿gญ>ดPD-z ๘ผ๎dv}ถึ>ถiฯวฦฬ์0fๆ"้๘W15sัฏฺ'คB7๗โwnร๏ืyตโญ!Mฐๅา้๓$฿ฤฬ^r-`ท”๏tอ?ฃ4ส 6~ฒฏฅผะI “:15z‚t๊ั‰g1ณร๎`ฝถถ0จ0็ฺบ:6นฟถฌsกไพปNถRภฬ\"พˆ๒3่๚Vnw๖–)McŠS}{๐ฺ7บC7๊ส้[-\z›สซษตŽI9Žป4•9'{ˆ๊‰ชou"<*9ั•ˆ๛Š๚j่yX 2ฎ4k%ULi [[ปแ๔สsำ๒rอ.#*S๏dRฯW”ูJk’›Qืโ…nสจMฑq…๘+kBL๋|f๖Oษ*BJแR‚ ซ›้C๛ญตั—o๊มiฤ๏ใฤTCGญ-อ๕ถq3uŽtbˆt๊<๑ษ็œ IฃUuอtS7^วๆZ๛ะ.tsฯbU™!พH:|ิU)Ufo“่XpศS^Mn@ธแ#xํั-๋ฎๆๆX‹)M‘Ž'>Jt์๛๓‡ฦUพuA…9ผฮญxmƒตษy่บึšˆ2ฎk๖2fๆ2x>*ฌๅ ๋ซ๋•N_Biฏg^พฏ–/uELLy†ไ์หT๏ฆฺ8W+6*๏#่฿‹฿ทwพ"Šธ๊๒โrM|คที฿YcภZtS—kๅ rNLีชHซุjSม&•5TีฆA{ฎช0เฆ^นืล%lตไ๎qit๎s‹E–ญ‰/๙Atไ›ฯไ^•yำ‡๖B2˜?๐ฃรฒ#Aธๆฉ BJau๒AEิuG”๚6unคซ˜ชoE๙ูy1•Nœ&=I:~Š๘์Kซ"๘\7uปœจž๘}{ัอฝฎeN๛ตJŠf๚"ษ่qฬไ9ฬ] FVุjะF0๘(^วft๋zืhมbฐๅ’แฃ$ŽŸx[;XฏบMKE7๗แwmร_๗^ว&t}สฯ`ฑP-a #ค“g][ž๊.ดb]9d+าย(สฯ8‘Y฿ถ ๘œซ๙N&:~•m\;7$cฐับฉ๋@ีทฮอ๊\MDอ`ำไŽ’ู4FyชฑปzžqีkเK\qblvk“U+ฆ, ”v"*ำ่*ขผšิหฎRญ<ํ๎๋w๘>gฃJœŒพ๛อ๊‹๔Vซ˜Anฐƒ!%‚ฐบ๘ฐ"๊Zผ–๕๘๋๎'ุ๔8^พUืZ›Jๆปœœ‰ำ$ร๏’\z“ไโn ปYAีJฃ๋\{^>‚%Dิ์0ุ้Iา๑!๎~—+\ฌ1(kP nYื6ผึืRcฌ5ุส,ษๅwˆฯผ@|ๆyH"lR]๙›• ‹n่ภk฿X›žท ะ๎ฆจกฑq37F:~ 37†n๊qmYw=ศ‰)k fvุฝ็ฎm่\๓ขเsาS&:๖}โกWต˜R:ภj—!๔๎ม_บฑ ฅผ๙๏–+ND%ีป:ะMไซG7ดฃ2 .|ป6ตo^’U็0…QWAt+์๎ ึX”RNฦๅš]lcฑIโฒk_,ฯ๕฿[ฤ” ยฺB„” ย*แv‹จE ?ใd@฿}๘๋ฤkpทึบส”ธB:1Dr๑ โs/‘\~ฌkYถhmD็๛๑๛๗บึฏ…"สค๓ญ_้๘iาฑSND™ไ&S ๏›ฯO๒Zึปlข4มš[ž&น๔&๑ะ‹ฤg_ยฦeH“๗™V~UืŠื>Hฐ๎A'ขšบ ผฒ\qNCตสคะษŽeNmำ•QนFŽ-ฎํsa๐yc&ฯQ}๋;คฃ'V•˜R:ภb]ตX๗N๕บึWฅkืฅXหmšฤฦ•{*{lš 2่บผ“œ™7‘ฯคุจ8m\bๅ&€)ฌIมZTฆก๔๎Bฬ.ธ฿ท<)MโžV†‰˜AXˆAXแLฺŸทึบ"๊บ‡F]ฟsซ ๙๎ูๅr๊Z Mฑi„J˜้ ฤ็^&><้ฤRศ๗D{จL^s~฿^‚มGk"ช ๅ๙๎pV-บŠจ‰!า‘c˜นQ'ุ–6M\fQ็žN6vบ1kฑัฆ4Er้-โก]๕Zฅฐ์~โ๙่lณ ผxฟgท ”๋ฏถx•งIง/`fG฿_฿ถlรจMySม๏qม็*ศ]SึUฅค#วจ๙Slqre‹)ํปฯ˜๖๐{๗ <์*ึด็$o\คŒ)Œaใ๒ฒZ3k :ื„ส4A˜C‡ .ว-M0Qข ถ:‹)ฯฎ jฉZี^ฃย:t};ชฎูM…Daโ"ฤleฮต]รฒš6hฃJ\y๛ฆ๑็๗Fž๖‚ ซR‚ +”้C๛๓s@Yšๆปzๆl์ย๏…ืนอUNulBๅ๒ฎB'q“ฑฬฬ0ั้็‰O3;ผ žxฺต~5uฌเaผ–šˆ œˆห˜ย(้ไ9’ ฏนช›e>อ&Qญ eบ๛ัM.เป–]dหำค3—HGŽŸ{…t๘จซ€X–2รCux๙^‚MOเ๗ํqฒ0ำเZผL์&็M_$- ฃPจบŠษ๘Iง/5๘}๗ก๓}ต๗ฝ@LEsฤg_ฆ๚ๆทGถ–kด2v”ž๛,zžหˆบ"ข<›&ฦn(ย(ถZXkิน๛E]ซkiำตฯ_uโ+๙f—๑๏ก˜—สCีๅkykYPสU|%Ule37ๆ*ง–‘ˆZtKขฃ฿อoๅ<๛ y๚ ‚ ฌDH ‚ ฌ0๎ฅˆZQ.wฉ{'~฿ผ–ผถWa 6.aๆฦ1…1ขใ฿'9๛ฒkyป๏ํใ5u >VQ๋\vส•T0ลIฬิy'mฆ/ ดฯฒช์zฟC[TFe๐๛๖ธชฏบVRฌ]Š)Nธึรัใ$—";9_ฑฯส ะM„?฿ปว ›l“kŸด้|ีš™น&นบ~+tvd^"ฮWต-œศWš">๕๑ู—kylห๙sจ\K(š`๐a‚E7uืฺ^๗ณธŠ)N`ฃJฏŒฆ7k ˜ิMญMžS~ต–Cาชซ*šวฦลe๖YTXkQตjPุAฆV]ƒI0•์ฬ0ึše+ขฎ[“j‘่ฤs"ฆAV"คAVหFD]‹๖๐jเ~^ผ:—“ฉฏUUH'ฯbf.ฝ๛]’‘w]X๎]:˜้ฆ.ยอOบ์ซ–~Tถู,-ฎอฐ4I:užไห$ใงQ~fJ4ถ2‹nhฏ‰ฉวPน&๐ย๙j37N:z‚d๘า‘cคS็1…ฑ{'=”Bๅšษ์tพ฿ษ&ํ_ญZ›รฬ\rmŠaŠ9@ฟfnย:ฮญ.ค]-h3)ฆ0๚ณ๗f1–]ื™ๆฟ‡s๎ำyž3rN&Gq‡”Yถ6บห ฬ •^ ไS€Tไj๔[็C?4ะ‚ ~่๎j@ๅjฯ’lฆIQโ˜ฬ$™๓๓<w>็์ฝ๛aˆL’I2‡ˆศึA$ษˆg฿sฯ_ฎ๕/W แิyz_บ5,ภU ผมoย9YืJกเ.ฏฌQ%QX†ุฅแKฮ„€ะ๕ํ4‰ฮK~v"_Tฅ๐๓<œ ป˜ข … ขถขฆยKQuก345ฏZ ้6ฺฑ-ฎ_๛;ฒ˜b†ู3ฐb†ูแ์X๕๙ŠNP;ภ7 {Ÿ†j๊#๙ใง6of๎2ฬาMืฮยฌNPฆั!ฺ๋เœ"Iึุ ‘jคCฝˆ’ฅU˜•qD“็ญLฤีRfoผiค‚+e!:ก;C๗= YำOฬา€ฐ๙y˜ล›ˆf/"šฟ ป:นอS"Y‡ฤฑ฿†๎Žื(g€ชึ Kิ๎iBภKลน={i฿BAำ6ฟY ~"ีmB˜์‚‹‡hแ:ต=ๆ๗ฉซแl๘ex^กj<Œ…[ถœขสีฎ^)gB™B0 IDATคะD  žKำ*\XŽงqฮวSHๅถฟ>M])สˆ"๑naรP^ƒ-ฎภ™๊ฎซช๗!‰ฉ๘w™ำo๏†avแNˆ…ร0ฬฮ%{ๆีำฮ้ั,ขพ๐`I5@ึ4รz ^฿3Pอƒโ,U€Xƒpโ พ๙ j)็6m"฿บˆRGใi€Mqˆ4๎„aฏŒ#œ๚vmยัดณฝ%:ึ/†‚ซไก2ฝP‡ใ)uwe9สฬZพp๒ฬ˜์L, –พGผ็แ พHkTำ แ%Iะ˜ถธ ป6U!ต๑{รํอ5ฺ ฎฒQำvˆคว_+0หท|ื0นi?ฝฏ1(ึภ๘ผแ—iต๔ต(„+ฏย–ฒ€ hญ[3gยx"_# ”oฆHธฐฉ ฉœ`ทๅ๕’ชำตTฅ“จ:ีU๓q•ZBศmyMพ&ี"ย๏}\ซ?อœลY90 ร์XH1 ร์@ฒg^}=Qปึ…ิถ@ค›เt๗4]L๙t@. ฝ‡h๎‚๋oาA.(ฦ™9๚4$มF^ƒn?ีL’~ฮ„pๅฬสขษอ_…Hึึ๎iษqg14`#ศ†.จๆAส.สtC(ฮ™๖0ป:I๙ๆฏา„Dm๎ฆ#ีฏ็I่o@ต AีทSลO~X`GXก6ร–ขณWฑๅ5ุ4tฯำPญรŸk!upีข๙kจ^๘ฏp•]ฟญ>๐[„e +xž‚๓“ BฤUฒฐลีฯ…•๏ํ5sฦ@ฆฟ†DŸฆส#kฉZ*(P๎YiuKชฅœต€3ฉFศD ห(D!‰ 9ˆฝS๙Uื„ลร0ฬฎƒ…ร0ฬb/ˆจฯ=f 3]ษ๘G บ๓(TำUKYg# ฌ ั%„ท~WYƒ‹ช4:kฟฝ„ฌi‚72t๛!ชฦชmฅรกฑˆสยฌN!š<ณxNi์อJฏEj@(จฦ^จฦจึ$ฆtฮ†@ทษๅ็\{ัุ์ิgึ๓aDƒHe ปŽร๋y’~fCDฒ๎3“๓ฬ๊$ฬสJิฦำ ๗๏ลdgบ๓Tc/pw6‘ณฐๅ,ฬ์%T>/€า[3‘ฯZ@๙P-ƒ๐zŸขuซiบ#yื3ขชjSr฿ญ™s€Le 5~ ต(ฏฟฏใฬ&T ฐๅตMส>ฃ้y"Q gCศtsœนฆเL[Zซไแชส๓ฺ‡๗‹)†a˜]tR`!ล0 ๓๘ู{"๊‹จฆ~ศบv๘Gพ ี:L‡l!mด–„็`ๆ.#œ๘ถธ๒ๅ:BBึตQK`A’umฑศP”cSษQX๙ิ˜•๑Xp‰}Q)p?งhVเ๕?™้‚j V>/E๋Q-Rxiมฅ 1•Ÿ๐MFฒบ๓t็qจถ‘;ก๒สฃ l•ใ๘>๚ฬบT‹งฮฟœษw3งฯŽ๑a†ู9ฐb†y dฯผ|ส9 $N๎ืk ฺม๋y’ฦล'jจีN'ย–Vฉrf๎2ฬU„3C(ŸไF๛!่๖ริj–ฌƒšชmชุ์4ข้ 0ซำpa‰EิุL!ผม ๛H %๊๎ˆฉา*์สlq ีO–&$–ฒ_T่T๛a่ถจฮcPอ4O'จ*ซZ€อฯรฎNRำืx}HxุตyจL7TศFึบ„pQณtแอทM‡Hึ%5พ|ฟG"J@5๕“ˆ๊8B"JiQqพI}’ป๖H๗SกตqีฆNlศ'gBส˜ชไ7ชฟ,cส9ะดผT…•'๋จ"สYj\QCx]พr]XL1 ร์8XH1 รl#ฑˆ…ฤk|5uภ ๐_ ฟ๙O6P;Š1ฐ…E˜ีIธJ€€ฌm‰ซ๊้ฐli2™ออ"šป ป:[ษลaๅ–/๎ !$ผม šกZ†ฉฉ•ฯYุJf้6์ส8‚๋gasณTม&tAจ–ก8ภ~˜ฺ๏ผ$ชƒ2l~fm€ุ_Šฐ็"<\P†ฌmฅเ๓xBaUšศ7wมๅŸมฌN%ฆ>๗}ข.,Ceบก{ž„๎<YืF๗VภU‹pa‰ค‡Xx<ฤ: ฟ"DR*YOไ3pQ.(“ค-.ึ@(gHะ ํoHa‘ส@( ็ \Xฅ ตrŽD ย_S ร0;R ร0‹จฏAjxฝOรz บ็$U=N}เฅ4*ฏ็ญอ!Zธป:gN…|-yg!;ฏYจึจถ@ช8ดZภU๓0+ใˆf.ย,^‡Hิฦ•Q)kศKั๗ +ฐล%˜• :`๋œต›๎ฬุRถฐฏ๗ศฆพ8ุ.1U-!š๚ีO?ช‚>—’ฎ4ผŽฃะ}OCึตSถWP5T\ลCSฺxฏ๘HฤD$—R๕~ dข–ฎฟเ‚2ตฦๆ็แ*kดFส‡ฌiฆ*5/X˜.(ภ–ฒ$่…bก๛จ๋R-"šฝ๔7ี๏“9}6หW„aๆ1l;YH1 รl,ข๐ก”j€?๔Mx#ฏBท„๐kปๅ…U—อ^D8uฎZL•/fฏ…๒แ„Ls’ฺ%;C๗‰ธสฃ8Kํ–^’Zศย*lify 6ฟU฿xษx๊ณู˜์ „าPวก๊;พ0‘ฯU๒n แ๕ณ€s$[ภ|ฒพฺ^MtGD•s,ขถB€XK๙’u€Ÿ†๔R”Ÿg#ธ [ฮRฅTชŒspA+TIUฮฮททR†t‚Z_ฅฆ`์  „eชพ‰สเฌ๒ญ_3‘สPีT"กSภ๚=โ่(ณซUh‹จ-‡ลร0ฬcx"ฒb†ู<ฒgN 8็F!ี๓ีธŸง„Hิ@ึถQ–ิะKP=”#ฅ|8XภDิฎ'$UแH VฉฌดŒh๚cDณ—`๓๓ยอlม:)’†^ ๐หะ]ว!“ ฑ”Š…ˆM9,,#ธ๕6dฒžฆ็ฑุ6ษ8 >ฯฯCึตQ–Wบ๑ฎ‰|wํ๙ฌญจ[X† J’k{ˆืรKBึwฦ-|wW‚: -/.รW`"ณฐ˜b†ูฦ )†a˜G‡Eิƒ>}$„—„ฌm…๎9 o๐Eจฦ>jUYQAถธ ››ก|kกš๚ก2]u€าthซๆaKYDS!š๙ฎด๚ฅ!ฮฬCH!เ‚2t๛!่พgh_*CdO๖Š…œƒ หฐล˜ี ภY:ls๐๒ถฏ›ญไอ|‚ไS ฒถ-ฎภนซิ0n3หcpA™sฝถ๋~‚ )เผฆ‰BฯeปgโŠOVโถฺุ<œ YLm#.จ„ม•๘_k~๗GฦWƒaf‹žŒ,ค†až์™S็Q๗๛ิาƒจkฅ๓มกš๚7D@Qถด ป2pโCjหห/Bึ4Qpv็Q่Ž#um4L’˜ฒลธย"ยษsˆf/Q•ลิ#œ…ิpBBึwภ๋}๊3๋DยฐD™6a…ยๆ๔ฦ41”yณ6KmdฮR๕šs\1ต ยรdgเ*yx}ฯ@6๖าšA_๋wคGqถฐ,ฆถl]X ‘ฌ…จ๏€๐RqvWH๗J~.ฮสP๕ก—‚ะ$})hพ@ƒ ‹$๔น v[p&Bp๙็ แีณฬ้7ฬW„af“Ÿ,ค†a•3ฏŽ งOCขฏฦW=qdm+ผoภZQ™รฒ‹ช”?”Bxใ-7฿‚+ๅ๐๙สY ีq^๗I่ฎ้ dบ *SK0หcˆฦ฿‡YพM!ฮ,ฆ่๐์ฌn„๎>I๋”n˜ะๆยj<9oั๘๛จ^๚GจๆAxฯมz™2ฃ4„Ÿข๏Uษo„›C ฟ€`๑ฑ๋f‹+ฐี<ผฎใ™žธŠ pQ™ึ ธ ี2D๕bqธq๐ฎ`๓ ฐ…@jมๆp3ึ„!ฉjP>ez…eช๐,ฦ-“Jร…U’Rฉจฅuด.,ัŸชpี"x‰ถW-ข๐ืฃใBุS™ำgว๘Š0 รlา“’…ร0ฬฃ“=s*caOณ˜บ7ฒฆเ‹ะฯB5๕Cึด@x & ฟ๙ฯอ ธ๑&‚๋gแ*ภF_=3ิFึ๓ผž“q@p ‰ฉ‚€ฃ™O~ถฐH c๏™{บ‚ Tหtฯ“Pอƒ5M^,–ข*\ifeแ๘{ฎ \em#฿ ฮาz๔?ภ+4ฒ^'bแ(แJY˜ๅ[0k๓ฺ'1%5็mถฐ Vจrฐก3^3ช64K7\{แญ_ยW 4’O+๘ ฒฎP๚๎w›—VaK+๗สžb`—ญ ’๕•ƒT๑‡วะ…•ธฺ้ณืุYCRสฏ…HึBz๔ูมE ,ำ็f9วีR[นX-ข๒มy฿ฬŸ2งq–ฏร0ฬ&>*YH1 รlbJ่ฯW้ แW {Nnˆ(๘)ศXDญมๆfN]@pๅgpฅUธ่>วอ  ีุีv^฿3ะ=OB$j คGbส†ฐk๓o แ๘{:๙ตขk_ธ*yศ†.x}ฯPv]+เง!„ค–ขrfeัฤn ฎฐt๏uZSฝOQKf฿ณ ]€๖)'G(ุ๒*์๒ฬ๊„Ÿฆเs8–~wม–`+y่ฮcP๕@"ฝqo™ล›ฎŸE4๑‰ษ)’*ำฤฟ๏ภซฉฬFnQlCH˜—a๓‹\อ๖ภKฃจฒ)Q ๘iศuฉkชโ,,ภ…eศ๛x๏ j•Mิ‘T๗S4=ั„ฐีMใ+็เชˆฯศEๆ‘?ซE„ท฿๛4ธ๘Wส"Šaf‹™,ค†a6Ÿr.’๕๐ผ uœZพ๊ZฉeE$ขึผiDำ#ผ๕6la ฎšฟ+ุ๗A~˜„๐S ]ะmก๛ž+ฆjฑส kaV'\? 3wๅฎ€็ taฒฆ‰Z๓Z†ฉบ&Yv6‚ซฌมฌN!š<‡pุตYธ ‡”ีšPภน๎}^๏ำTqีุ x‰๘Sซ“ˆ–nCฆ๊)เ™ืไ~๐ิšWสAw‚ฌk#aหCณxมอทMž‡อฯมๅ/_/!กปŽ!๑ฤภ๋{Ž๎qW๐นตฐๅ,eL•VYL}-’DTฒPปTp&"มWZ‚R|yอ.ปข็dm\ํ™„ฺจ0uQ…„~Pไเ๓G\dล0 ณ}ปR ร0[วS"Y๘eจŽ#P-ƒ”U“จฝ#ขึวฬ'ˆ&ฯมๆfaหYภšM๘๑"Yีุqบ9่๖รฑ˜`"8ภฎอ"ธ3D๓Wฉโรzบ(€๐ำะO@ท€ฬtSk‘๔เœกสต์4ยษM‡ษNWๅ=฿‰4t๏ำะGก;’ ๔า๔:œ+ญภฎอ#šฟ™j€H7ว•ผ?๙<ถฐ[ฮCต B5tR&ั]Qแญทอ| “›…ซ่พ๒†^Bโ‰?€๎:N•„w‰)pฅ,liฎ’g1uฏ๗นŸ‚H5A๘I@%(ฐ’ˆrๅ\9K"๋d๎Wทึ$!“qลT,Ÿœ ใlฉ<\~ฮTYL=่๕ญ\k!ผ๚๗ฤ"Šaf›ž ,ค†aถž์™SO:'ฯ@โตฝ๗$ฉฬ†Rญ ๋;โ๊‹จp™B'โujŽƒๅ•Or((ยฎอ!š8‡h๚c˜ี ุา*`ยG>ฐหฺๆxชbT๛aจฦ^’…ฮRๆW) W\B4{‘™—ไ๕๚บ˜์d]_um$yM@™^ท‰h๊lv ถฒ๖H‚ื?๚$N>T๋P|c1ๅ\X‚+Rพ” +๛^L9€L7าT ไ5ช Jิmด๒นสLnf๑ข™Oaณ“ Vณšเ Jส‡l๊ƒn?ี2Dำ๏โ)l+ฐ…E˜ล'ฯม,\‡ษMoYๅฺกPm๏ภ+P}๑๋j!1%W)ภๆ็c` ‹q%๖‹๗ŠD‚ ก{ ๋ปํQfuัไ9DณŸฦ๗ีา– แ%‘|แu๘#ง(|๎เsk(_ชดJำ้ทท†5สงชB/Imsส‡s.ฎผฬรWเย Vุฆ๗ซ32UฤA๊ยOCHMb*,SตVต[ฮBžj้L„เ๒ฯYD1 ร์„- )†a˜วG๖ฬซฏ;งG!ัฟ^ฏL7Bต€j? q„๒€Rw‰จ Hy@ณaฎ!šฟ›_xl"๊ ฏฟก^stภn์ฅรeไlKqศ๖์E3kณqxฐฟ๛\ี"U#ีwPฐ|Aศ8XUa K0หc”ต2†hสึ‹จฯฃผXLฝ ี<6หย@ศธตršฺ*k๑๋ท{ท•O(ธ๒œฉ@5๖Cfบํ“ˆสฮ š˜Z^ฎั}ต]/+•A๚ๅ๏มx"UOำื1UL•V` Kwๅํ€zg-„Twฆๆฅ›่3Žฺ๒‚ณZ ๖_ฉำ๋t้ Ul%(RR–U\-…jถœทํ–.จ„แ7C๚ท~๘yย0 ณถ>,ค†a?;]Lษt#d๓t๋t๗ จๆAˆdUm8Gํo๙E˜๙หˆฎSฅัฺC„`o๕SB…Uหผ็เ ฟีะh?žZ%a‹K0+ˆ&ฯมdงHา์’vpaฒถ^๗IจŽ#wrf„ UZ…]G4{ัโu˜ูKpQ๕๑.‹—„l่‚7 t๋0T็1j…๒RT1U-ยฎอยฎัิ8‘ฌง@๚=ำส'aหซpQบe2~O"ขh๖2ษจนKt_=–—จ šz๑฿Bw๘ยD>g" ๏..Q%ฮ†4ฝbŠBฤqง๊(xW]ฎธ˜ถผภ>6๕ลJั‚DD"‡ิS๘ฝซ่s ธ๖MN› *aดpๅ'ีw๒๛™ำgณผ๋`†ู!,R ร0;‡•3ฏŽ งOCขaG“ำ ]Pํ‡แ๕œ„l€Lg่ฐ์UDๅฉๅห,\C8y67Cู);๚้'็ {Ÿ‚ืt๓P ”ร"่PiKห0ซ“oพ ››‰ม{ศ ฮYxว ปOP^Vข.;ย•VaV'อ_…™ฟ‚h๖"URํ'ฃILีถย;๐ Mๅ๋:‹'M๊ฐ ››Yพg T}็–f๔l๑‚ั๛ฌธ–๏dฐ้œ )\~j\๕1lnv‡ผอ|่g‘|ๆโaฉ;bส9bP\อ/Pฺ๋.ฮZภ9’Pฉ๚Š#„UุJˆชpฅlฦงv์๏ฐ1`"]\ฆEย<\ดw'๒ฑˆb†ูแป!R ร0;‹์™S {๚qŠ)‘j€ฌk‡๎< ฏ็)ศๆ~jSั ๎ Šp๙ลธี๋*ขษ`Vฦwฅ~ ภ๓Pญเ๕=Y฿ แงโรต+.รไf\{6;M‚D'ฐ3ฺ’$,„sP-ร๐๚Ÿ%ฉ‘ฌง๐kยUr0ู™8#‹ฆบJ~็.‰๒ Sศ:สา]วกปžˆฬŽฤ[Xฆฉs—!”Y฿พ~๏9ฐ…EุjบใMิ4อๆ็iญฆฮ#œ8ป6ป3 /่o!qฟ‹Ešปƒฯ]Xฅjฉย"I›Pอๆโ p/Q ™ฌt’~ญฐJSใ฿‹&้+™Z“ฺ๋ใะ๓KBlTTบJ6?O๋บGชYD1 ร์’8 )†a˜ษ†˜๚฿o›œIค)ผ๓ผ็!›๚iคy\…ฐ [\†Yบh ตต-ํง!ต{#ง 2ะ]วจฒภฏูถฅุตyWN-nŸisn1%แL8Cํ‡ฯ“ิH5™pX-ภๆfa–n"šพ€h๚cšฤถ[P2ีีิu‚ฆ9vฅ–)ภธฐ ณ:‰h๖„—ข5;ตELP๘u~ถฒFฟSห „๔เœอ/ยฎŒ!แํwhภnธuา$ŸC๘ฟY( 1e l5Oฟs9ทƒe‡ธ๓XำLUQ^ B(8Sฅ๖ผฐW\†‹*;ง5๏Aอ๚Dพšˆd- $ิœ…‹ชฑ˜ZŸธ{'๒นjัโ๕‡Eร0ฬ.ู‚ณb†ููdฯœpฮBช?*#tขฆบใ0‘oA6๖R8ฎNppae#[ษฬ]Bx๛]˜ี‰ฝwฑฅ‚j่„w๐ืก๊ใ0๐v ูถle .ฟ[XDpํŸแยJ2ถฝgWอC5 ภf,Ÿกi_ฐ@P‚Y›‡Yบ…h๒CD“็aK+ปxM4dM3Tt,ฅT๋j่0]-ภfงจb*QYืถƒไ‡€ณ–Zฃชy่ฎ' š6ึห•ฒฐksฎฝเฺwMฌeหิะ…ไ3o๐Ej๋•๋ีCิฺ๋*ุx"฿ฮฉ,"I(€XD5P›žˆ\M%ุโ2\XปB3!DขžขมKาKฅkเ‚๒iๅๅr\ตˆp๊ม๙Ÿ|7s๚์๏†av,ค†av ›/ฆ„๒ าะ]วแผFQ5MYI.ŒCฐณSˆฆฮ#ธ๕Kุ์ิฟุสƒj์ƒไ7กบ Z†H๚๘iSลeุ์1eถบ%IPๅ“ษ:x฿€jZUhrส8ย[o#{oืส{_Amค]วก{ž„nl์‰CฆM+ญภไfaฎวZ้วXอB•Zfu.(ฦQCด^ฐี5ุ"ยซ„เ๚Yุโ๒ฮฯ^ปtวa$žCx}ฯศฏฟ‹ย8ทจDแ๔Q๙ฑ็9Aค2ต-‰ก)+(Q๐w9K!๚b๏}ฤ9k!S ษ:ภKA๚ฑ˜2lXชล;ำ-wp‹(†a˜]พฝc!ล0 ณปศž9๕คs๒ $^{่o"dฒบ็)x^j„L7วกท๔ท่ฎœƒออ œ๘มท`sำ{โภ@I/ ูิไ5จ–a ^Š2ฆฌู@feแญ_ลืoณฏmWตญะฝOAต ๔๚ดฏ(€+็`ฒSˆ&>D๕สOแJ9์ึษf๗uEฺ๊ {Ÿ†?๔U๓ี4“,\>_›ƒอ/ึฤ•Hnี๋aๅหฐ๙E่ฎใTั‹จ๕ื\{มๅŸ๎๎๊ตฏ@w?ฤ๑฿…๎:‘lุ˜bนัW-ภญอรูp›ลUฌ ?Y็*ลCย2l%T๓$ฅฐ๗?๏œU…y)^๔™ใช (ร–spีŽสฬbล0 ณG๖ฺ,ค†av'ู3/ŸŒ IDATrฮ}P1%’๕๐๚ž72TหP\e!6;p}ืyใ`ฟฏ–~ชํ ผม Aต าฃCถ5ฐฅ˜…kˆๆฎภฌN@ Uะ”!ฺ๋แ๕=M"ชฎmcช™3\e 67ƒh๚*็+ ทต…๐๑"๋;่ฝ|เสะ๒k(๗K >ทล%z*ช$j1e KฐฅU +oŒ๏-‡6วฎฦ๗ี>^฿ณ๐:t็qj‹‹ร้]ย…8P{!žฆธตkใฌƒLีCิถQธ๗zuก จjซ’lดง๗อ}D๙ dmDฒยฏขˆ+z.๛ไDQ ร0{lอBŠafwsฟbJคเ๕= oเPอƒTeใื|VDๅfM_@pๅ็ใภมฯ BiศDTผ็ :C5๕RB8 [ฮ"š๙ัิ˜ ค—คš>tจ จ๛$THœcU !–W๒ฐนiDำŸ ธ๒3ุrว~[+j‹“™nzoฟ ีิแ%II W-ยฌNยๆ็)๐Kp›สg๓‹V~ฒฑ๗ฎ,ขfuแ7๚%‰์ป๛ส9ะฏAต„Hg คGนEa ถธBูEAiKฺใึซ€dM3ๅ&y้X๊†ฐฅธต9ธ(ุ˜>ท๎ฃ๘:™Bz๕ํ$ฅผไฦDQq^[ฑTถนjแํ๗> .ีŸfNโ,?†a๖ศNŽ…ร0ฬ {ๆีืำฃ่ฬ}ช^s$7Z†!๋จ’DjQ•5ุตyD3Ÿ ธ๖Fพ\W•6๔เ๔R฿:LYF'ก{6ไˆsฎธ‚p๒ข‰`หk^ ฮ†_่ชไ!4t฿ณะํ‡ :ฉI}vr^4{แท`ฒ“ผVwก{ก๛ž…7๔U'yiฉฉbชš‡ษNรfg(ศ?‘„~ฤ jณ6WษBท‚ฬ๔ฤ“)›Z9)ฯหๆฆ)?W*‰#฿ฆ‰|อ‰๚;นEA*๔yTษmŠ0t.nปญmกV4ๅวR7ข บ•q’๎bฝ:‹๗ฤ@,ฆt2SP~\Mๆเย*\Xขฯขตyบ—ถฐฒEร0ฬ฿Wณb†ู[ฌ‹)‘ชํ๗_€๎<ี"ฒฎย่›H6tSปž”pA™‚ตซDำ็k ’ P™Nุโ*U่x)ศฦ^จLตRšvmŽฒยฆ.4,,qฅแ#เ๕=Cbช0DMๅYKaฺAฎœงjNg!ผ\X…P>Dบ๐๑”ล4K•<ฅWึโ๛g๓ƒ์๗๏วœ"๙—จฅJ4ค๛( ่บGUชไผ‰|,ข†a๖๙#……ร0ฬ!๗ฟ}gภ†ๅQH๕ว|5ถ๒้*!แฝo๘e่ž'!5สงV็(ซ+ž่ๅLWฮย,D8}fแฬโuQ[€l่„7๐x)ชd‹ซืเจ๊ฦ,฿B4uมต7`–o๓ๅฎ๛จถ‰ใฟo่%สําษฯ>ฐ&7ป6O๕pœ๕p&„๐า4ะม‹'๒ญท\%jo{/Wน๘7g2๖/ืๅ{?๘ั๋NˆQ ๔เ[็_๐,ฟ[†a๎ฺฑb†!!ตqพ.ภฺำ?“๏์›c๖ฬหงœ๓GYLmยƒ5Yีะีq^฿ณPM”ทข}š๎–)Hู8๓&š,QัโM˜๙ซวYผVมีR[ถZ$›๚เ๕?o๘จ๚vเ3ฬ4-ัWŽฟp์]ุ์lv†*ฉ˜ญCiศtT๓ ‘ืเ ฝ‘จ๛‚ฒๅl~ฎšาเsf{pฦP _ชžฺ๘’uสหมš3ฎZ<#R ูpไ‡qJZ7*คุxฆฒb†นวNŒ…ร0ฬg…ิ]‹ตv”ลs_T? Y ี~Pf”n„ะ 8W ไ(zeถธ yฒฑชyถgเT 0+ใˆๆฎ ผ๕6ฬโ พภ›บX"Q Yื‘Wกšh2@aุ&ค*ฉ) €3\aแํwN|ณ:Iแอ< `s‘2YOขฐ๗ixฯA6๕Q๋คณ€ กฅใŠCภ…UZทjvmžึ˜ณฃ. M^ศyร/žQ}gDบq฿ŠจuXH1 รcKฦBŠaๆK…ิ:๛PLฝ๚บsz๎๘สว(„๖!j[ Z†เœ‚j‚ฌi‚ะI88 (ร—`–วอ|Šp}ุ ป๋; S;Rm dS?ltฐ.ฎภฎN"šป„เๆฐู)พได\ยOAึถAw‡?๒T๛ajั`หซฐซSˆf/ย,„ฌkƒ๎~บ๛ษะ์๕ #[XD8๖ข‰s0หทaหYภZp5ฃฌ‰Bีะ๗,ผก—จยPyp6‚+ea–วxเ <q”Za•Gํฏa.,มU๓pฅ,ฏวcภ•ฐr๑ฏs๋dNŸ"๊{?๘ŸŸ„3g๎%ขึa!ล0 sG? )†a˜ฏRดษ†๛oกtงฯพฑr]XL}้ใ“๒‡’ $ขT๋dm3e@ภEุา*์ส8ย้ ˆฦ…YฝทPRฝะ]วแ พQ U฿‘ฌง๏W|˜ี D3Ÿ ผ๙6lq๙ฮ๋เ๗‰€จiืผ‘ืHd่[อร–‚‹ทq}Eชบuช๓(tื šส—จ'‰Uฉšญฐ„๐๖/N ณt ฎœใuy˜%๒’ต-ะฯร?๐T๓ „WV๒tM~„hๆภั„7WอC๗<oเจึaศd=ต[juA‘r–ซฅถW-"œ:Fp'ร~Q฿๓ัง๕(€ฏยBŠaๆฯR ร0๗'คึฑ9RvtŸ‰ฉำฑ˜jเ'ง„๐ำPญเ๚5่Ž#ตm^ŠD…เส9ุ์ย้O^? ณ2q_‚Bต A๗ณ%ขพ›9}v_<DDญรBŠaๆ;5R ร0&คึูob*{ๆTฦยžNŸทbJyะmแ<uฒฎยฏ”L[-ภฎอ!š:เสฯaV'๛€“๒ค‚j=ฏ็I่พg ๛ R Rpa f้ข™‹ว฿…™ปสแฺ_ถษIeเ |‰#฿†j;HQBา8๚โ2‚ko ๚้฿ยๆp?ยP$๋ {ž„?๘"T๋0Dบ 2ู(Mm|๙ุข้ฉํo๑\eโหฏ(ผแo"๙๔ฟŽ3ผR€ ‰mvmแท„—ข‰m_๛ํtื1x}ฯBึwาภ!แLWษรEธโ \Xโเ๓M`?ŠจืGG3‰HŸมˆจuXH1 รใัอBŠaๆแ„8‹œ‘8cฅๆ์๋ง๖EIฤSบใ0ผแ—ก;B6tำ๔(ฉแœ‚l~ั์ET/=lv’‚ฎ๖gฉฦ>่งแ๕> ี2HU9ฮัฯŒ˜ล๋'>Dp,l~๑มๅื^]ญd=ผมเ5จถˆD „P$:๒๓oม•ŸมdงแA๋Dฒžยถผ ีz€ฆ%&๋ ”Objm6;…hๆ"ขนKิสW-๐ยฌฃ4ผgx๊)#*Y!Mก,.#ธ/oฟCืฺO?ะ๚ธ(ฌ…๐5่ž'I๋ฤฦืœ (_*ฟgS๓ง"JW๔i%๑ะฯ=R ร0๗ุSฑb†yx!ตฑA฿Ÿbjภ97 ฉx/žชeะKะวก{ R Y†‹Eิข…๋.LvŠฤร=ฺพ Iํfฒฑ^๏3ะ]' Z†่n œ ลa้ ผ~ถ”#Œ๖฿๓]$๋แ๕=ะฏ‘(JึCH ฤถksวAxใM˜ี)ธฐศ๋$k[(รh๐๙8_ช๐SŸSf๙6UKอ]Yบ V๖๏ฆำKBw‡์ทกAค›๎–W๒oแํ_ยYKษ=๚ธJ"•?๒t็1ˆšๆ๘{ฺ;๙_•5ุย" `ฮ˜๚๚kZ-"ผงมลฟ๙=Q )†a˜{์ XH1 ร<บฺุฐณ˜ฺ3จฦ>xƒ/@wƒl๊ƒL7Qห”` ‹0‹7xf้li0แึผฉกบ ›๚(วจํ ‰)/ุ.ฌ6B8๕ข‰zฎ”[W๎‹{ุ?๘-๘#งhญjZ t‚DTnแ๘๛ว…]‡ญๆใชจM\žšf่็เ <~"QO9HRมeุฬย5D3Ÿ šฟณ2ถu๏•ธู๔RPm#๐GNAwวญฎ^’หซE„ท฿Ap,ตฅ ฑyB$ฆdฆศซPญ#ิช}ภZธ [\!9–มA๔_r 7Dิ_iๆ๔/๖P๙w?ัiXฑiู‰,ค†a๎ฑG`!ล0 ณyBj๋0.…้w๓ว๛ๅ’˜’?†ฤkป๙๗ ๐_„n?ี2YำBU/paถธณxแํw`ฏร–ถฏ๊Eiจฦ>จ–axฯB5๕C6๖‘(s.(ภU T15qแญ_ฦญb{๔Yฏ<๘C฿„7๔"Tห0d}U'9›F8๑ข‰a–วเสน-ฯฺR}ะ='ก{Ÿฆ  Tf#D…eุย2ขนKˆฆ. švmnOWฒ /ี:L๗S๗ ‰:8g Œpโ}„ท~ ณ6‘จsาถHช่ŽCะ฿€jุhน…ตฐAลx"ŸณEิ๗~๐ฃืฃ›;]–…ร0ฬ=๖ ,ค†a6_Hญณ?ลิหงœ๓Gw•˜ฒฆ™ฦวทP๛U]+– Dli…&MžC4w6?๗๘ฆ)ชiบผ‘W!k[Iฦฌgๅ”s0ks0ณŸ"šฝŒp}ธj~๏l^5”ญี๗,t๛!ศLฯต6‡h๒ย‰s”T\†ะwu้'tชuชใtื ่ึˆšธ5อ„@X†ญฌ‘”š๘แิ๙=|.t‚&F๖?Gmฆฝ้ Iำuaz๛ุ์ t<๕p{๖ฃฮZ่ฮฃ๐ึ๘5€Œƒฯซ…๘^_ื๙XDmฎˆZ‡…ร0ฬ=๖ ,ค†aถNHญรbjง>Dช^฿s$ขฺCึทC$โๅ๘pjWวM‚h๖S˜์4\9ท3^พ๒กZ‡กปNภ?๘-ˆšfศT <ฎœCดxั๔ว0KทM}”v๏ฆ%YyŒ*:ŽB5๕Qkžณ*?๕ขษ`–nยๆ(XqพึŽ#P-ระGกš)วH๙qฐv\อ6yแ๘๛ˆ&ฮํ‰i‰ชe^฿3ะ' š‡ jš!เช˜…ว฿ƒYเ[ ธ‹ *ร~•&๒5tฦแ้‚พfธ ป6U๖M๐นซ\k!ผ๚๗ดŸDิŸ๐/N)ธ3€8น•?‡…ร0ฬ=๖K,ค†aถ^HลฟXkG'฿ู7›า์™W_wNBnอ฿:?ำO@ฆก:Bท@w€l่ŠCฐU<&>ณ2Ij*ฬ๒mุย2vV๛› )ชm„ฝ|›2ŒtPŠชR*kˆฆ?A8๙!lvัๅ]%ฆD*vบ๋8tืq’;~zc*[8๕ข้O`ฎมไfvT>“L7Bw?ี2 ี~*ำY (ยตKซpA ั๔„ท฿E8ฎผฯUct๗ ่๎“ะG jš)j fe แd\ฑUwLKœซไ!ผผƒง่3 ถ5ฮ‰ด6a…&๒ญอรมํูเ๓;"๊,s๚อ๏—gำŸ๐/NI๋F…๒—&,ค†a๎ฑวc!ล0 ณญBjSSnดCตคvขๆ~ส๚‘šG5Oาf๖"ข๙ซ0 ื` K€ณ;h้Au7๐ ๘‡B'!”H8 [ZฅŠœฉ๓ฐ+c0หใqีฮ ศt#TหTวQ่๎' [†DD8๑!ขษsปโพ–๕ะGHD๕œ$ู&V`Vจฒะ,„ Š;๖wp•vบ๗)ˆdd*Cm–6‚-็`ณ3'ง฿qๆใ|gฎฉถ่ฎ'เ |ฒฎP0ฬ๊$ฬ%˜๙kฐ•ฮ—น1ฎR€j=@ฺัDพ8๘…eธฤ”-ฎBHฑk?ƒ‰\๙พQ฿๓ัฃๅ ๙ใ็ณb†นว–‚…ร0ฬcR๋๐Ÿ#eGฯพฑpฝณgNe,์iแ๔้ญS"QYื~บ็Iจึ49ฯKฤ“้Jp…ED ืaๆฏ"ถธด๛Dิsศบ6xฯB๗< y,ฎHPVQP†-ญPธ๖๔Ds—a๓ ธ; {_qฒชก ช๋8ๅzตC$๋hJซ0K7ฉ๕p๊#˜…๋ปtYญM*C-nวแ ฟแื@x)SฮมUrH?๑>ฬโ ˜…๋5‹^ป„L5@6PnูW ๋;)ฐุตY’นณ—Hๆ๎าj"Ui`ภภ M‰:j5lP‚\e ถผกvืD>Tย๐ฦ![?๛ๅ๙?pZ๘ใว๙:XH1 รckมBŠaๆ๑ ฉuXLmโฮKBึถAต€ื๗,TตyIช8 +ฐล%˜ฅ[ˆฎลSฟfฐSืีzเ ะํGจEฑฆ™ฤTT…+็`‹+0ณ)‹iๆำmŸ๚Fาฐบใ(ผกกฺQๅ,ฬ๒8ขูOŽฝป{Eิ~iHMSิ๒ๆx…ชูคŽ,l9‹hโ„“ม,‚อNm—‰ZจLtืqx^…j €vXธ"ฬส8ยษsฐนูฝำึ&$T๛!xฯCeบ(๘|#c.OŸ!ฅธ ธใƒฯ]P ฃ…+?ฉพ๛—฿ฯœ>›ฯ—"ขึa!ล0 sG- )†a˜#คึ!1ๅŸ>๛๚ฉ}qpศž95เœ…T|pส‡จi‚j L˜ถCuญ€Ÿ†ˆรŠmqfy fแยฟŠง~ํqค†๎<o่E่ถƒเ\Bb*ฌภ—aึๆ`ฎ!šั์Eธฐผ•[?Eญ_Gเœ‚n?LQ‰ฒ ขฉ๓nผต๋Z๓่:x ˆtt๛!่งแฟ ‘จฅPp็เlW^C8๖.ขฉ`oยi}ถr'„Ÿ&Yุu๐หะํG่= WสยfงŽฟ‡p๊ƒ"Tห0ผกoB5Bค๊ฉ]ฯธ  I„—s2‘ฯU‹งฮฟœษw3งฯŽํ—u๘~๔บbT;ตฒb†นว๎ƒ…ร0ฬ๎R'tต7 IDAT๋X‡q)ฤ่Oฟ๛›?/๋๓E1% :แผง!3wFดรQ๋Y~‘*ขฎฟ‰h๎\PฺผŒาะG ๛ ๛žn;Q !$เ@UAมีฆ)wใ๏Q(๗}\Oj< ๐ฏSE”_!œ5pๅย[oฃz๑`W'(ฏผF_ผˆบ็$ผ็ก;Cฆ3w‚้MWX†-,!šฟ 3wัฬ'ฐลๅ๚บ๋'~*ขาRื•s”ใuํŸแชลธ5ืhgBxวก๛žj์#‰'Iผx‚‰ฉ-ศืbต๓Eิ:,ค†a๎ฑลa!ล0 ณป„ิ:ึaผ)•/ใk?/๋”ู{๓๘บช๓P๛ูำ4อ๓dู–-’lใl,6† ‰Œ N.%้Fํmo“@sO’ๆถ๗~UšฆIšถHฐ€<ฒe[’5ฯณt$s๖ฐพ?ถl“ข$<ฮz~?ƒฮฐืz๗็๏zW†[•ค‚zฃ|m‰Qฒ5ญu๖มQaทa๙` ัฆุ}8แqฐm๙}>I๎Eฯ_Š(ภ(]ƒ–YŽš”y๖ม›ูสHใ3X]‡ฑzŽ๒ป*ฅo"za ž…ตn#l*Š๎qEิิ0fkDO>=า†0รเุ2อภ(ฌฦ(]^P…โKF๑ฅบMถmห]f9ํJฉ็ตcข–ฝ๐\…aRถ#แ "!ฌฮƒ˜-/แDBณ’dŒ~'ชŽžW‰^ธ-ญลH8WžDXaฤ๔่‘/^Eิ฿~๋ทŽ„&๋cIDA )‰D"™#๗”BJ"‘HbSHd$x๙๛jฺ็ฅ'ื้ช๒xผฤหlฺฆ&็1|% ชปs๔(ฮHัS/œk๖,+n^rเMD/จFKอC/]ƒ–QŠš nŸœH™"r๔ ฌž์มฆ฿zฟQถฯยMn๏ฃฤ ทถc#Bƒ˜0[^ฤjADBry‰แC/ZQr•lŸ๊๖า=`8SƒุรํX}ว>`}ˆ่๔™wƒชขฅใฉŠQฐ5%็lSrv—ๆ5๏+‚ขhว”“~+ BเYฐฝฐ 59ว•…ณป{ +‘ฮDย1฿–˜ŠWeNmw@๐{>ฒqdl<6ว …”D"‘ผ9ง‘BJ"‘HbWHe'๙^_CiZฆm๏zถฉ'xKeq$ผ"2ตอ™ญwFSอึWฑzํืฯ๖9’ผฃ$ม—ŒQ|Zๆ<๔ยjิิ\WL1+ฆฆ†qฆFˆžุŽ5p5!อ…,g!jrฎ+ข„ใ.Ÿ์>„ู๚*๖`3bf}8—ผณ๘๘…U่ลซะ๓– &คกxฮ-›ลlvซู๚ŽcตžmศmUป†ฮTZฝว0[^ฤiG๑&ษ ~ป๗ฅ๐$JBš+ฆr+ฯ๎b ฎด‘ป#_h๕ผvไ‘)ฬึืขวB ๎ฅธนว๏xๅ๕ฺ๕+ช‚รุุ30ศ๗|”ก‘ั˜‹R‰D2G.#…”D"‘ฤฎสK๖๓ฟฏฏฆ$DฤถyๆT฿{ํฤ.วq‚;๎ุ‰๏ฬฮ ˜=G๊œ๑ก:H•g๓…GMHC/]ƒžปุSพd* ธฅfฦA8วAM€๎!ŠจฎรX๛ฐ[SC๎๒<ษฬไิ”\๔ผฅ่…Uฎ˜Jฬœญฬg›ฦ‹H่lฯ/ล“เJ’ู๊Bซๆ้—qF:(ณฝŽd~๘NแIด๔RŒฒตh9 Qท*J8๎†ก!„่๔๏œ๏xQw๕อj„]‘›7o\ฟชฏว wpˆ๔Q๚‡FbrLRHI$ษiŒR‰DปBช05ฟปฎšโิDย–อำงบ๘๗ืO๙๓ฎจ๊lนmk[<ฤpฌพ6เเิ)BฟขทŽYT51mฌ]P…^Tb๘ฯ.IrปŸยม™ร๊iภ<ฝ{เฮdฟQ;กำ<จi…่9‹ะ –ฃe/t—โ้>(ช&fCeEฐ›0[_ล8((ช†Qven๑Jดฌ๙จdPup,œ่”›-2้6ขW4๗=‘VวธQŸRฐT่zธเ[ฎcใ๊•x=}Cร๛C?งw`(&ว&…”D"‘ฬ‘ฟH!%‘H$ฑ+คJIฝi9…ณB๊‰ืพ฿๎็ใ๎ณ4'ObJQช.ฯ์ 5จจzษUxnBฯYˆโK=':P‡์‰>ฬ๎ฃ˜M;ฑGปp&๛])"น๘!๒$ ฅ—ขฏpำงฃx’]ฯโVN9Cญฬ์}1=‚โMFสจ‹‹ŒœE่%Wก ฯํศwฆŠmf13AไะใGฬๆํ_Œgu†[nจฅvํ*|ร#วรฟ ซo &ว(…”D"‘ฬ‘ทH!%‘H$ฑ+คๆฅ'๓•ฺๅค$0cู๊x๗hž๓ตq(ฆJ…A)ฆ.PยเMFห,Cฯ[‚^X5[้‘2[% 8+>Dt {  ณ๓ V็~œ‰œ™ัณหฦ$5) -งฃhz๑*ิ”lU”Yq๘1%Dd ซ๋แƒ‚ชนั%‹žทฃจ5%wvG>aGลิpšš7Tl S* _œ๋๏๏ด๋ฏ^ƒฯ๋apd”๘ูct๔๔ลไXฅ’H$’9๒K)ค$‰$v…ิŒพRปŒผไfL‹_๋เ'‡Z~›„๘vT๓wnซ‹‡ุฮŠฉzTํyฆฟDม›Œ–Vˆ–[‰QT–]โOq{DอŒcฦ™่C๑๘ัาKQ3หPอSŽ™tลTว>ฌฮC8ใr๙ลˆSB=ณฝ`9zัJดดขsป†'ำฃn฿(_สฌtzร๚=gv™eวข-/‚•z‘qBC(šงr+zAuปšœT<‰๗ฦห๘ทƒ=ฌืi*ฟw‰๕Mฏa๓๚ต๘ฝ^†Fว๘ฯGงญซ'&ว,…”D"‘ฬ‘ฟH!%‘H$ฑ+ค*ฒR๙าฦeไ&๙™6-ihใกรญ๐}ยaVฉwTO}ˆฉ๕ตBx‚จl”gy$$ิ@zNza z๎โูFๆธ"jฐซ๏8V็ฌพFิ„tด Œฒu่น‹Q…(š‡3;ธ‰ฐ๛ณ}/VO๖H›ฌ–บ qJFK/v+nสึขe”ขxฯ๎nh6a๕ล๊kD๑$bVใYผ5! ดูส)7ช`8กAฬฮD›_ํU~’ ŠOb๕4ถ+Š ิํพ7^ฦ}พ"๊์o๓๚ตlฝ๖>/รcใ่ั_าาั“c—BJ"‘Hๆศcค’H$’ุR•ูืฦฅไ$๚™2->าส#GฮกHŠ)ษO < ๎ฎm9๎ฮz9‹ฮ‰จHgคซ๗˜ ปฏ๑M๏W“2ั‹V`”ญCห(EMสB๑๘Fฺแqœฉa์แvฬŽ}ุฝวฑG;ไคฟ๕(กxจฉ่น‹0สฏAฯZทrmz{คซ๋ f๋ซุ#ํœi<ฏ๘’ัณb”ญรSq;JีxW@XQœ๑ฌถืˆv’b๊"ฌ(๖`k'แแฏฦ“ˆ๘_ฏรQ‚oeำ‰๋ืญๆๆM๋I๐๙ใ_ž…ืaฏœ•H*":…3ัูuณ้์กV„9ฯ4ฯฬ(มSyF้รหo5>G "Sุงˆžุ=๛aห˜œ'"<ฒงฟหx฿ทu;วโe๏DDaรชnู\Kข?ั‰ ~๘“46ŸŽษ๙BJ"‘HๆศDฅ’H$’ุR+ 2๘หk*ษJ๔11นw3O|็5โXLีฟ•ๅ$1๓?[%“<[isFษ*๐$ธ"สœม™ล๊€–W๙฿Ÿใ. O`๕Ÿ r๔ Dtล๐K1๕{ˆWuว๗ิjˆzPช้gญซYฮoผžค„ฦ''๙ษ/ŸคแTKLฮ‹R‰D2GF*…”D"‘ฤฎบช0“บk*ษH๐26๙}งุtแv rเ0ŽSทใŽญq‘Dีืœ:E่u๏Z1ฅจ(žD๔œ…x*ทbฏ:WiใXˆ๐ๆ้Wˆž|{ฐ้ยํˆง๊(šŽ^ดฃฐ-wZz1hwW>ฮ‰)ณ๓f๛^Dh่ํ –wEœP5ดŒyx+ทb”ฏw+ื !lฤฬ8V_#‘Cฟภ๊oบ _ซeฮCฯY„wู๛PำK[ล”pโฬVO‘#ฟ;โ.ลDๆ“gˆgฅ:"จจส๋ฯwี๒%v๓f’M๒เฏžๆศ‰ฆ˜œ)ค$‰dŽtG )‰D"‰]!ตถ8‹ฟXท˜๔/cแ(?xํ$/œ๎ป_ตหqœ S1ฃo๘ะrใญŠ^ผ ล›ˆขเุs๓๔"วžยlF˜‘‹"‹โKA/XŽžท-gZF Šf „ใVโ„†ฐ‡Nmู๖"2wยCห,วปdv]bบปcกˆHkเ‘ƒbv˜ฉP\”๏7สึโYtƒปิ๒ท*ฆ86ฮ๔(f๛>ข ฟ;๛š๘E„'q&ฟ/B_–"๊ยฐr้bn{ฯR“˜…x่ืฯp๐๘‰˜œ')ค$‰dŽผP )‰D"‰]!ตพ4‡?]ปˆtฟ‡ั™(฿{ํป[๛/ๆWฦ˜Bิฃjทว๔ฝแGห]Œงโ:Œข_*Š๎แเD&ฑ:ixา]๒eNƒs๑—aอ/o Zึ|๔œEจgฤ”m‚ล™รj&ฺ๐$fวธธiฅnฃ๑’ีจฉนณหโ@˜ำุƒอDžt%วบ๘ว“ฝO๙<‹7ฃ๘oSถ…ฤ์ุ‡ูพ์๘ซhแIœ‰ŸŠฉกฏ๊vถลหธ?ฅ`ฉญซ๕*๊-๋;ชW๐๑๗m%%)‰ษฉ)~๖ิณ์;z<&็K )‰D"™#”BJ"‘HbWHm,หๅOึT๐{™‰๒ฏฏ4ฒง}เโ?€!~iชขn็ถญq๑๐5V_[*„ฦข˜า๓*๑,พ=jbŠแCว]๒ี}ุmT=ุŒ m^๚Dฤ“€šZ€Qผ-ณ -{!Z Tl'2‰˜ว๎?IคแษทีX=PS๓๐,จล(]šV„โMBAAXa์มข'ถปห#ก ทŒ๒ญœGน•x*oฤ˜w5ช/47Š)aE;๖avqf7>…wku[<‹(ก๋Aเข฿—Uฬ็“ทLjR2ก้)}zฏnˆษy“BJ"‘Hๆศฅ’H$’ุRื•็q็๊…|Fฆ#|{O#ฏu^ฒ๏w๗YšŒ31Uชrฅซ^P…gมต๎’ธ”<oข+ขฆGฑzŽmy ปbf์Š่ำคx“ัา‹1สึขe–ฃe” &eƒชนb*<39เ๛ษ็ฐš‰}ัก &ga”ฏว(Y–^์V!ฉยŠ`6=2V๗œ๑žูฅ‹—UGฯ_Šw้{c$PUฮŠ)!\6†ู๒V wGพูฑพ[ฤ”Q\21ฟdA9Ÿบๅf))„ฆงy์ู็ูsเpLฮŸR‰D2G&$…”D"‘ฤฎบqAŸ]ต€TŸมะT„o๏9ฮฎกK~๑'ฆึื แ ขฒ๑J;6ฝฐฃlญป.ญี›4+ขFฐzŽaถฟŽ'4„0gฎผฤฤ—์๖/šw5z๎bิ”\T_ h†ปฤpj{คซ๋0f๋+8cฑื๘\QPา1สึนQ้%จI™(ชŽฐM์กฬถืฑบ`อ๎8่\9ปู)D๔)^ƒมฉ0าq๔ _ถใฑเ๏ีSฟs[m\4๔ฝbฤ”ข ็/ร(^‰žท5ฃิญ^13†ี{ซcVIœ‰>Dt๚สOP|)ู่ 1สฏq—&็€nธอฝgขซฏซ๛(Vฯัุ—ข ๚ำะ‹W`”\…–555฿9ฯ1qF;1๗buฦnล™ฟ$}ขXTิฤt๔ผฅx–พ=wฑ๏JQฮฝๆL๖๎รDOlว ก๘’c๎:?'ข๚๏ิฝ7BแrŠจ3,,+แ๖พ๔ิTฆffx๒…yแีฝ19ŸRHI$ษ้„R‰DปB๊–สb>U=dฏม@(ฬ{้‡{G.๏ร›รธญR_bjรญB๕จ”\า/ึ ๔ฌ๙่ล+ั๓–ขe•ป" Q}X]]5ึˆ„bkb5ี›„–ปุญ&*ฌrล”ขธ=ฆ„ภ๋ฤ๊iภj฿‡=ิŒ3=z๙—ถอ•p๙R\iXฒ -ปย]žงyยฦ™์วj฿‹ูuุํ็55ถ#1าัRr%ขKnFห(E1|œ๋/ๅDxณ}‘ฃฟUu›๊_แK๘คˆโฒ๏2:ฟคˆฯ|่คL‡gxz็ห์ุ๓ZLฮซR‰D2G~$…”D"‘ฤฎ๚เ’>^5dฏN(ฬ?ํ>JC•แ€โSL]ปM=xฑล”b๘ะ2สะ๒*ั๓—ก็-9[y"f&ฐ๛1ป`๗7bด_‘‚ๆ-ื›ˆโID/ฌม(น =)jRึ์‰f#„ƒ3าีำ€y๚e์ัNฤฬ๘•ัห—‚žฝฝ`9z2ดฌ๙ {ภqSร˜]]กึ{gฒ/vDิง๎EMอว([‹งโ:ิ@แ›wไsœ๐8ๆ้=˜ํ{มŠp%๖–ŠWp็]_฿&%จr‰ๅ๚๏`^q!Ÿ๙ะ๛ษL 0Ž๐ฬ‹{xๆลWbrnฅ’H$’9๒)ค$‰$v…ิmหJนmy‰†Nh†ภ๑+ห‡qEU๊ž์ๆ{ใๅ|šS๕บบ@๑$ ฅกๅ,B/ฌBฯญDIธŒLc๕Ÿภ๊9๊๖:}E๖ˆzGใ๗Pา0JVกผaB ์(86๖p+V๏1ฬฆ]ุใ=ˆ๐\†\G๑%ฃe”ข็-uc•ตผ ฎˆ ปช๛ˆป‰“—•Iิ4yi฿!yz{Lฦ@ )‰D"y3RHI$ ฑ+ค>ทบ‚›* ๐jใS|ํนCtOLวjvi มง?ณ%.๖Y1Uช‚ชป$™๓๐.‚^Tใส UC˜๗!ฝทhำ.ฌžฃ—ฌRฌขฆๆฃ,ว[นีญ–JHCQuPUDt {จซง{่4VืAœ๐ไ๙๗/RToZ ฯย๋0ึขx“Xู&bzซ๗ัฆX ˆศค ศsจ๚่…Ux—ฝ-ฃ Ÿ#Eu๛€M c๕6m~1=๚Žล”O…์้ม๏2๗ญ@ฮฑx™๊/~๕›ฅaว ทวโ๑gฆ๘“O~„์,ขฆษžGx๘ษgb2RHI$ษ)R‰DปB๊Oื.bห‚|ผšF๛Xˆเs‡่›Œี†ฦ7ถฌผฏ"+%hจj[<œ{ใถฅVM[๔,ปyฃQถล—Œข๊ฎ˜qwc‹žี}DŠจ?œึณ—ฒฆฃg–ฃ็/ร˜w5jjž+ฆPˆบฯอ๎#X=Gฑ{Ž๕{vปS@ำQ“s๐.‚g๑*Šๆวย O`ถ=4fว)ขฮ7b$๔œ Œ…›ะ๓—ก&eบs +‚3ูีuˆhำ‹ ๐–๛Kลซˆฒmปดฝง/๘๛z๛๔L์.MKMแO?y9ู˜–ลk‡๒เฏžŽอ˜H!%‘H$oฮค’H$’ุR_ธz17”็ahmฃ“๏‡œŠ‡$ฏม76ฏ`Af –ใทซฝ/xcyA[|ฌใเ˜๐ณโUDฝx๐``๕’%A]ำฟุูวฟ๘!&งb๗‘šœฤŸ}๊ฃๆๆ`ูฏ9ฦO26o๑RHI$ษ›BJ"‘Hˆ]!UwM%›ๆๅah*งG&๙๊ŽƒŒLGb6ฉ>๗lฎก<#ำvฺุว?ฝx์>Ks‚;ทmm‹‡sั<๕|mค๑น{ญฦ™ว–่@  ็,Bหฉ@ฯšš^โŠ)วBDฆ\15าy๚eฬ๖ฝ8}๎๛’ณ1ๆoภณ -P่6ใFAุQœ‰^ยŽy๚eDtๆ—I~OfชเYxžล›ั2ๆก๚SA3fใยํฤj฿‹ูwEU฿๔๖xQ‚ม€ึ๋>ม›๋ึT/Mี5ฎ~ํว?cl2vซ๕’๘ยง?FQ^.–mณ๏่1๎์ื19)ค$‰dŽŸ})ค$‰$v…ิ\ฟ„๓rัU•–แ ๎~€๑ฐณqศH๐๒ตj(KOฦดžo้ๅ{Ž#ฦm•zG๕ิ๏V™c๕ท กQ)‘W่K{ะา‹ัrฃ็-Aห(CK+D๑ฅ€c#"“83ใ8ฃ˜]‡Q4ฝจ-ฃล—‚ขhณ"ช่๑฿=๕":‡;็]‚Hy็'#Œ IDAT๐,น O๙ดดboจฺo-ดฺ_ว์>‚š˜ŽBLTL }%Pทณ-^ๆ้ŒˆาT๊PI๘๛ถฒถz9†ฎำ30ศ๗๘รcใ1;พŸ/qJ๒๓ฐl›ƒว๙ัฯ“c‘BJ"‘Hๆ๘ฝ—BJ"‘HbWHอตKูPšƒฎช4 Mpืณ๛ EcทJ#'ษO๐†jJI˜ถอ๖ๆ^๕•ฦณO1uํ6!t)ฆ.h๖ฃขe”ข็/E/ฌA  ฆไบาC8+โV;)šป3œช!,ท"สly™่้=8ฝˆฐ์uฑQ3๐.?z๑ชู 5ฟ๘L๙“˜'ŸฟฯlŒ'๐นปฟ^‡ฃQI=๓฿nปy ืฌฌยc๔ ๑apd4fว่๕x๘โํงค0วq8t$๙ศใ19)ค$‰dŽ”L )‰D"‰]!๕ฅหธฆ$MU898มWžฯŒปKผ๒“๘๊๕U”’ˆุ6ฟ9ีอ๗_;๙ฆืSฯvK0ฮฯฑ๚ฺ€ƒSงฝ๎Ÿ’wˆf ฅ— Va”ฎEหœ‡๊KU็l)!แIฬŽ}DO= gz๔๗4?—\”Peฮร[yzQ+ ภ}ยŠร฿Osq็]_฿&%จ๒fIกฏgรU+๐z ๚‡๙มCา78ณc5t/n๛eE8Žร‘M๐แ_ฤไXค’H$’7#…”D"‘ปB๊ฎMหY[”…ฆ*4Œ๓ๅg๖ตc๗Aน(5‘ฟปฎŠขิDย–อS'ป๘แSฟ๓๕Ž ]U”เณŸ|o<œงRL]„Dศ“€Qrฦ‚Z๔ลจ‰้๎าฐ3މwณc/V๛^์‰>ฤฬธœผห€^ฐ oๅอ๗้๙K‚j ฐ-žฦ๛Dิnผ‰kVโ๓x่แ฿9=ƒ1;fUU๘หฯ|Šyล…Gp๔T3?๘้ฃ19)ค$‰dŽ&…”D"‘ฤฎ ^_อสยLT กŒฟอพ˜ŽรŒdพRปœผไfL‹วŽw๐ใƒ-็ผ*h๊v-วรy;V_[:+ฆn—W๑y&>†-k>zมr๗_๎b‹@ fฦฑzŽbท!ฆFฮพNM+Dั wวC!ๆ fkX]‡0; fฦถ)—๑],โXDฉŽ*ชฒ๑|฿sำฦkุผ~-~ฏ—กั1๓gำึำ๓๐ลmŸ`ai Acs+฿ษรฑy๏ัดM฿๛/๏”ดD"‘ผแ(…”D"‘ฤฎ๚ฺ 5ฌ(ศ@Ž๔๒ๅg๖วt*2S๙Rํ2r“L›6ด๑ำรญo็ฃv9ŽqวึธHฅ˜:„ว๐ฃฆข็-ล(ชAหซD๑&ก  ขSXฝวฐบb๕มnGXดŒRิ”<<๓ืฃๅ.FKษMwwไ3รsณ๕UฌžฃXGpฆ†])%sซ ƒQ฿๊{ทlXวึ Wใ๗นB๊ŸŠ–Žฎ˜ž/|๚ใTฬsW)ž<ฦw๎(ฆŽ_UUV-ซคfษโM+*+vส ["‘HŸI!%‘H$๐ญ]Gลฎึ>l'ถ๎‰๗lYAu^:‡{Gธู๋1‡ส์ฺ๋ฅไ$๙™2->าส#GษGฦ™˜Z_+„'ˆสFyUฯ&:†5%-งฃจ=JB( ˜aฌ“ุ}ว1;`๗Ÿrwุ๛ญงI ={ZFฦผkะาKPSrฦ็Žw›žทฝŽืˆีsิS’ทOœŠจฯ)Xj๋jฝŠzหŒ๋ืญๆๆM๋I๐๙ใ_&#nแฑcไajชR๗์ถอ‡โแ|–bสํฅ$gฃg/@/ชA/จBMฮvETt{ด{ฐ‰hหKX]‡ฯkนžท=o ฦ‚จ iจ‰™nล”mแL แL cuฤ8…ีsT6>ซ8ด+ŠYจ{๑๑x๖็ฟ,บq…ใฦี+y฿๕I๔๛็ว~อ‰ำm1=?๚ษจœ?EQhj๏ G\๑วผta9kซ—SRGjr2CG6ฉชฒS^่‰D๒†|M )‰D"!„ˆุ#ำNMฐฃน‡ฝ]CWqk๋J–ๅคแ๛ป‡๎ˆm฿R—ฮฐ„ฌD““๛ด๐ฤ‰ฮ ๗ผ+ธฯาœเฮm[โแผžS๗ข๎]นuจ:jb:ZF)F้๔ขจษ9(ช†0ร8“}Xง0[_ม๊:„ˆNฟๅฏะ‹j0 k0ๆo@1(T๋Šฉะ๖X7V็A์กฌco๋;โ ‡vEฑ‚บ๗ฦำฐ/คˆ:ร5+ซนu๓&’›˜เ'ฟ|ŠcM-ฑ=OŸ๘0KฬGQZ::๙็=ภ•๚ฒdA9ซ–UR^\D % Cื0-‹‰ะิฆฌ๔ด๒‚—H$’sH!%‘H$ภŒi ฆต†ง#ewk+ฆEแทฎค2;€์ํไkฯŽ้8ฌ*ศ ๎š%d&z›hฟ9ี}แŸใNL]ปM=๘ฎSŠŠโKAK+ฤ([‡Qบ55E5v'4ˆ=ุŒู๚ f^Dd๒ฅQถฃไ*Œาี๎Ž|žWL9๖xŸ+คบbตbฬฑ0‰Sต- ่aฝNSฉC%๕B~๖š๊e|x๋๕$%$2>9ษฟzŠฃ'›czพ๘ฃd๙ขจชJkg7๕?zหถฏจc\4ฏ”ซ–/กผคˆด”d<†(XถลDhŠถฎ4žt็mุ)/|‰D"yC๚&…”D"‘ภฎึ>Q‘™Jš฿ƒกฉfh*ยฑ1^h้ๅP๏ศuฬบช๒ถฎdqv*ถ#xตsoผp$ฆใฐฆ(‹ฟธz1 ^ฦยQ~๘๚)žk้ฝx_(ฤทฃš7ธs[ํX<œ็๏V1ฅxPSr1สึโYxjJ.ŠๆA8&bf {่4ๆ้=˜ญฏโL^ุ/ื <๓7`ฏB/ฌrฅ๋>Pu„cโŒ๗b๗5bฮVLู#เX๑}ร•"๊‚‹จ3ฌZVษm7o!91‘‰PˆŸ>๑5žŒ้yปใถPตx!ชชาึีรท๏}จi^ว6ฏธซk–3ฟค˜@J2^ข(X–อไิฝ์o8ฮ๋Gฐ›ใžปwสŒK"‘HรI!%‘H$p๗ณDfขีE™ฬOO!ี๏มฃ*8ย–อะt˜cc<ิร๑+ร]xuธq%‹ฒRฐมžŽAagl ฉซKฒ๙๓u‹I๗{›‰๒ฝืNฒซต๏ข~งpทU๊ีSbjฌพ6เเิ)Bฟhล—(…Aั ๐๘๑,„w๙-จIYฎˆ6":…=ิŠูผณ๕œะEฌtTTิ„4Œฒu่…ี่y•๎2>อB ฌœษAฌžฃ˜๛ฑ๛O\ในRqŠUŸ^ท;Oรพ"๊ 5•|์ฝ[IIJbb*ฤ#Omg฿ัใ1=Ÿ๙๐-ิT.BำT:บ{๙—๛สL๘๒V–ไณถf JKศคฮŠ(หฒMOำ?ศ# ์;zl5—R‰D๒ฆJ )‰D"ปž= ฆM›ฒด$ึgQš–DŠฯƒGSqAุฒ้อpดo”อฝœบผ ‹=:฿ุฒ‚…™)XŽเฅถ~qwCLวacY.Ÿ_SAš฿รศL”๏พาศหํ—ฆษผSฑ”ฝ((ž$< 6โญ€#J๗ ยŠเŒv9ฑณy7Nh๐า–๎E ธีRyKะฒ $คกhย6‘bjณ๋Vว~ฌ†๘่/5+ขTิ๚@ฮธจF<รw}}›P” สฅฉJ\^ฑ€OrฉIษ„ฆงx๔้ผv8ถnเ๛Xนด]ำ่่ํๅ;๗?ฤิ๔ฬe9–‚œlฎ^QEลผ2าx Šข`6S33๔ r่๘I^=t„H๔ทซธค’H$’9r')ค$‰ไœ:CฤฒฉศLeEA%iI${ Œ7TL๕Mฮpธw„g›บi ]–cN๑ณe๓3Rฐ‡ญ฿c๛มใบ๒<๎\ฝ€ฯรศt„o๏iไตฮมKz ยa•เ๖ฯnฉ‡sฌพ6 „ขj_Œ‰ฤล—ŒQบ๏า›ัาKQผ‰ จฎ๐ i|†่ษ็p&ภq€KŸ็($ดฌ๙…UhY ั2Kฯ๎ศ'ฬ0bfgzซc?fว>ฌ๎ฃ—ๅ8/:RD]2u†% ส๙ิ-7HI!4=อcฯ>ฯžฑ[๐n}W-_‚ฎ้t๖๕๑?ฬDh๊’CNfืฌจbั22ำx=TEลvlฆgยt๗ะpช™—๗"‰ฮ๙RHI$ษ9“R‰D๒f!u†จํP™`yneiI$y tUม‚ำSz†yฆฉ‡ฎ๑K› ง๙=|ms ๅ้)˜ถรฮึ>๙ฅc1‡๐ูU H๕ ME๘๖žใ—ญฉผ#hW%๘์g7฿ืภX}m้ฌ˜บJ<>ล—‚QXQqzฮ"wIœช!ž zข'ถใL #ฬธ๒5! -)zn%z๖ิิ|ิฤ ะ Dt'4ˆ˜วl}v)฿ษwวษว"๊s_น็VGฅR‹จ3,*/ใำทพ‡ดิTฆfฆ๙ีŽ]์{ ฆ็๔“๏ฟ‰ีUห0t๎พ๛“‡›˜ผ$฿‘ฮบšๅT.˜GfZŸื‹ฆjุถอt8L๏ภ GN6๑ฺก&ง~ …”D"‘ฬ‘฿I!%‘H$ฟ[HEภ‚ฌj๒า)$‘ไัั5q˜Šฺ๔…ฆู฿5ฬณอ=๔L\š%8™ ^พถน†าดdLๆน–^eOcLวแ=‹ น}ล|RผƒSaฟ—Žqฐ็๒6“—b๊2'*พd๔ๅxๆฏGหY„š˜ข๛>QำฃD›važ~{ฌ 13ยนโๆTMHs{Kๅ/Cฯ]Œ’†š๎VLEงq&๚p&๚1[_ม๊>Œ=ฺป'c[Q”`ผ‰จ;๎พงVuDPQ•—๓8–•p๛฿Gzj*ำแž|แEžeoLฯํว{#๋jช0tžAพ๗ภฯปธKๆ3ำฌฉ^ฦาๅdgฆใ๗๚ะ4หถ™ ‡แศษ&^=t๔ผๅ˜R‰D2Gž'…”D"‘œ‡šES*ฒRฉฮKง 5มSชŠๅฆขS์ํโน–^๚&/n‹œ$?มช) $aฺ6ฯ6๕๐WOฤtnญ,ๆ“ีๅ${uBa๏‹ ้ฝ"Žอด#œm;๎ุc๕๋k…๐Qน,ุŠ'=)Fูี่น‹Q“ณQ<‰ณ"jณ}fหKุรญ83c`_๙;ืฉ)น่U่๙Kั ชP}I($P5Dtgข{ฐ™hำ.์กำ๎ฒรXมฑ๏›Qm๑๔qฅˆจ3”—๑™ฝŸŒ@€™p˜งwฟฬ๖—^้9พํๆ-\ณฒ aะ30ฤ๗|„ม‘‹๓ปHNfŠๅTฮŸG^v&~ŸMUฑm‡™H„ม‘QN5ณgaF'&าgK!%‘H$sไ{RHI$ษ๙ ฉ3hชBev€ชt๒S$:บช` A(jั16ลพ๎!ถ7๕0<}qvสONเซืWQH"bๆT7฿-ถ—|xi)ซ*#ษฃำšแŸv7pฌŠ+ดุๅ8NPŠฉ‹”˜hดผJŒฒตฎˆ ขz“ยALb๕4`žƒ5ุŒ3ูถ;“ฉ(๎#P€^XใVLี ~ท)ปข!ฌ0ฮx/V๗"วƒ˜ฦ™พrวง"๊ฮปพYฐ๋ฏu†าย|วGn%3-ภL$ย๖—^ๅ้]/ว๔\่ฦู๋pี ผƒพมa~๐ะฃ๔ ^ุk"ม๏cช–-œOnVฦฌˆาp„C$ฅx„-ญผดรฃo๏7I )‰D"™#5’BJ"‘Hบ:ƒกฉ,ฮNeyŽ[1•`hจŠ‚ๅBQ“ฮฑ)^๏โ้S„"๖มน(5‘ฟปฎŠขิDย–อS'ป๘แS1‡U•๑‘ฅฅ$ฎ๚ึฎฃœฟR7ลิฝจฏ7ŽžSQถ-o‰ฐ— €˜ว๊kฤj฿‹ีgผa†cw2Uอ‘/ตฝ`z2Œโ•(†o6;SŽ…3ฺ…yzั–ก!œ้1ฎ˜ๆ็q*ข>ฅ`ฉะ๕ pE๖Z+ฮฯๅŽ>@VzแH”็^y_?ฟ;ฆ็ึอ›ุธf%>‡กแŸำำa6ป๐yฝฌซYNueyY™$๘}่šๆ๎ฌu+ขNดด๑๊ก#๔ผณ~†RHI$ษ›‘BJ"‘Hx๛B ฦ็ฆํฐถ8‹št๒“๐:šฆ#EL:ฦงxน}€ํM=L›fiQiZwmZNaJ"3–อฏ;๙ฏM1‡?ช)็•ล๘ ษiพน๓(อรW๚a๏Šชฮถถฦลƒ๙Xต„ะƒLL) ZFzQ zRทว’? a๗Ÿฤ์:ˆ{{ด™z๗Lฆชกx“ัา‹ฦ็หั‹V h@€pVgข—hใvฬ๖ฝn#๔่ิๅkฺ๎ฐKQœmRD]™ไd๓ว๛ 9้„ฃQvพบ_๎ˆm๒พ๋7rบซ๐y< ๒ร‡AW_;๚LฏวรUห—ฐr้b๒ณณHL๐ฃk:B8„#Q†วฦ9ีฺฮ+ำูAฦ!…”D"‘ฬ‘J!%‘H$๏LHa2bโัTฎ.ษฆ*/œD~CGULa"bา>bwk;[๛˜1ํw๔}๓า“นkำr๒“˜ฑl?ฮZb:Vฮ็‹‹๑๋ำ|ใ…รดކbโุม}–ๆฅ˜:OT]บ–ฟิWXใŠ(E่ ึ`3V๗aฌ๎ฃุรงแษw๏d**ช?-{!z๔ฅhน‹Qt/ยŠ "!œฑnขง^ภ๊:„3ูiซฤv)J4จ{)ฎจทƒฉ…/ฦย๑ๆeer็ว?Dnf‘จษ๎ฝ๘ล3ฯลt ณi7\ฝŸืรเศ๙ณวh๏้}[Ÿฅkkช—Qฝธ‚ข’ ่บ[1ฃŒŽOธ"๊ภ‘ทฟ )ค$‰dŽH )‰D"น0B๊ “ŸกqMq6ห๓าษJ๔แำ54ขŽ`2ฅyx’=์h๎ลrฎ` 2S๘๒ฦๅไ%๛™1-~~ฌŽ้8qีBSQˆOื่Ÿโ๋/ฆc,ถ*bม}ŠAp๛งทดฝฏ›ฑ๚ฺ€ƒSงฝ•ิ๓z“f &gฃgW VนKี3P aGฑ‡Nc๕6`uย๊?OฤัHAMส@ฯ_Ž^Tž]š^|NLEฆpฆ†pฦบ1OฟŒี{{ผ็โ๖ัŠSu็7พp&Eฆr็๖@vF:Ÿ๛๘‡ษฯฮ$jšผด<ต=ฆcฑ๕ฺซูฒa~ฏ—กั1๋‘_าฺี–>CำTV/_JueEyน$'& kB@ิ4Ÿ ฉฝƒื7ะ~qvน”BJ"‘Hๆศ|ค’H$’ +คฮ01I๑ฌ)ฮbYNY‰>ผบ†XŽรX8Jห๐$/w ๐BK/–๓ึaQV*ปqนI~ฆM‹GŽถ๑ะ‘ึ˜Žร็ืTฐua^Mฃ},ฤืž?Lฯฤtฬรซk|๓ฦ•ฟ(+ฅPีฑw๛๕s^bJำQาัฒสั ช1JVกฆไกจยฑqF;ฐšฐ:๖avxwWDjr6FษjŒาีhe(I™oS“ุฃ]8ฃ˜๛ฐ๛O`๕€p.ฤฉˆฒl;ะี[๗/๗>X6ฃฉฑviไ!?; ำฒxๅเa๚๕31“อ๋ืrำตืเ๗๙ใG?-็)EaๅาลฌZถ„โผ’1t˜Q4ทw๒๚แNตถ_ิqH!%‘H$sงฅ’H$’‹#คฮ01 ๘<ฌ-ฮbiNY‰^ผบๆ&ฤถร๘lลิฮำ}์n๋็|๏หKrอตKษM๒ŠZรŠ‚˜วnล8…ี{ {ฐg.3r8ฌ(ับxQ‘จนMืด๚๖žิ๏Sฆgbฏq~ %™?๛ิG)ศษฦด,^?|”~๕tLวๅบuW๑žMH๐๙็พ_ม๗ฏZVYขk:ฝ}๋br*๖ช3“๙๓O”ข\,b฿ัใุฏc:>ืฎ^ษ๛ฏ฿Hข฿ฯ่๘8๗?ไ๏•HKฮ็ชๅK˜WT@jr†n`Z&ใ“!ฺป{ypGN^ฺM@ค’H$’9า)ค$‰ไาฉ3LFLr“\]œอยฬา^ผgฤ”ๅŠฉฦ1vž๎ใ๕ฎ฿PY“Ÿฮ_ญ_BVขษˆษ}Z๘๕‰ฮ˜Žร_ญ_ยฦฒ\ Mฅed‚ฟ{๖ cแhฬ#ี็แžอ5”gค`ฺป[๛๘/C8Œ+ชR๗์g7วลCฬฮ๏” ฎ j™ๅท+บ!Dx{คซํ5ขMปpBƒ๒t>จ:8z2Œาี่ลซฮ‰)UsลTh{จณ}Ÿ+ฆF฿ฐ+กฬq›‹s%%จBษงn}ซ—/Aืtบ๚๚๙ื?ฬD(scJ๔๛๙๓OŒ’<,ๆภฑF๎๙ฏb:Nืฌฌๆ[6‘่O`lb‚?$ว›฿/qษ‚rV.]Lyq”ไณQฆe3 ัึหc8ึxYทR‰D๒fค’H$.ญ:C(bRœ–ศช‚Lfฆ’ๆ๗`จฎ˜Šฺ6CำŽ๗ฑซต}รozส‚ ๒š%d&z™ˆ˜ืพ&~sช;ฆใ๐7–ฒก,]Uišเ๎ํ˜Œ˜17Žtฟ—ฏmฎa^z2ฆํ๐ย้^๊_>~ฮฺUE ฦ‹˜ย6kEt*huo4๗=๙<ฮX—ผ๑ผญฬMEั Œา5h๙K1 ชPS๓Q /แJฟฉa์แvข-/b๗5bvผก๚lVLลฑˆบใ๎{j5D=(Ug'kช–a่:O~ฦ่D์5ิ๗y=ลํŸ ค วq8x$๕ศใ1ฏตีห๘ะึ๋IJHd|r’Ÿ๒)N5Ÿ๛‚าbึV/ฃผคˆด”d<†ข(˜–ลdhŠ๖ž^;มพฃว.kฆR‰D2GZ#…”D"‘\!u†Pฤค,=‰•™,ฬL!เ๓เัTfh*ยฑ1v4๗pดo๔์๛Vf๒ลk*ษH๐2Ž๒{›ุัำq๘าฦe\S’ฆ*œšเหฯ`ฦดbn™‰>พvC5ฅiษ˜ถอŽ–^พณง๑Mฏ‹715yงjญแž *ๅ]็fp Š/ฯยZดŒ2๔ลณbสŽ…ฐขgwไ‹žzซฏัํ/็"JuDPQ•7{๏ฌซฉยะuz๙?cxl<ๆฦh่:_๖ สŠ p‡#'š๘แรฟˆ้ธญZVษm7o!91‘‰PˆŸxšรง˜WTภบšๅฬ/)&-5ฏวƒข(X–ลไิ]ผ~ธ วqœหผ#…”D"‘ฬ‘ฮH!%‘H$—WHa*jQš–ศบโlสา’I๕ปbJมŒi38ฆก”ํอ=4Œsuq6~๕bาฦfข|๏ต“์jํ‹ํ8lZฮฺข,4Uแฤเ8_๚อ~ขถsใศI๒ผกš’@ฆm๓lS฿}๕ฤ๏|ฝ‡qœบwl‹‡•ฑ๚๕ตBx๊Qฉ’wŸwšษ)จIูx—„šš‡–ต5%วํ/e[8‘ฮไฮx฿x๔ไ3๕N฿ษ๚”?๙XลผโB„#8zช™๔ั˜Ž฿Š%‹๘่{o$%1‰‰ฉฯ๏yฏ๚U: IDATิ”d*สJHคโ;+ขlB3ำ๔๔์w|ี™ฐŸ™u๏•ฎzต%Yฝหใ ๔†B ‰๗๛๖๐ )ฺ…dูvฟษฆgC ฝwlllใnฒeษV๏ฝ]้๖2๓!ษ@ฬn7}ž?m™๓ž๗ฬ™็พ็๖Wื๒QU5มะิ๙AC)@ ๘œว!ค`jฉI|ม0Yฑvๆฆล‘mรn6b”%ผก0}./Uร z|\S”Nดลศฐ7ภo๖c{Kฏฆ๓๐“ๅeฬ›N‚ฃฝ#๐ฝ(žJฑG๐ำeค;l๘รaซ๋ไw{‘nSฅโยS‹ืฉชพ™tq:UกG†ฑ่2tQษศŽ4d[<’1ยI8Xฉx†+e{ย%ข๎{ "Cี๋+€;ึ฿^ฟv%‹ๆฬฤd4ะ?ภ๏Ÿ}‰!MฦฝฎศIŸŽชชิ44๑›ง_ะtห๒sน๕สK‰ฒวซŸ"ฬๆQแpทืKW_?‡ีณ๋@ภิ[{P)@ 8!ค€ฉ%ค& „รไว;(OŽ!=ฺ†dภ0!ฆ|มฎ@‡ลˆI'3่ ๐ซ]5์nำ๖ั+ห™‡ ้ๆ๗๖k2Žดจ~ฒผœ้QV|ก0๏ึu๐‡๊พฬ!„˜|ต;ƒ]l:†œๅN]\Fฅฮ1ญRŽL"๊opํ๊ๅ,ž7“ั@ฯภ x๎eบ๛4๗๏ผ…ผฬ TTj›๙๕Sฯk:Ÿ‹ๆฬไ†KWb2šUU'D”‚ว็ฅณง๊บFvฌยใ๕Mู8„‚ฯynBJ ฆฆ:๑ซชไลEQ–MFŒ ปั€~BLษ Ixƒ!~ฟ๗8๏j|Q๓‡VอdfJ,Pี3ฬ6hSHฅ;lxY)iB๊ญcํืพ/ฟลธข๒DHงTl]ทถๅBธ‡*WHช~=2Qโฎ๔QpชRจRgŠฌŒ๚๖[BD}AฎZน”ฅ ๆ`6้โฯฝBgoŸ&๛แ;n&oFuอญ๒‰g5GBl สK˜SRHBl ’$qEมๅ๑า;0Hีฑ:๖ชึฤŽˆBH มษ!%Lm!uโ†DN\$ณRbH‹ฒi2 “วะUUฅsิรถๆ^o่ขkิฃษ<|๕,ส’c8ิ=ฤ7ะd™ั6\VFjdP˜7jx|รWw ˜ฉ\๊PPึ 1๕UJ๘ I’*๋ทถ\Haฏซจp่}๚๕:™ฏล[ถk./BH มษ!%hKHtzX:#‰›K31๊uจชzb _XQqCดปุ฿9ศปu8})“$Iหฺู%8P€}ใๆCšOนq‘<ฐค”dปo0ฤKG[yๆPำi9ถชเ หT*ฒฑr๋บฅ็”ฌ‘สฅชชV ๋๎D๐Y.PpฯWœ5ษฺลฑ๚’…XL&†G๘๓‹ฏำกอ)ะ๗|ฅy9HฒDS[> กpxสถ7ยlๆขูe”ๅ็’‹ลlF'ฏ๙~F]nข์6ฬ&^Ÿw?ษ๛;๖h./BH ม็< !%ฺR=c^ๆO‹็ๆฒLlF=ž@ˆAฏŸh‹‰ƒY‚ะDลT๛ˆ›=ํlจ๋ฤMู˜๔ฒฬ#kgS˜EX…ฝm<ผฅJ“ใ)?>Š.)!ษfม ๑โ‘ž;|Zฯ!ฤิฬ,ข๎}๐กuช$Uศœ๐W/Zภฺลc1›q๒ุKฏำุึกษ>บ็ฦk(+ศE–eZ:บ๘ๅฯเง\;อ&๓หŠ™U”ORBV‹ฝNช*๘๚‡‡9ุB{O/W,_L\ดฏ฿ฯฦํปy๏ร]šห‹R@p2BH ฺR}. งวsCI==./Ol$+ฦNyr ษv ƒY–†ฦAฺF์h้esc7žเิSfฝŽ_ฌ™M~|$aEeW[?ผ๕ฐ&วSa‚ƒXRLขี‚;โ๙รอผxไฬธƒ PL•ซช\‰ฬ’ ๎FฅฐM’”๕Ž๕[]hกŸ)5ษŠ…๓ธlู""ฬ†FFx•7ฉoiำd_uUฬ,ฬGง“i๋์ๆ—O>‹ื็Ÿ2ํ3 ฬ/+ฆผ0ŸดคฌŸQCN'ว›[ู} Š๖๎^าS“๙ฦ ืใภ็ฐiื^1eO ฮ„ด'ค>.JOเบขt,=c^ูv˜บQฒb์ฌฮIฅ,9šซ๙3bjิคyhŒญ}ln์ฦš:ำ8ฌF=?_=‹ธHBŠสŽ–^๕รjMŽง’คh’bmfฦ!žฉjไีฃg๖ๅVQi•%ฉbใซฟฎู‘สEKUีXqAˆ)…m’จpฌ฿qมฝฬ~๋G_ญศTž)5ษา๙sธ|๙bฌ CN'Oพ๚ว›Z4ูgw^{ณ‹ ั๋tดw๗๐ซ'Ÿรๅ9๗]่๕:ๆ—•PšŸCzJ2ถˆtบ๑ฉy`€a็(uอญ์=T™้’ำ’น็ฦkIˆฦ๐ม๎ys๓6อๅE)@ 8!คํ ฉAŸE \]˜ŽEฏฃkฬร/ถฆq่“‡๒ใฃX‘•Lir ๑V3fฝY‚ ข2๊ P?0สž๖~67v +็<ฆ(ณ‡Wอ"+6’ขฐญน‡฿~T“ใฉ,9†ฝจˆ›™1ง6๒Fm๛ูqฆ˜ชDฆ์ผ ๎Q๗๘แฅฒขVHฒtV„ใ%sgqีส%X- Ž๒ิซoQุฌษพปชห˜WVŒ^งงฃท—_?๕<ฮ1ื9k,หฬ--bVQ>ำ’“ฐ[#ะ๋๔€J dศ9JCK>๚นUi)‰๑{ำu$ฦลเ ุถw?ฏฝฟEsyBJ NF)@ ~ดaฟ:น[๖Xœ‘ศๅำฐ่utŒบ๙๙–รด ŸาQœอ๒ฌ$Jฃ‰ท™1้tHร #พƒclo้eksaๅ}'ฤD˜xhๅL2c์ร [šบฉYฃษ๑4+%–ฟ[THผีฬจ?ศใ๛x็๘ู]FQiึo๚ฦ๊ื.„kxคr๑:UีW ŸูJšณ“šรทnนž”„8ม ;๗W๑ย;5—!คเd„เ๗๖ซ:Y;Bสฒ$3‰ตนฉ˜t:ZG\ำUtํuBfฅฦฒ:;…ผ๘(b,&Lz๙„˜๒๘ฉS{๛ฯjLษv ?[QNบร†?fC]ฟ{L“ใi^Z?ธธุ#พ๚ธžM ]็บY”˜ช\\!ฉ๚๕ศDM๙ฦ*ดJRจยฑรว/ด{๏}Tdจz}pNwOœ[Zฤ —ฎยnตโt๑์๏QuฌN“}zฺ•\2g&&ฃžA~๗์K๔ ž•s็f3งคำาpDฺ0่ €J0bิๅฆฅฃ‹}Gj8T{ 36ฺมทoฝ”„x‚กปV๑[4—!คเd„เ‡๏ํS๕ฒฌ™๖บ!–อHbuN † !Uฑ้ฝ.๏>ฦE้ ,อL"7>’hณ ฃNF’ภR๔๘ฉํa[su œ•˜าขฌtyำขฌ๘Ba9ม?ึๆ แย้๑ฟฐ€˜#ฟ๛่8[›zฆJ๓ถ!K๋7ฎ[u๏ิ6Rนิก ฌŸฒbJˆจ ฮฑˆšdVQ7]พšHซQท‹็ภมm ๑ซW-cษู˜Fz†๘ร๓/ำี{f`(ศสdniYำงแˆดa4‰`(ฤ˜Ms{'‡jณฟบ†/๛๊แˆด๓o"51`(ฤGUGx๚w5—!คเd„เผปO5๊ด#คผม0หณ’X‘•ŒAงฃexŒŸพฯ—ฺ[g&qqz๙๑Q8,FŒ:U8ฬ วOM๏[šz8ะufaฯˆถ๑เฒRา"ญxCaชm็ฯ๛๋59že$๒๙D[Œ {fฯ1ถท๔N-ข๒DHงTl]ทถๅ|ฟพOˆ)Iณฉั๙ฎˆZWQแ0๕’ฤฆRปส ๒ธๅŠตDฺlŒนผ๐ฮF๖ัๆvWฌXย๒s1›Œ๔ ๓ง^กฝ๛ฬฒฆงqัฌฒ eวd4 IกP˜Qท›๖๎๖ฉแใร_}ƒŠH›•๏}fา’ …C||๘(Oฝ๖ถๆ๒"„”@ |ฮปˆR@ =!ๅ…Y‘ยาฬ$ :™ฆก1~๒†ฝฏ|ฬe3’X’™DVฌ‡ล„Q–PT๐…ย x|ิ๔9ูPืIM฿ศ™yฑ‰ฑ๓ฃeฅคุ#๐CผVฦ“ดนจ๐’ฬ$พ=?‡ลศ7ภ๎ฎeื9Z›๋oบ‘ KLeจชZฌ;7U9 ฮ UyกcืUT8๔>zฬ”ฌV+อหแึซ.%สfวๅq๓โป›๘จชZ“}}ูาEฌผx>“‰ก๋ลWiํ์>ญ็ศHKaแฬRr2ฆ…ษhœQ!\ฝ}|TUอพ๊ยงธ‹ซ5ยยwฬ๔ไdBแ0๛ซkxโ•75—!คเd„เ๏฿๙X5้ušio0ฌฐ2;…ล™‰่e™†มQ~ผ๑ฃเ)W/K,ฮLbyV2™ั6"อ“S*`˜>ท๊ža66tqผ๔๎ฺ”ษKJIถ[๐Cผ\ส3UMšOหณ’นw^.ณ‘!ŸGwีž๕5นพด+Qy"ค3ฎ฿บn้ศ๙~ฝŸu1ฅเTฅPฅŒ\้Xฟ๕ผ๏฿O3ีEิ$ลนY~ีืˆฒqy<ผฒa3ปึdŸฏนd!k.น‹ูฤภ๐ฝMmงg—ฯดคD.šUFnf:ฑัQ˜F@"ใ๒z่๊ํ็Pอq๖:B <-็ด˜M|Ž[˜žšL8ฌpฐๆฝ๔บๆ๒"„”@ œŒR@ฏท?V-ํฉฐชฒ2+™E‰่e‰บQxw tZŽoา๋X™ฬล้‰d8ฌุอF ฒ„ช‚7ฆืๅฅช{ˆ๕]4 –s&8๘‡ลล$ฺ,ธƒ!^8ฬ GZ49žVๅคpฯœ\ขฬ=~*wึ๐๑YZ‹๋TPœa™JE6V^ bช\UๅJdฮฬฮnฐˆธ๗ม‡ึIชTฉ……ๅ ณg๐๕ซฟ†#2ทืรk๏oeวพƒš์๗อใฒฅ‹ˆ0[แ๑Wคพฅํ”Ž™œวย™ede=^%K2a%Œ๋ฅณง๊บv๎ฏยœึxLF฿ฟ๓V2าRP…ชฺ:๔ยซšห‹R@p2BH ๐ฟHต๔šiฏชชฌสIๅข้๑่d‰cฃhร~|ก๐i=ล cMN*๓ฆล“mรn2 —%”‰Šฉ^——]Cผ_฿E๋ˆ๋”ฮUœอY\Lขอฬ˜?ฤณUMผrดU“ใ้าT๎š“Cคษภ€ฯ์<สฮAํŒฏ NL-ZชชฦŠำ&ฆ„ˆZงJR… ้Zis~V&w\5ขฃขp{ฝผฑy~ด_“ฟt._พซลยฐำษฏพล๑ฆ–ฏtฌฤธฮ,ฃ0{qัฬ&ฒ,‡๑๘ผt๕ p๘X{Uใ๒xฮH—^อแžaMฦrSi&หณ’[Šฬhใย`คr๑:UีW  ฑข„Ÿ˜Q-ฺำ็,•$*ึ7–ู—5Cv๚4๎บ๎Jb<>/๏nษฆ]{5ห‚๒ฎ[ป[„็ุyช๋พะg‘v.š5^•‡ลlB'ห„ร ^ฟŸม!Žิ5ฐk#ccg-ฆ๕wFN๚tTUฅฆก‰฿<‚ๆ๒"„”@ œŒR@เญฝชอhะฮƒญชreม4fงฦ!Gz‡yเฝณ7ฝ$6ย41•/Žิศ" z๔ฒDXSํN7๛:ูX฿ษ€ว…Ž9/-Ž\\Hl„‰_€?}\ฯฆ†.MŽงk‹านฅlv“ž^—๛แช{ตY0๓“ๅeฬITvท ด>ฒํHลฦปW=~!พ˜บ€Eิ=?~x้ทXQ˜3c‰„D}K+•?ฃษXfLOใฎ๋ฎ$.ฺื็gร๖]lุพ[“ฑฬ))ไฦหVcทZuนx๖อ๗8T{ŒีbaัœrŠsณIŠ%ยlA–eUม็๗ำ70Dmc3;๖bhฤyึc๚ท—™ŠJmc3ฟ~๊yอๅE)@ 8!คธอฝjคI;B*Vธฎ8™)ฑH@Uฯ0?ฺp๖ื;Iฐ™น47™)1คFZฑuศ’DXQ ้pz๘จฝŸw๋:๛;^”žภ๗c12โ ๐ฝวูึฃษ๑tcI7–fb5่้uy๙ืซฉ้ำฆzdอlJ’ขQƒlำA•VTeฆ{ึ^/WC•‹+$Uู]โ.p%+j…$KK๎ป๕Šsฒ$‰†ถv*๛ Z|ดฬHKแ7\=.ค~฿ฑ‡wทํิd~fๆs๓kˆดฺuปxแํ์ฏฎฟ0›™_^ยฬย<’โใˆฐ˜ั๋t(ŠŠ/เงp˜ฺฦf๖:LOน[๏;n&oFว›Z๙ี“ฯj./BH มษ!%ภo์U#อฺRP˜›J3)KŽเP๗?xเœตgZ”••ู)ฬJ‰!%2‹AN‚ ขโ๒iwบฺููวฆ†.\อN€‹3๙๖|ข-F†ฝ~ฝ็;Zz59žn)หไ๚โ " zz\^ูv„ใNอล!r้Š(ภพŽq๓กOษ6EQ*.15Rนิก ฌ—T)ใBQ๗=P‘ก๊๕ภ“๖ญ[ฎฃ$7I–hj๋เ?{ๅ ญew&™ž’ฤ=7^C|L4>€อป๖๒ึ–ํšฬSi~ท^y)Q6;.›—ฤช๊ฯูdbniณ‹๒INŒวjฑ`ะ๋QŸ?ภเศว›Zู}ฐŠŽžพsำwoฟ‰‚์L$$๊ZZyTƒ•xBH ม็ฒ- +๋ถฎ["๎*ฺ็Q“}รีฬ,ฬC–eZ;บx๔‰g๑š‹5%1ž{oบŽฤธ|๖๎็ต๗ทh2oY™|šห‰ŽŒฤํ๕๐๚ฆm์>Pลผฒbส ๒ฦE”u\Dฉ*‚A†œN๊[ฺ๘จชšฦถŽ)ำทnนž’์OUโEัึ;ŒR@p2BH ๐ืwซั“fฺ๋„ธkv๖ฉ\9ง&8Xž•LIR4 V3&ฝ ) N_†กQvท๖ณนฑ›ี9)ฌ›Mคษ@ฟว์จแ@ื &วำณsธผ`ฝŽŽQ7?฿r˜–a—ๆโฐtb๕l๒โ# +*;[๛xd‘ฟ๙9Eๅ‰NฉbJ›ฌซจp่}๚๕:™ฯฎ›๕9u•ฬ,*@ฏำัฺีอฏžxฯงน˜“โc๙ึอื“‹?d๛วxyรfMๆ/73;ฏฝ‚˜จ(^/GŽืa13-)›ีŠA?พฃl dุ9JCk{ซชฉoi›ฒ1u%^ๅใO …5•!คเd„เพืvซฑฺRž`ˆปg็P๐…+Wฮ)ล‰ัฌฬNฆ(ัqBLย N_€ฦม1\๓งลa7่s๙๘๗Gฉ๊าไx๚ๆ\.หKรฌืั๎t๓ะUด;š‹รfิ๓๓ีณษ‰‹$ค(lo้ๅ~X…?/ฤ”ถ๘2"j’;ฎนœ9%…่uzฺป{๘ฯงžcฬํั\์ ฑ1w๋๕$ววูฑ๏/พ๛พ&๓˜>u;†ฟ?€^ฏวhะŸจˆrŽัษ๎ƒ‡9ึ4๕/ฯop5ๅฏฤBJ NF)@ @{Bส ๑9น_บrๅ\Sžรชœ โฃˆ0จ˜๒‡a…ƒ$ัํ๒๒oVSซอ้พ5/K๓R1้tด9ำๆCtŽj๏%=สlไแU3ษŠ$V๘ฐน‡฿q๔หHU ่L[ื-w›ฉษ=<\๑eDิ$ท_5ๆ•กื้้่้ๅืy็˜๖ชใข|๛ถHIˆ' ฒ๋ภaž{ƒ&sนjั._ถ“qrบzBDบ\ดttฑทชš๊บอฤ๔™Jผฮ.~๕ไsšซฤBJ NF)@ พ๕๊.5ฮjึL{ฝม๗ฬอ%7.๊+Uฎœkๆฅลฑ<+™๘(ข-ฦb Iภ ๑ิม&^ชnัไx๚ฮ‚|V็ค`า้hqQฑ๙=c^อลaโŸVฮdFŒ`XaKS7•;kพาฑTgXฆR‘•BLM๎}๐กuช$UศU>๋•—2ฟฌƒ^Ogoฟy๚†ฺ[ภ?ฦลwnป”„‚ก{ๆู7฿ำT ลนYฬ..$oF1Q‘H๗ำP8ฬฐs”–Ž.ญๅภัcšหฯx%^zŽ๖๎~๕ไsธ<ฺ’BH มษ!%ภ7_ฅ&hHH๙B!๎›GV์๘TชmM_ฑrๅsIF"‹2ษ‹$มjF/หใ๒BU้s๛8ิ=ฤ‡อฝš[{ X•ŒAงฃeุEลๆƒ๔นดทฎNผีฬ?ฎ,'#ฺN0fSc7ฟฺU{Jวbjjpช"j’›/_รย™e๔zบ๚๚๙ํ3/28ฌฝด:์vพ๓๕IKL$ฑทชšง_GmฯอLgAy Yำงแˆดa4?u/ํไญ>d฿‘อŽืฟฎฤ๛ฯงžgิฅญJ3‹iQ'~ี+*p˜AŸš65vkfMฉ\Tศ๒ฌd :™ๆก1~บ้ ƒฟๆ๒’hณPฑฒœt‡`8ฬ†๚.~ณ็๔TWจ NI–ึoผ{ีใโt๖๘ึพZ‘ฉVO]s+฿ธ๑j’ใใ †B์>Xลsomะ๔8พแาU,š3^‰ื?ภ๏žั^%žR@p2BH p๗ห;ิd{„fฺR๎›Ÿฯ๔(+p˜ww๒๛Žk:฿Yฯšœ :m#.yJ“ขY0-žฬ;v“รค˜ †่qyฉ๊ๆ†.š†ฦฆT,ฐธ˜E‰่e‰บq!ๅ „4—“Œh.+%-าŠ7ๆอฺv_Fฯฉ@Šฒ~ำ=kล‹)p฿Šฌ{L‰จIฎXฑ„ๅ ๆb6้ๆO/ผB{wฏๆ๚หd4๒ƒ;o!=-EQ8Tsœz๑ต)ัถฤธX.žUFA๖ bฃฃ0่d™pX9!ขช7ฐ๋`^ŸŸ่ศHพs๛ค&Ž/ะพท๊ฯผ๑ฎฆว๓ตkVฐxฒo`?<๛2ฺZ[P)@ 8!คธ๋ฅjJคv„TXQ๘๖|า&*W>มŸฮPๅสูโ‹ X™5น๘o๋ 8มAเ(1FrcฃศŒถa7ะหaUลฏ˜ฺ฿9ศ†๚.:œ๎)หKJธ8=,qผ”m7ึ\Nฒb์hY))๖ผมฏีถ๑ไฦณu๚mŠขT1๕ๅธ๏Š Uฏฏ๎<็ปl้"V]ผณษHะ๕โซดvvkฎ฿ z=?Xw+™ำRQ…รว๊๙ใ๓ฏœำ6%ฦลฐ ผ”ยœฤGGc6™ะ้dBก0Ÿžชjุ๋[Uอ˜๛“{_คอส๗พ~3iI‰šY๋oqีสฅ,]0gผopˆ?>๗ ฝ}ฺxู’`fa>ๅ…๙หๆ—‹๛™@ |๚)„”@ ภ?o=ข๖Œyฐ™ šhoXQ๘ฮ‚R##๐†ยผQฦใ๛4ƒOฏปิ44ฦ;ว;(Jpœ๘~ทY–(Lp0-สŠอจว “ )*ž`ˆ๎1๛;ูิะE‡๓nเฒRL‹G'K๋w๒ภ{๛ „อๅ$7.’–”’lทเ †x้h+ฯj:อb๊ pถEิ$k_ฤ๊Kb1™แฯ/พNsGงๆ๚Oง“Yฟ๎6fLOCUTŽิี๓๛g_>'m‰vฐ ผ„ข์$ฦวb1™‘e™p8Œื๏ฃo`ˆชใ๕์9x็ุษ;อii=ฌ/สหณ|แผOUโฝJ{wฯิ~ษ’$ส r™SRฤ๔”$"mถef“Qวเำ๗J!คบF=jเ({๛้๕b3๊งt{Uๅ; ๒OTฎผZำฦS5ƒฟ^wiC]'…ŸR“ xu2๙๑QคFE`5่ั๋dยŠŠ;ขร้f_็›บ้uyฯI,?Y^ฦผi๑่$จ้s๒ภ{๛)ฺ๛พอโ‡KJHฒY๐Cผxค…็7Ÿ“ถจจฏeuึuk[ฤ๋ึUT8ŒA}…$๑ƒsqU‹p้โ‹ฑ˜อ ŽŒ๐ุหoะฺุฎฝb ึ฿u;ูำงกช*ี๕๎™ฯj"mV.ž]Na๖ ’โNˆ(EQ๐๚๔qดพ‘ํ๛~ฎˆšฤl2๑;o!}b=ฌC5ว๘๓[๋หrูาEฌผx>“‰กโkดtvMู๖ฮ,ฬg^Yำ’“ˆดู0๔ห$Iฺ*๎Z@๐ฉ๏_!คTUUa…!ฏŸฦม1๖ด๗ำ>โฦ>E+ฆTu|อฅd๛ธ(xนบ•gชš4ƒNLs›\w้๚ฎฯR“ xDtไฤE’A„AN–ฦลT0Dˆ›ผWืyึwธ๛ูŠrๆคล!G๛F๘แป๛ะโทmQขƒณธ˜$›W ฤsUอผTrNคจ<า)บ˜ZWQแะ๛๔๋u2๋‘‰:WํXพp._[v f CN'Oผ๒&uอญš์ำ๕wFN๚tTUฅฆก‰฿<ยY9o„ลฬลณห)อห!)>‹ูŒNึ๏0๊๗ำ;8ฤฑฦfvจขh๘oฯ`ะ๓ƒ;?™~XU[วŸ^xUำใ}อ% YsษEXฬf†‡y์ๅ7hj๋˜Rm”e™น%…”ๆ็’‘šŒfร q+ 1ๆv/‹‹vlO\@๐ BH เ …UฃN V๖จprฐkˆ–Vริซ˜๚๎‚|’์ใขเ…รอผpD๏็?ZZสย้ŸLs๛ ฑ›‚xว฿ˆ/0>•/Ajิธ˜’%)*ฎ@ง‡=mผW฿‰๋,ํtWฑฒœูฉใB๊H๏0ผท_“9)MŠๆ๏/)&มffฬโ้CผVำ6%ฺvกŠฉฉ"ข&Y2o6WฌX‚ีbaุ้ไษW฿โX“6S๒;o!/3•ฺฦf~ิ๓g๔|f3๓สŠ™Y”OR|,6K:UฏˆแXc {ฆซ๏‹๏\(ห2wืิ˜~xบXyั|.]z๑ธ๘œจฤk˜"•xzฝŽน%E”ไ2-9 ปีŠAฏ  3ๆrัึรกc๕ห๎พ๎สญโ‰K >A)@ ถท๔ชูฑ‘D[Œไq1TFผG9ุ=D๓ ‹A7%ฺซช*๗_THโ„(xถช‰WŽถj:Ÿžๆvดw„mอฝฤฑ๗mง?@Uฯ0%‰ัฬLŽ!ษnSฒD(ฌ0๊า๎tณฃฅ—ปฯ๘Žwญšษฬ”X$ ชg˜mะฆ*OŽแ_RDผีฬ˜?ศ“y๓ุิ™Žฅ*8ร2•Šlฌบn้ศ๙~Ÿบ๗ม‡ึIชT9Dิ$‹ๆฬไ๊UKฑZ"ๅฉืฆฆA›ีš๗฿q y3า8ิสฏž|๖Œœวd42ฟฌ˜๒ย]Utธg˜:๚ษމJวjwบ้๕Rœไ 4)š›ณ^‡,APQ๕hco{?›บN๛xฟX3›ฒคhTเ`ื ?y &s27-Ž๕aย้ ๒ง๋xฟa๊.$|พ‰ฉฉ,ขNŒ‘า"nธtvซงkŒgx—รว๊5ู฿฿นF ณg !Q฿ฺFๅcOŸ–ใ๊t2sK‹™U”OZR"vkzP ƒ ŒR฿ฺฦช๊ำถ wLŒ เฬV{-.šUฦ5ซ—c‹ฏฤ๛ห๋๏pด์ŠO“ัศผฒbJ๓sHKLภnตขื ล@0ฤจหE[WGŽืำ78D„ล™ฯ !%'#„”@ ๐Y!ใHฅ'ฐtF9S๙ŒบqกPTœอรc์ขqhฃ๎์Š),๑ฝฤYวEมŸ๗ีณกพSำ9๘tUัก๎!u ‘m;ฅcถ;๔บฝ'FS’M‚อŒIงC’ 8!›†\์h้eKS๗i ๏‘ตณ)IR๛;๙ู&m ฉำใ๙ยb"LŒxฃใli๊™๒ํVTZeIชุx๗ชวตุ๏๗๘แฅ:ิJสฆz[gpำๅซ‰ดฺuปx๎อ ฌ9ฆษ๑~฿ญ7Pœ“…$I4ดตS๙ุ_8•วdIšmญ„้ษ‰ุmใSบTuผ’fxt”ฆถvS“Sภš†ฦ8า3ฬ๑ัำฮ4zYๆ…๙ใขภเี๑Acทฆs๐ฯkfS:QUt sฃ}#Lฒž–cท;๔{|”'ลPเ jยคื!๑Iๅ[รเ4vณฃฅ๗”vฤ“€นtE `_วธ๙&sฒ(#‘๏.ศ'ฺbdุเ7{ŽฑฝฅW3ํืš˜บ็ว/•ตB’ฅ%Z้ใ๒‚.>G.^|็3&>ํึๆL์š—๗™Šจ@0ภ๐่-]Tีgdิ๕7Eิ$BH ม็ผ!%_LHM2+%–YษไลGg5aึ๋คOอnqOๅC’ฮฤหตŠอhเพ๙yDOˆ‚_๏ฎeงEม$zYโ‘ตs(Lˆ:!qZ†]$ู,gไ|ํN7๎`ˆข๙๑QD[Lu2’ะธ˜ช้แรๆ^๖ถ91eิษ<ฒv6๙๑Q„•=ํ|หaMๆeyV2๗ฮหลa62ไ๑๓่ฎฺ/SŒmŠขTlบgํ”x)ผ๏Š Uฏฏ๎ิj‡ๅdq๛U—แˆŒฤๅ๑๐๊ฦุu@›๖7\Myaฒ,ำฺัลฃO<ƒ?BŸ-ฬžมา"ฒฆงeทc4่้ฤnkอ]ฌ9ฦฺ๊ณห=7^CYA.ฒ,ำาัลฃ?C ิ์…[šŸรญW^zFลgคอสา"J๒r>Sฅช @‘ฑ1š;ฉช=Žsฬ…Eิ$BH มษ!%|9!5Iyr +ณSศฏ˜2๋uศปนWLนจ๊ฆap๔ดถ5ค(D[LŸฟ]หž6ํŠ“^ว?ฏ™M~|$aEew[?]ฃโญๆ3zvง8L~ค˜฿]QU!3่๑Sำ็dKS7๛;ฟะ1อฑไMฤฒณตGถัd^ึไคr๗œขฬ~Uรว็ร%Nลิ๙ ข&)ศสไ๋ื\Ntd$nฏ‡ื7mc๛วฺU๒ฎ๋ฏbfa>:L[g7ฟ|๒Yผ>๘™์๔i\4ซŒำำˆŽดc4ว+gC!ฦ\nฺบ{ูwไ่YŸฦx๗๕WQฉX}โY|~ฟfวYqnท_๕5ข์v\ฏlุฬ๎ƒงG๔ญV.šUJA๖ Rโ‰ฐ˜ัษŸ์~82:>5๏h]ร—ชˆ๚k„‚“BJ ๘jBj’Y)ฑ,ฮLค(มAฌี|b7ทขโ๒iqqดw„c}ฮ๑นiงH ฌ`3sฯœ\ขฬ=~*wj[D๔bอ,rใ" MHœ~ทX‹้ฌœฟ้&V(IŠ&;ึŽรd๋}šŒๅฮkฏ`vq!zŽถ๎n~๕ไsธ=ฯำRY0ณ”์๔iฤDEa2Ž‹จP(ฬ˜MGoQ_uชณ‹(ศžมืฏฺ'โ๓ญl฿wj—QคอสยYe็d‘{’ˆvŽาฺุฮ‘บFฦ\๎ฏ,ข&BJ NF)@ เิ„ิ$eษ1,ษLค(1š๘ฯSฃ๗ Swjปั{ƒ!ฆ;lŸ;k8ะฉ]Qi2๐๐๊YdวFRถ5๗0๊ โ0ฯj;:F„•าคh2ฃํDYŒe ๐ร๔น}T๗ณฉก‹ฺ>็Šๅรๆ^mป6…ิ•ำ๘๚ฬ,์&}.พใ(UC็อu.„ิ๘zl9_๚0'c:๋ฎฝ‚‡ฯห;[wฐyืGšŒๅŽk.gNI!zž๖ž๓ษ็sป?๓7ำ’“X8ซ”ผฬtbQ˜F@"ใ๒z่์้็Pอ1๖T! ณXnฟ๚kฬ+-Bฏำำัำห>๕<ฃ.—fวY„๘Œ> โ3ึลผฒbŠsณIˆ&ยlAงำกช พ@€ก‘QZ8|ฌืwส"j!คเd„Nšค0มมŠฌdŠ$ุ,X&ฆ๒…ย c ]ฃ^ชz†จ%๘™uBdลฺนcB๔ป}๛๖ฃาฐ(ˆฑ˜๘งU3™c'Vุาิ?ค`3๊ฯI{บฦ๋0yh๕Lฒb" †วๅฺqT“yนถ([สf`7้้u๙๘ฟVS;|\๗BH:3ฆงqืuWํภ๋๓๓๖]lพ[“ฑvีeฬ/+—8ฝฝๆฉฟพSใY8ณŒ‚ฌ bใQฒ$Vยธฝ^:บ๛จฎk`ืC_xฉ3ษญW^สฒ z=]}}๚//0์ี์8;I|nูมๆ_N|ฦลD3ฏดˆขœ,bcˆ0›ั๋u„ร @€!็ธˆชชญร๋๓Ÿ65‰R@p2BH งWHMRลสฌ”q1e5c6่ัOฌ1ๅ „่๕pคg˜๚'/!ฆFA ขธต,๋„(๘ทํี้ัฎ(ˆทš๙ว•3ษˆถ ‡ูิุขจD๔็ด]c^๔:‰œุHfฤุฑ› ่e EU๑ร๔บ|์ไ†.Z†วซb#Lำส™dNศตปytW&๓rCI7•fb5่้uy๙ืซฉ9ล ฟฉ„RงNFZ ฿ธแ๊q!ๅ๗๓Ž=ผปmง&cนๅŠต,(/Œฤ1 ใ"*;“8‡ณษ„,ห„รa<>/]ฝTซcoU๕”šwำืึpัฌRŒ]}๖้ึ๎ต›5=ปฎฟŠX‡ฏฯว{๎dใŽ=_่ณq1ั,,/!?+“ฤธ,&3:LX™Q#ฃิทดqธถ_ pฺEิ$BH มษ!%œ!5I^\+ฒ“)IŠ&มjฦbะก“$BŠŠ;ขร้กฆw˜c_LL๘”'วpSi&6ฃž——ฆmQdทPฑขœt‡ 8ฬฦ๚. ฒŒQ'O‰๖๕น}ศไว;Hถb7ะ๋dยŠŠ'ขwฬหฎAฏ๏ย Vฎ5t๓ซตšฬห-e™\_œA„a|œ=ฒํว๛็อu/„ิฉ3=%‰{nผ†๘˜h|›wํๅญ-5หง%N฿เ05 MdNK!!&ณษ„N' …๑๘|๔ r๘X{UOษฉpืฏ]ษข931 t๗๐๛g_ขw@ปUด_E|ฦวDณpf)Y™ฤวFc1™‘eEQร#ิทดqคถ0xฦDิ$BH มษ!%œY!5IN\$+ฒ’)IŒ&ษnมbะ!Kแ 1ี5๊แh๏ี=#”0ฒ๔๙+ zฬ›ว ็‘(H‹Šเ'หห™eล ๓n]Vฃฝ$Mฉvx่ๅ๑ฉ|ฉ‘VlF=LhBLuz8ึ๏dvj,)๖ˆrํ7{Ži2/ท—gqmัt,=c~ฑ๕ศi฿5๒\"„ิiธv“ธ็ฆkIŒมฐuฯ>^฿คอw๎.[ล%sfb4C„ย!LF#:Y&V๐๚}๔ sไx=;๗WM้5™ฎYฝœ%๓fc2่โฯฝLWŸvwb2โ3)>–ๅใ"*6ฺลlB'ห(ŠŠ/เงh˜บฆVฏ' Ÿq5‰R@p2BH gGHM2#ฦฮŠฌdJ“ฃIฑG`1่ัIVU=c^v๑Q๛!Eมn2|ๆ๓n‹าฯ+QmใวหJI‹Rok'ฦbBšขํ๐๘1้e๒ใฃH‰Œภ:13<1•ฯ “1้d|!…w๋:๘ใšฬหบYู\Y8‹^G็จ‡_l=Lำะุys !u๊$'ฤq๏อื‘‹?dG๛yuใš‹รaแท@ึ๔4dYFUAUUUม็๗ำ;0Dmc3;๖ิฤZLWฎXยฒ…s1๔ ๓ว็_กฃงWณใ์‹ˆฯิฤๆ—“—•A\ดใ“ฉyแ๑ PืJu]@๐ฌ‰จI„‚“BJ 8ปBj’I1U–C’Bฤ„ิ)bสๅแPื{๛ )๊ 1ี๋๒ฒ|F๒y% fฤุypY))๖ผก0oิถaš๒ํ๒๚‘e‰ขฉ‘Vฌฦ๑ช7I’€ฐขRำ7ย?n>ฤจ?จนผ='‡+๒งaึ๋่pบyxหaZG\็อu/„ิฉ“ห}ท\ORธฺพ๏ /ฟทI3ํทZ,,(/กผ0๔ิdLฦ๑=Uผ๑ฉyต อ์9t„ํ์dzูาEฌบxf“‘ก๋ลWiํ์ึ์8๛Ÿฤgjb๓หKศ›‘N|t๔ฤ:_aๅีะาNck;พ@Y>7?u!%'#„”@ pn„ิ$ำVVfฅ035†$[Vใ๘Sa<มcชบ‡ูำึ‡;"จ(ฌฮI=ฏDAn\$,)%ูnม ๑jmIV‹&ฺ๎๔8ุ5DQขƒY)ฑคEYฑ๕'ชปผม0uNvต๕ฑฉก›1 ‰ฉoฮอๅฒผ4ฬzํN7๔AN๗ys !u๊ฤวDs฿ญ7’G d็*^x{ใ”oทลlbni1ณŠ๒INˆรf‰@ฏื๘`(ฤพ#5lฑ›ฎ^ํMu[ณ๘"ึ\ฒ‹ษฤภ๐ฝ๔:Mํšg‰q1|๋–๋IŽรฒc฿A๖VU3ฟฌ˜้ฤ9˜Lใ;*Š‚ื?>5ฏฑญฆถNมภ9A)@ 8!ค€s+ค&IŒ`UN 3“cI‰ฏ˜าM์่ๆ †้๓Rี3ฤ,ฯJๆาqQะๆt๓ะ‡่pz4 Qpq ‰6 ž`ˆWถ‘lทh*†vง›๊.อMeษŒคฯ,ศ +Œ๚ƒดŽธ?{๏วu๊ฟปณฝ` ,z๏ฝ›%ช’bษ‘-ษE๑M์ุq๛In๚Mrปพ7ืNs|ุฒ-ห*–ฌb‰”HŠTฅ(ฑ ขwA5› IDAT`ภb{›฿ @$%+†9๏_|agฮ์๙fฯฬซ๏|ฏyyed–H2ตๆฏ้‹›šธตกฃ$1๎๓ตG™ Eฏ˜๛^ฉ๓'ฯ้เ‹GI9•b‘}nวšฏ^ฏcKWM ”bต˜ัI้t†t:$Ih4เ๓๘ึฃO213งสyนi๋&n฿v5“Ÿ฿ฯw๒,Cใ“ชณ|W._|เใหqฆเ]\4ธœ9๏ี๙Jง‰ลxšœblrfMˆจ„‚๗#„”@ ฐ6„ิ %9nช+ฆป82‡ซAทœ1•ญOไฤษdฒ…ภ๕Z-ใ0s๗fC1ี~m…N๛uํฺL„)ž๊ฃฬaUuผ9แลŽ๓;)ฐšศr:ƒคั iฒ&d†ƒ์ŸœgืเฬYuVผ\|yK37ืฃ_Rน๋žp์Šน๏…:œ9vพ๔ฉ๛(+,DNฅ8p๔<๛โšงN'ฑฉณฎๆFสŠ ฐY-่$™L†ค,ณ่”eJ ๒1่๕ฬ๛็?elzF•๓ฒmำ>zใuXอf|฿๚yNŽŒฉ6ฮ\N_y่A ๒rP”4&๙PQˆลใx| ŽO0>=ทฆDิ BH ม๛BJ X[Bj…’ 7ิฑก4ŸR‡›A‡N›ํ่–ษdะ-ืม˜ฦ๘ฃ๏โ วU๛wป๘ฝkZ)ฐ™%dž86Fฅำฆบุ๋?97็ฏoงุn&ก(Œ/E0๊ดฺฬuZM6c*—๑…xsยห๎แYไ5(ฆ~gk3kณBjิโ/vf!šธb๎{!คฮŸ›•฿๚๔'(/*"ฅคxง็8?๘้ฯึฬ๘ดZ-ฺ[ุะBYQ!๖e”“๘A†ฦ&ุด—บŠ2nฝv+f“๚ทน]ปก›ปo†ีla)ไ?'†FTy-5ๅฅ\{ี:6ดท`ะgk)f2 ( ัxœ๙E'GวŸ™%•Zป™งBH ม๛BJ X›Bj…B›™k‹ุXๆฆ$gYLIฺีE‰”ยั9^89ล o@•฿บา<พzu nซ‰เฒชRก:0ต€7[~‘S<3สqฏŸํตลดๆโถ™0-ืช‘•4x’_˜}ฃs์CIฏP๊5ญlซ.B/i๖๙๓—ณK^1๗ฝR็ีbๆท?๓I*Š‹I) {๛x๘ฉ็ึฤุ:›ุAEq!9vzŽL’ฒŒ?bdrŠร}'Y\๒“RRด7ึsว๕ื`6™X๔๛๙žŠทนm้๎เž[ทcณX„B๐™่Rี54TWฒพญ™บส ๒œLF#šๅ…/)หŒOฯ286ม๐„:ๆH)@ x?BH k[Hญk6pkC)W•ๆำŸƒqYjd€h2…'ใธวฯพั9zๆ–T๕o,ห็wฏn!ฯb$—y์ุ(ตนvีลัม™Eผแฟ]E63แdŠGŽ๐“๑์ rฑ‹›๋Jh.po1bิIh€ค’ฦK2ดdืะ oMฌ"สฟmืUขำjZ ๒g/ReทภŸ‡R็ูdไw>s?ฅล(Jšร}|๗ษg.๋˜:›ุะึBuy)9ถฌˆZ‘มp˜ัฉŽž8‰ฯฤj1ฐ่ะ\[อGnธ6[w)เแงžc`t\•๓rUG+ฟz๛อุญVแ>ทƒฃ'T1๖ฦš*ฎjoกถฒgŽฃํ\ชFC:arnŽgwํ[^ีR@๐~„ิ!คVp™ีอิๆูัj4d22@:๑”ยb$ฮqฏŸWFๆ8:๋Sล5mญ(เห[špYŒ๘cIํฅ!/Guqtxึ—Rืถ-o?L๑ศ‘a~ฺ7q๚หbY>k‹it;p™ ซr1+ฆ๔{ผ:๊แอ ๏eฝž?ธฎkช ัi5 ,๙ำ—ฉข๛ู"„ิ๙c4่๙ฯ>@UY ้tšฃ'๘ฮใO_–ฑด7ึฑพญ…š๒2v}VDษฉP˜ฑฉŽใY๐ญŠจมตๅนzฌf3Kหu—๚UZwฉปฅ‰Oy+9VมH˜ว๖{Oฌ้17TWฒนซš๒ฒฌˆ2่ัhดค”ฑxฝNั`@Q๕๕sเ่1Uอ‰R@๐~„ิ%ค่๚vฎฎ*Dฏี“Š‚อ G/iIง3ฤS ั8ป†gืผ˜บฎบ/nj"ืl`iYH5ชPH๓แ ว๙ฝk[q[ณ๕ฐพh˜็๚?xKษี•\[UH“Aฎูธฺ™/ฉ(,F“œ๐๚yuฬร“—'c๊ทuฐตยคีะ?ไOv$žRฎ˜๛^ฉ๓Gง“๘สCR]^J:ฆง๗ุS—t M5Ul๊jงถbED้ )%E0YQณ…๗‰จ‚แ%ลสRwฉฃฉž๎บ‡อN(แษป8pดwMŽตฉถšMmT—•’๋ฐcXฮˆJ))"ัs ‹๔ ฑฎต™Š’ขU๑นHบึ!คเ}!%จOHษถถ,‹‚ม…ฏyุXžO™รJŽ1+ฆ2™ฌ˜šฤ้Ÿฐgx–ร3kSLX[ฬ็ฏjภi6เ‹&๘Qฯ(อ๙ีลั1ฯHดzX฿}w~qaไ๋ช นถชฦ|นfร๒ABQ๐E๔y์šแศ%‹zC›หณqvยเv\“ลืฯ!ค.ภƒคFรWํAj+สษd2โ฿}๒’œปถฒœญิV”Ÿ.2R)‚แ0Ss^๗ฤณฐ€ลl๚…ว Gc”ธ๙ุ-7žRw้g๔ ซr^ฺj๙ิมaทŽFyj็n:ผถN{c๋Z›—3ข‰Šข‰ล˜๕ฮำsrท๗”eพ๒ะƒิT”‘Ig860ศจjN„‚xŽBJ ิ'ควl,w#i ฯเ›o๖a3่i/สฅปุEEฎ ปQ^ซY‹ั}^?ฏy/[ฦอฯใๆ๚~}C“žลh‚GŽา์VŸ๊›๗ใ ว๙ส)๕ฐใ^ๅญใ5ภ5U…lฏ+ฆึeวนœ1uชX์๓xipšใ%3-ะ็๕๓;r%=7!ua๘๊ฏ=H]e™L†พก๕‘ว/๊๙ชJKุNCu%.‡cyk—†TJ!2ํ๑r์ไS&ƒแฌŽ‹'ศฯu๒๑oยfษึ]๚ั3/าsrP•sา\Wรงๅ#ไๆไ‰Eyๆๅฝผ๖๎แ51ถฮๆึต6S]V‚รnCฏหฮŸข(„cQฆ็ผ๔ ๓ึแโ‰๗บz~๕sŸขnY|๖๓๚ป‡T5'BH ม< !%๊Rฑฝ‹ e๙hใ^?฿|๓ลv3ํึ่vะ^”KMฎ ปษ€^ซ!ษn๓E๔ฯx}ฬ{ูkญpGcญฏ#วจg>็ฑccชฬ๊_เ ว๙ญอูzX๑$฿>0ภžแูณ>†^าฒญฆˆ๋ซ‹จฮต‘c2`XžฟxJม‰ำ3๋cืะ,'.nWลฟผฉ‹๕ฅู8๋๕๘๙ร๏^Q๗ฝR†฿}่ช*ษแฤ๐(๒ƒว.สyส‹ ูาICuyนฮีbื๏‰ŒyNŒŒ215‹ม ๛PวN$ev๗q vซ•`8ฬฃฯํเศ‰“ชœ“ฦš*>๓ฑโr8ˆฤb<ฟ็U๖พ}y๏฿ฮฆฎ๊hฅฒด˜[ถฦืฉ"qjฮKOzŽŸ&ขV๘สCPฟg}C#ผzเ jๆ#“žA!คเL„ิ'ค็Mฌ/อC›[โ_฿๎งะf>ํod%Mmžฎb5.๛ib#ฉ(๘bI‚ผ22{ูปบี\ฮงปkฑ๕xรq?6ฆส ฉมล Hœ/oiฦe6เ%๙ททOฒot๎Cหจ“ธนฎ„-nชฯ‹๑”ย\(Fฯœ—g๖….ส๕ีอt—dใฌgn‰?y๐Šบ๏…บ0๖g๎งฑฆ€“#ใำ๗ฝ ว/v็ณu]'อuีธœL#ZญEI‰ล˜š๓prdœฑ้๔ห >,rJมb2Vฑ็_โะ๑ชœ“บสr~ํปp9Dใ1^๛ป|๛ฒŒฅณฉmT”’•-6ŠD™๕ฮsฐ๗{๛H$~ฯ฿๙์4VW‘!C๐{฿~G5๓!„”@ |0BH ๊RงŠ‚#ณ>พฮึฎ‘’H)TๅฺุX๎ฆาiลi2dท‚‰Tถซะb=ร—OLำZษ5ุ:<แ8OฅูํT] ๛BฬGโ|i๓{ฺe?ฏyฮ๙˜ฝŽ[๊KุX๎ฮfผ๕่ด” ฤไžpœร3‹์œfยน ื๓7ทฌฃณุภัY๚าก+๊พB๊ย๐[ŸอตีhะprtŒo>|a„Ta~[บ;hฉซ!?ื‰ษhD’ดคR ัxŒน๙E๚G˜˜Cฃ9ฟs)้ Ž๎บ›P$ย/พฬ;=วU9'5ๅฅฺว๏&?ืI,‘`็koฑ๓ี7/ †Fร๚ถfบšฉ*+!วfEฏำYตฒต๒๐๑~9vYๅ;ฟ้OาT[ตg{: š๙Pาz‡F„‚3ื !ค@}B๊onYGWฑ‹ pxf‘|w|๋/.ฺ›ช]v6”ๅQ•kรฑ,ฆ +ฆ–โ ๆƒผ1๎ๅี1ฯ%ญ๔‰Žj๎kฏยขืแ วxฒwL•Bjฬf>็776f ดว’ำ›}D๔9Lnฌ-bkEๅN+๖ๅฎŠฉt†จœb.ใะ๔"/ อ0ธ0b๊oo]OgQ๎jœ—_Q๗ฝR†/=x-u5h4ว'๘ฟ฿}ไผŽ—๏สesW;-u5ๆป0MhตZE!ใ]๔qbx”ฑฉเยNi4ผ๋ŽๅBเžฑ›ทSๅœT–๓฿~๕cธ]Nโ‰$/ฟฑŸ๖พ~ัฯ+IZ6ดทาูิ@EIัฒˆสnŸ”S กH„ษY=ผำs9•:๛8๛ิrœกaplฒe| Š’ฆwxT)@ 8sํBJ ิ'คึ๕ด/‹‚ƒำ‹<|hˆ<‹๑ฌ>—j\vบJ\หลณ ่ตY1•Tฒbjh!ฤ[^๖ฮ‘J_ฏๆฎ>Z‰Yฏc6ใฉใ๊R ‘8ฟฑฑงษภb4ม7฿ไ”B฿ศ˜R@pๆา+„”@ จKH้ดถ ด8P2p`rž๗Œโ4ฮ้xแ„Lนำสฆr7ตyv\f#F้ฝŒ)<ษˆ/ฬ‘Y^๓^1๕น ๕ูTŽI'1Œ๐ฬ‰IUvู› EYŠ%O๋๘o๔qhz๑ขณศnๆึ๚RบK\”9ฌX๔:ดšlอ’p2+ฆ๖Oฮณs`š`Bqฆๅ๏o[Ÿณt†ท'๘๋W„:_ฎD!๕๋๗}ŒฮๆดZ-cS3|ใ{?")๒Xณšอl์lฃปฅ‘"w>VณI’Hงำฤ“ |~FวŸž!–H\‚+ั๐ภท‘ป†:ำ+…๙.พpว)v็“Hสผ๎ažฑ๋‚_ฏืฑฑฃฮๆ†S2ขtd2 งd‚แ“ณsผำำว‘ค/@ฆํฉq6:9อŽW฿ไBnูผ˜$ๅ'Fว…‚3W^!ค@]Bส(i๙ปึำไฮŠ‚ท&ๆyฒw ว9 ฉ"ษeหช˜ส51๊ดh8]Lฝ9แe๏๐, ๅย‰ฉฯolเ๖†2L:‰‰@„็NLจrห\8†?žไ3ห็#qพฺqŽฮ๚.๚น+œVnช+a]Iลv3ๆๅŒฉ”’&”™ Dxcห๎แYBg!ฆŒ:‰ฟปu=M๎”t†7'ๆ๙ปฝ=Wิ}/„ิ…แsฟ›ฎ–&$Iห๘๔,฿|๘Qโฟ@ ™Œ6uถำีาHIก›ูršˆ๒๙ƒœใp_?Zญƒ^wฉ‹นฃทฎvฆ{แ•ืูญขยูง’๏สๅ‹|œ’7IYๆอC=<๖ณ็ฟ๔l๊lงญฑŽ๒ขBlV :IdV3ขฦงg9ืฯกใtK็~๕W่niDซอฦู {_Sอ|$’2cBH ม™+ฏR@ .!eึ๋๘ป[ืัŸoŒ{yบo‚ฃ‚?œLQแดฐฎ$Ÿ†\fIสถ้Vาโ2รพฆๆู=4K<ฅœ๗9ฟดน‰[๊K0Jใ0/œœขQ…R๓ั8x’:kW;~ต^Žอ-]ฒ1T็ฺธฅพ”ฎVำib*˜[ ๓ๆธ—]รณฤ~Ag+‹^ว฿.วYj9ฮa฿ฑ+๊พB๊ย๐ู{๎d}[ :Ibbv–z๘วDb๏ฏ_ฆืุ้AGc=ๅ%…ซ"*“ษ“ซ"ช็ฤ Yฦj1]โงb Ÿศญไ9ฤโq^|๕ ^~}ฟ*็$ื‘รo}๊>J S)๖้แั็vœ๓๑Œ›บฺ้jn คภีb>MDBaFงฆ9าืฯแพ“ๅšบ๗.ึต6ฃ“$ฦgfy~ฯซฉ–ุ…G)@ ๘9KฏR@ .!e3๊๙››ืQŸŸC*ๆตQฯŸœฤfะ_ะ๓„2e ๋J๒hr;ษณœ.ฆVไฦ[๓์ž!&Ÿป˜๚ํ-อTWŒ^’[ ๓สศ,UN›๊โh1– —๙dg56ƒŽนpŒ๕j/ว=K>–๚ถืำU์ขภfฦค“ะj@Ngล“ -†ุ?9ฯฎก’ํf7๊๙›[ึQ——ณWG=|ต+๊พB๊ย๐™}” ํ-่$“ss๓๗#yฏำฃN’–ทๆ5QVTpZVM")ณ206ฮัฤโ‰K/ขVŠัp฿Gn!?ืI,‘`็koฑ๓ี7U9'96_๔'(+*$ฅค8ะsœ๔g๚8ณ‰ ํญtท4R\อlAง“ศd )หB!ฦฆf8ะำK๏ภ๐%ณ็vฟŠZถ์ลIฦ'…‚3ื^!ค@]Bสi2๐WทtS๋สAVา์cวภ4VรลูึJศุฬlฉpำ˜ŸCžลˆQ'eท๒-หqv;ุั9ยขNั _นบ…jŠัKZF|!L.Ph3ฉ.Ž๑$ม„ฬ}ํUX๔:<แ๐๊1Nx—mLอnช-กฝ(ที„Iwzถˆ/ฤ๋ใ๖ ฯV์ƒโ์ผ~Šบ๏…บ0ะจDHล LL !%g „”@  .!•g1๒ต›บฉvู‘•4{†gู=<ƒ๙"ืY %d๒ญ&ถVธit;ฒbJ’ะj5ซSใKa๖Oฮณwd–@์ลิ๏]ส๕ีE่ดZ†ƒ๔yุ/pฦืฅ ”” &d๎mญฤขื1Š๑๗๛zX^๖ฑตๆrs} - ฌฆ๗คโr}ฐแล{– ืg2™ŒณoผูwE๗BH]๎ฟ๓66wu ื้˜๑z๙ืGž ขธˆmT–‘cท&ขกฃ“ำ๊๋'Šฌ ตXฬ}wŒ•K<‘dฯ[xnฯซชœณษศ๏|ๆ~*J‹Q”4‡๛๚๙๎“ฯาฯY-fถtwะRWCiQAถะผ6ปญ2)ห๘C!F&ฆ8ุ{‚ใƒร—5ฮž~y/•dHEcq'ง…‚3W^!ค@]Bชภfโ/ทwS•kCV^še฿่&tIฮJศธญ&6–ๅำ\เ\อ˜าj •ฮJศŒ.…98ฝภหƒ3gีูํฎkใšชBtZ  Aฦ—ย่ดZีลQDNJศ|ฌฅณ^วl(ส฿๎ํah1ดfฦุY์โ–๚šWคโ)bสK2ธdฯศ,C‹ม๗ลู?ฟuโŠบ๏…บ0๗‘[ธz]'ฝžฅ@ษ9%nvzžS ^Nอะ{ryŸ ‰จๅ‡b4{๛Mๆนˆ'“์.ฯ์Rง?0่๕๎CPUVB:ๆ่‰พ๓๘ำ?๗๏ญ3Wฏ๋คญกŽBwV“yตพWR–Y Ÿไเ๑K–๕‹โlฦ;ฯS/ฝข!‰ฦšBJ ท๖ !%๊Rลv3ฑฝ‹Jง„ขฐs`†7'ผคK+pV2ฆ6”ๆัZเ$9๋fฅNQ8!3ˆp`jำฟPLษถถTธ‘ด๚็ƒxยฑ า&RK)„“2w5W`ึILณBjฤZscT๎ๆ†š"Žำ ื'Ri–b ฦ–ยิๆูษท˜Vใ์฿๎ฟข๎{!ค. ฟํ&ฎธƒ^ข((iฝNhSห"jršพกๆๆืœˆ:•{oป‰ข<I™}๒๔K{T9'’คๅ+=HME™t†ž“ƒ|๛ว?y฿฿9s์l์lฃฃฑž‚<ณ Jก๙คŒ/`xbŠG{›ธ์qvอ†nŒ=ณ๓ <ตsทjๆ#1<5#„”@ œR@€บ„T™รยธฑ‹ ‡•xJแล)L. —.OFQ(!“c4ฐฅยMKก“‚ๅ:EงŠฉ้`”“๓ผ2<หB๔ํเ์†N6Uธ‘4ะ็ 0แc”$ีลQBQ'SูTŽI'1ˆ๐ืฏ๔0๎ฏู1_[Uศี•48p™$mvk•’Fงี “ด$R ฯ๗O๒ํWิ}/„ิ๙S_UมwFIFC๖ฑ2ณ,ข"Lฬฬัำ?ศยšQ™LVzนณB๊ตw๓“ปT;7_งจซ('“ษะ;8ฬท~๔ฤ๊หs:ธชฃ5›•๏ยb2ฃำIคำiโษไr}ฏ)๖9ฦ๐๘ไšธžr#ืo\ั gnaQUsŠD™žBJ ฮ@)@ @]Bชาiใฯn่ lYH=ื?ษแ™ลหพล-”ฑ๕lญ( ฅะ‰jยฌ“–kL…’2ำ(๏L-๐สศž๐{mแb{ส๒ัวฝ~๚ผ~๕5—ำi"ษw4–aาIL"|mฯQฆ‘5?๖kซ ูVSD}^นfC6ใNฃAd2ฦ๙ญ›[บb๎{!คฮšŠ2ถtwPWQNAž ๒–แL&C0a|z–ฃฬz็1›ŒชธฆL๎นu;%๙$e™7ๅ๑^Rํ๎CะPUI† '†F๙—>Fžำมๆ๎šjช(r็c1™$-้t†D2‰/dh|‚ท๖221ตฆฎ็๎›ถฑm๓LžE?ูฑ ตผว„ยQFf„‚3BJ P—ชqู๙“m”ๆXˆฅžํ› วณ„คัฌ๏„Œอ gs…›ถ•Œ)ฝiนฦT8™b2แ๐ฬ"ป†f๑„c|ํฆnึ•ๆกzๆ–84ณH•ำฆ>ม‘ษ‘SึPŠQ’๗‡๙ฺ๎ฃฬ„ขชฟVฃแบ๊Bnฌ)ฆ!?+ฆ4หq%+iฆƒQŽ{ผ<4CŸืฏ๚๛^ฉOei1[บ;จฏช$ฯ้ภhะ/วˆ&ปๅ3)๓๒๛้ลจฒฦ้ sห”ธ‘S):|”?ฟSต๑ŸนŸฦšJF&ฆ› ฅถwž ‹ษ„Vซ%I“Lส,๚ ŒM๐ฮัใŒNMฏษ๋๙่ ืฒ}๋&LF๓พ%žฑ‹๔)Aื2มp„ั™9!คเ „ิ%ค๊๒r๘“mํ-ฤไOŸ ฟ*ึ ก„ŒEฏcSน›๖ข\Šl&Lz ญFƒฒ,ฆf‚Qอ,าQ”Ks€ฃณ>^๓ะ^˜ซสXŠศ)nญ/Aฟ,คrื‘ำฒมิภ5ู IDAT€Aา๒ษฮj>V…I'eหg2ค3O)xย1zๆ–ุ54ณ&:žณ€B๊ฌ)+*`sWMตีห"*++•ด‚ข(่uzดZ ๓พ%ใ๑ŸbณšU>vห” งRผ}๔?z๖Eีฦ๗o}๚ดิึ ีjI$“ค”fใ{Q๑d‚…%?ƒฃผ}๔3sk๚znฟjnพf3fฃ‘…%?Oผธ‹tZQล\Baฦf=BH ม!%จKH5บั๕ํูฬDๅO๔Ž1ผZณใ %dŒ:‰อๅn:Šr)ฒ›1Ÿ’1‘S่ตZฬz %แะฬ"/ ฮฐนญสXŠ+ 7ีฃ—$ฦ–B๙ฎ#,DโชปŽฦ|ผญbป%IEAงีขำjฒbJNแ‰ฤW3ึbแ๖_. „๚eป๓ูฒฎ“ๆฺj๒r˜ FดZ-Šข‰ล˜๑ฮ“LสิU•ฏŠ‚๏ไY,*ูฆwzฬF#ทoป‹ษŒฯ๏็{O=งบํzห๑ภ7@yq)%ลปว๚๘ำฯซ๊J l์lฃฑฆŠŠโขำj{Eb1Nฑศ1ฆ=^U]๖-นใ†kVใ์ษป‘Sฒ*ฦพ1แ๑ !%g „”@  .!ี^”ห๏_FกอD(‘โัža&Qี|ืก„ŒNซaKE]ล. lfrŒบำj -†8:๋ใ๘ผŸjงMUb*ษp]uzIห๐b?{๙0xRu๗D[a.บSโ์่{†gนฑถ˜ญ•”9,ุ z๔’–T:CTN1Œrpz‘]ร3Lึ~L !๕~\N[ืuาR[Mก;/+ขดZ%M,วณเcljšคœ"ื‘Cศfฃ‘p-Vณ_ ภรO=‡AฏS]ฬ+JšปnฺFeI1)Eแะ๑|๏'ฯชb์ฅ…l๊jงฑบท+ฃั€ค•XูษO$y๕Cผy๐ณ๓ ช\งทmฺภGoผซูฬR ภ;v!ห๊Rพ@IฯผR@pBH ๊Rล.~ฺVVก„ฬŒ0Œช๎;%d4ธฆฒ6•a^~อJ:MTV˜ F9:ทฤqฯ•*SืVขำj\๒g/"”U7?ล.~๏šV l๏ลู3}8Mnk(ecน›2‡๋rฆ›’ษI*L"šYd็เ4๐ฺฎ(„ิ{X-fฎปjญ๕ตๆ็V๔:Oเ]XdbึC<™ภiทฏ~nฅ]7]ีla)ไO?$iU๓)%อ]ฏงฒดEIsคฏŸ|๒™5=ๆฒขB6wตำXS•ญํe4db: $-™ L{<|;฿'žPŸ_]ะอ7o[ณ'w์"™Tว๕,๚Ly„‚3BJ P—ZWšวWฏnมm5Lศเ๐0sก˜jฟ๛ค’ๆ ฉqูะญ+ฅั€คษ Žจฌเ ว82๋ฃืใงยa]ำbJซีpue:ญ†… ฒ๓Q9ฅบyYW’วWฏy/ฮ>4ฤฯ๚OoŸo1r{c๋J๒ฒbส ;ญht0ย;S ฌŠเ”rBHอbasW;]-ๆปฐ˜ฬ๏ฝN$๐,๚˜œ™#)หุฌ–๗}~jึC4็cทˆอbม ๒รg^`๕X8+Rฉ4wnฟŽชฒา้4GO ๐วŸ^“cญ,-fSW; Uธœฺู^’ค%ฅ(ฤโ ๆ}่๕zŠ๒๓ะjตLฬฮ๒O˜HLฝkล–๎๎นu;6‹…@(ฤ“;vOจc;๔โR€ฉy!คเL„ิ%คฎ*ห็+Wทg1ˆห|๏ะ*‹fฏ`ั๋ธทญ’บผ”L†ฉ@„DJก4'+8tฺ์–ฐlญข8วๆ–่๕,QšcY“bJ'iูZแFาj่Ÿ๒ว;’H)ช›— ฅy|ๅ๊V๒ญู8๛ฯwู9๘มํเKs,TWยบ’zรuT——’Nง้้ไ=๖ิšcUY ;hจช ฯ้ฤd4 ัd‹ฬGใqๆ}Kฬxฝ„#1์V Wuดข“tLฮอ๑/?xŒ`8‚Zนชฃ•๛๎ธ9gแOํุM4ฎŽตoaษฯ๔ขR@pBH ๊R[*๖–f\#x’|wฅ˜zทaุ :๎iซคึ•ƒฌคู;:วพ‘9บK\ดๅRlท`3่ะ-gmฤไsหb๊ธืO‰ผฆฤ”AงesyVH๐๘ฃ‘•ด๊ๆeSน›฿ฺูLrœฟ์ž…Ÿฉฬตqs] ลฎีnŠ:ญYIJศŒ๛#ผ1๎aฯศแ51๕_QH๔zถtwะัTOYQ!V‹$‘NgH$“ูขื#c ŒŽS_U๑YQงฒ2ํ๑r฿ท`ทZ †ร<๚ีt?;•”ข๐‘mืRSQF&แุภ่“kblตe\ีัJ]eEvkžมํš—ฮfDy}ฬx็ั๋t8s์ŒMอ`1›ุิูŽ^งcฺใๅ_๘8Kม jืŠuญอ|โฃทcต ‡y๚ฅ=„ฃุ๊ฎ>๏[bfม'„”@ œR@€บ„ิตU…|qs.ณฅX’๏ผ3ฐ&ทC-zIหงบjจสต#+ ป†gyฆo‚B›IฃกนะI{a๎)Sาˆห)<‘8ฝsK๔yฺึ†˜2้%6–ป‘4pใ็w$ญยตvke_าŒหlภK๒ooŸd฿ู่ต‡ฏฮตqK})]%. ญ&LหSr:C0!3โ ๑๖ฤษ'๏ผ5+ "a{%’ฒ๚$yJIs๛u[ฉซฌ “ษp|h˜{ไ‰ห:ฆ๚ชŠeUNnNฮชˆJงำDใ1fฝ xั๋๕8s์ง EQุา‰Aฏcฺ3ฯฟ่ —ช]+:›xเฮษฑูE"<๒B*ษ๘๒..1ป(„”@ œ‰R@€บ„ิถš"~sc#Nณ_,ษw JชWHฅา>ฟฑ*งคขฐsp†NNแถšVFาhh*pะZเคiลnะ#"ฆๆฃ z=Y1ๅถ˜.ซ˜ฒtฌ/หG ๔zแŽwU9/ืV๒ฅอMไ.‹ฯู฿ฯ๋cžuŒฦ|๋Š้(สฅภfฦค“ะฎˆฉx’_ˆท&ๆู54C๒2d‘WR’คeC{+ฺZ(+*ภfต “ฒ ’rŸ?ศเ๘ƒฃใไๅ:ฯZDญ”ez†xเฎqุ์„"žx๑ebq๕m#Vาnฝf3๕U•dศะ74ยฟ๐๑ห2–๚ช 6uตS[Q†3วŽษp๊ึผฌˆš๑.`2NQ+Dc1–!ฎูะ…Aฏgv~o่Iผ‹>ีฎํu็ˆซฐ‹ฉ|ac#ฅ9b)…g๛&xkbž“—~NษdhฬwะU์ขยiลfิฃืjศd ก(ฬGโ๔y๔{8L†K"ฆœfล. +คLฅB๊ถ†ฌ๘ฬ1fล็?พqœƒำ‹ไุ๋K๓ุ^[L“Ižล€A’ะh ฉค๑ลœœ๒๊่o\d1uฅ ฉŽฆzึท6SSQ†รพ"ข@N-‹จษiF&ง0DDญpไฤI๎ปfr"ฑฯ๎ทFEม/็๚hฎซFƒ†ฑqพ๑ฝ]ิ๓ต7ึฑฎต™š๒2œ96๔:}ถXนข‰ล˜๑ฮ3ฟธ„คำ’็tž๕qEม็ฐกฝ“ัภผo‰xงŒฯฬชvhจฎไณ๗‰k9ฮ^ุ๛:ลล53>ƒ@EIu•ๅไนฐ˜M่$jVb พก0฿ต@ ฌ"„”@ 19•Yษึ•4แ„ฬL(สปS‹์c&ธvถŸRมงบjฐ๕xรqภIUl5yh5พฐฑbป…˜œโฉใœYภfะŸ๕1R้4Mn'ํEนTๅฺฒSห5ฆ’Šยb4ม o€๙6ƒ๎ขŠ)—ลHGQ.เะ๔"พ๋ฐ*็ๅฃMๅ|v]-๖e๑๙^?ฮแ™ [fkEืVาไvเ21HZเ=1ี็๕๓ฺ˜็œท 2ฎ!ี\[อฆฎvjสKqุํ๔:@CJI …›žexbƒ^AEิ วNrฯญq9Dใ1ž฿๓๓>uึ*บ๎ช๕ดิี ัhŸเฟ๛ศE9O{cWuดQUZ‚รnล ฯŠจTJ!‹ฒเ๓‰ฦt:I:—ุฦ ัีาˆูhbai‰|โFงฆUปVิWU๐ะ=wโr:‰ฦcผธ๗ ๆ.๏ฤt:ƒษhคฆข”š๒2 ๒r1MH’D:FNษ$’2IYๆ‘็v๐•ฯฟ@ ฌ"„”@ /ฮd\#&„คีRาDไ3ม(Gf}ผ22ว๘R๘ฒ๕žึJ๎๏ฌมnิแ ว๙ึ'Iฅี+ค$†/ljคุn&’L๑ฤฑ1Žy–ฐ่u๚XJ&CหNgฑ‹๊\v“รฒ˜J( พh’…ฝES๙Vm…Nาภม้rืUฮหฏดT๐`W-vฃo8ฮื_๋ฅgn้ขœฺ๋ชBฎซ.ค!฿หl@/iษœ!wฯrhๆยfCจ]HีWUฐฅปƒšŠ2rs์๔ูlrJ&Ž09็กx ฃแโˆจŽs๗Mศs:‰ลใผฐ๏uๆๆีYซ่š ดีืกัhž˜ไฟ๛๒YนญกŽอ]ํT”ใฐNQ)B‘พ@€h<Nส’s%“ฮเ…่ljภl2ฑ่๗๓Ÿ<ห๐๘คjืŠšŠ2~ํปศฯอ%ณ๓ต7™š๓r_ำ9‰ฦฑXLดึีR[Y†;7ฃั€Vฃ%I#ห2I9E,‘  ‘ฮd๘฿฿}Dtู‚3BJ ศvู๋,vq]U!ญ…NVfฝ„Vฃ!ษ•fCQz็์ใไ|เฒ๕พ๖*๎๋จฦfะ1Š๑๏T-ค๔’–ฯol ศf&œL๑่ั‚uา93•NSๅดฑก,ŸJง ‡ู€Aาf[งฃIƒ๔ฬ๚ฐ๕NLi ภjขฅ +ค™œ็k{Žชr^๎mหŠO›Aว\8ฦื_ํฅืsqทa]SUศMตลิๆูqš t™ฬJ]ฐlฦิKƒ3๔z.ŒSซช.+esw;๕Uไ9ซRCNฅGขLyผ M Iyฎ‹~Mรฃ|ไ†kษฯuK$ุ๙ฺ[LฯyT๗[ืuััXFซadbŠo|๏Gค”๓฿ฝฎต‰๎–&ชสJ–ทSf3@SJvฮb‰’V‹Vซ=๏๓e2มํ๕Xอf|?๕ฃใช]+ชJK๘ฏ nW6ฮvฝ๑6ฃS3HฺKgค"ั89v+ญ๕ตซ๕พŒ†ำET<™$Oโ…Hฅtหk™R@๐ฮBH AVHญป1฿มถš"ฺŠœ-XNS19[—่ธืฯซฃŽฮ^๚m)tึpo[%ฝŽูPŒ?p’ดŠหM:‰฿ธช›‰PBๆ‡GF[ ฏn฿:)…Z—๕e๙T9m8Lูโ็ูถRฏ(ภษ๙FtbJฃัP`3ัRเ@ษภ๓๕+๊RŸ่จๆพ๖*,zžpŒx๕'ผ_ฤ๊ดZถีq}u!ีนv&=Iปšๅๆ ว96ทฤฎก๚ฯS ซMHU–ณฉป†ชJ๒r—3ขE!2ํ๑229คqป\—์šFวนํบซO*ญUดนซƒฮๆดZ-ฃ“ำ|ใแ!ŸcำญVห๚ถf:›จ,->ฃฎWvฮๆ}K$e๙‚‰จSY๔่lชวjถฐ ๒ƒงŸ็ฤ๐จjืŠ๒โ"~พQ—K<‘dฯ[›X>“H4NฎรNGSUe%8ํ๖ีˆJZ!™LK$I$“„#QEแฬิ-!คเž…‚ำ…ิ Uน6ถีัU์ข$ว‚อ Cาพืษm1š•{Ff/Xฑ็ณแำต|ฌฅณ^วL(สฟฟ}5’›u:~cc=nซ‰`Bๆ{‡˜ ว.เ>Œ1ีU’Gห†รd@ฏ}ฏ^ัR,มภB“  ’–ฒœsSZญ†B›‰&ท%แญ‰yvo*็ๅฎ๎m}O|พ.]‹uฃคe{] [+ จฮต‘c2ฌึ‹ง<แ=ณK์ža๐วฅ!URเf๋บNšjซp9˜ FดZ ฉๅยืำs^ฦฆfHง3ไปœ—ซีj้nidcgeE…ุญึUY’”ณ5ข|Kฤ ๔:’tq3{ฒBช›ลJ โัgwpด@ตkEฑ;Ÿฯ฿/E๙y$’2ฏพsˆc'1~ˆgK")SVT@}U%•%EหR1{%ญR’I™`(L8;ซc !%๏G)@ เ ฉrอnจ)fSน›r‡%๛b|ส๖/<ษเBwฆุ;2Kโ"uพ๛๕ซ๘Hc&ฤT ยทœDซb!•cิ๓฿6ิใฒ๑ว“|๛ภก„|Qฯ‘ST:ญl*หJงู€qe.•4X’_ˆฃs>L:้ฌ3ฆt’–"›™๚R้4ฏy๘_ฏ๖ชr^~m}=w6—ฏŠฯฟyๅ(ฃ—ฑจŽQฯตล\]Y@นรบzฅาbrŠนPŒƒ3‹์šaย9ซcฎU!ๅvๅฒนซ–บ ๓๓0ณQŠ’&ใYXddrEQศuไ\๖X™˜žๅฺ๋NฃcชŒ๛๕m-ฌokA'ILฮฮ๑O฿1แh๔—๗:Z้jn<-#*“aตภาฑxƒโ‹จ—ด5ึ‘cตŒ„y์๙—8t„jืŠ‚<ฟ๙ภว)v็“”e^๗‡๚๚1 ์)Eกขธ˜†๊JJ ุ,๔ห[SJš”’"‘H GˆDch>D*!คเ!%œZมขืฑฝฎ˜ซJ๓ฉ>c๛—œNˆ'[ ๓ฮิป‡g‰$Stฌ_ุุศํฅ%‰‰@„oฝ๎"m๙ธ8M>ทกž\ณฅX’oฝ}’จœบ$็Žศ)*V6–ๅS›—อ˜2๊ดh85c*D|Iฃก4ว๒ ง—ดอิๆe…ิพั9๗kวU9/gŠฯฟzๅ่Y‹ž‹/7ี•ฐตาMiŽ›A‡n9c**ง˜ D88ฝศ๎กYfBฟX$ฌ5!ๅดนzCืชˆ2›Œูbษ้4ฑDฯ‚๑™Yโ๑$.gฮš‰•‰™9ฎูะuš(81<ขสธ๏jibcG+:Iวิœ‡มcร,b๕z›:ikจฃขคปี‚NาไTŠ`8‚gม‡œ’/IFิ™๘Z๋kษฑูE"<๑โหผำฃฮ฿#€\'_|๐W))p“”e<ิร;=ฝXฬฆ๓>ถVฃฅดจ€ฆฺjŠ๒๓ฐšอซ๓•RRศrŠx2I0&Ÿำ6K!คเ!%|8!uช|ุVSฤๆr7uงศ 9!”™ Dุ?1ฯพั9ฃ‰ 2ึ/mnโ–๚Œ’ฤธ?ฬทœ\bช|ษฐ๙์บ:œfพX’‚x๊าv \ษ˜ZW’G}~น&#I‹F๒)bjh!(ฑฐ˜2่$Šํfj\vd%อ+#ณ฿7๚T9/gŠฯฏํ>ยt0บfฦ็0้๙Hc9ส๒)sXฐ๊uHฺl๓H2ลd สม้v L{oญ)ปียึuด7ึS˜Ÿ‡ลdB’ด(้4๑Dฯ‚ษ™9ฒLŽอบๆberึรึuง‰‚ใƒCชŒ๛ฮฆ6vถฃื้˜๖x๙—>†?x๚VUฃAฯฦŽ6:›)-tc;CDBaๆๆI)) z%Q+๘AZjซqุํ„ฃžฺน‡ทซณฆ@ฎ#‡/=xฅ…ศฉ๛๔๐ึแl๓9ำ 7PQRD]e9…๙.ฬ&:IG&“ห•ฎyK ๑D๒ผ จ !%๏G)@ เ„ิฉlฉpsCM1uyv๒,FŒ:)†]INสฬฃผ;ณ๗qr]๗a๏๗ฮggfgg{_๔B€€HŠฝIฆ ญjR=rไ’(ฒ_ž_โฤqlวq^œYv$[qlห‘"Y–dI‘eหN‰^ป‹ล๖:;ฝž?fwY@ษ,v/|พ๑ร™;็œ๖|๑+žผ0๗ถ7๕Ÿฟa3w๕ฆqษ2ณE์…แซฺ๖๚rำ๔๒‰=Dฝn2…/<‡j˜๋2–’ชำ๕ณ;gS2Bฬ๗j1•ฏiŒe‹ -ึ‹hงCฏyœ2อaฑša๐ุ่,_zฮž)2ฏŸฟ๕ุ1ๆŠี 7ฮTะว=}อ์i‰ำpหศ’„nZ”T้B] ?<ฑk.ง“™…Eพ๒o“ษีป9z=๎•”พอ47ึำนœNy-5/W(1ฟ”AUU<ฯU้๖ำศŠ๔wu ‡)W+|ั'xๆศQพ+"ก ์ใฅต)…n่>~Šง%xs๗†iZxฝzฺZ้jkก1€ฯ๋YkZข้[DE IDATšฆSUr…"Šช]–s)„”@ \ŠR@ภRซ์m‰s[wšd˜ธ฿‹ื)#K`ฌDmL*Ÿอ2xa–‹oฑฯฏด…ปำธd–‹|ํฅ[ฏ}:ไใใป{{\,–k|ๅะฺ: ฉUŠŠF:์ck’DdE2ฎค๒™…•ดฬำ๓9‰tฐ.ฆผ.™ๆฐŸŽhอ0xtd–?~žB๊ีโณฤฟ?p”ลrmรŽท-เฎfฎki ๒ใ_‰˜า “ขข1™/๓ฤฮ’ฏi+ำ๕RAฏgpฮํ์ฺOsช๑ี"JUXฮๅ™˜ย4 >฿†ฟVfๆุปc+ญฉ—Eมั3Cุฑด–พnบn'n—ซ.คืwจTซ์พuๅ|% ๚8๕(Uำศ๋"ชฆ(๕›uQซไ‹%๚:ฺˆE"”ซU~๔๘S!ตสฮt7wฆุ–Š’ x๑นdR=จขฬซœšฯ๒ฤ…9ฮ-ๆ฿ิฑๅ;ทrkwN‡ƒัLฏลด๑ฃผ5เม]„V„ิ—žC฿ **A7ถฏŠ)๗Z๔›j˜k*cู็๓Mฑ5!ฅŸŸแ+‡ฮู๒ผผR|Ž-๙wŽฒ|™าNฏ$ฑ ๗๔6ณป9N*่ล๗1u1[โน‰ฅXSฏบ๚๚ถ}ƒm้ฟู!ื;vช*ห๙<็.\d๘โฝํm~[\+ณ ‹\ทu๓Š(ะ9r๒ GNžมaรศอM]|n.๓Kห;;D[บ‰ึฆ—ลa=k5"j Uำ๑n€ˆจืR(•้ikก!ฅRซ๒ใ'žแฑ็๖]แ๗z๙ง ฃ9n=}–GŸ=D4ฉ฿+Wj„Cถ๕๗าำJ,ฦํvฝJDีT•ZM%W, ๋ๆ9—BH มฅ!%\~!ตJ"ฬmMloŠญDmผ,ฆjšมbEแฬ|Ž'ฦๆ8>ป†Ž๙kทlใๆฮN‡ƒแฅ}rl#Šฑ ูEศใdพTRๆ{7ฆ๋[lJึ#ฆฒŒCzน^ุุr‘‘L‘;’ด†(†ม‡ฆ๘๊a{ถY—๏ส-]Mธไบ๘G^’๒ถ‘้iqw_3ปา 4ผx]N่ฆEAัอ88ฑp๛nฺzU7ˆห๙ยmAฟopตๆขj,็๓œg๘โษ†Mษ„ญฎ•นฅ%vnX/>หกใงl™J฿ีษญ๛ฎรใvฃj:Šชโ๓xV๊@ี#ขฒ๙"ณ‹K†Žืใp"jํนUฎะู’&‹Qญีx่้็xไ้็m๛ฎ๐ธ|แSะัฺŒiš;3ฤCO=G,zฯ—+5ขav ๔ััฺL4ยใv!I ร@ีTชŠŠขช”ส รเJ†๕ !%—"„”@ pๅ„ิ+ฅหm]M์jn 9\/ภ์”๋๕*jบAฆข0ด”gpt–#ำ™Ÿzฌ}๋vn๊hDvH -๘๎้‹(บ}…TOCˆm๏$่v2Wฌ๒•CCNHญm๐V"ฆ๖ถฤู!๐โ‘ๅz)ำขข๊๘\2ูAU7๘ัน)์{ ฉ_ปy7wฝ,>ํฃ/QR4อc แฎž4;Vล”S^ซ VPด“๏U Z–u›e1จj*ห๙ฃSœง!ถˆZe!ณฬถ^:Zา˜ฆษั3C<๗าqœฒš-Huำ~บ:p8ิCึZjrพภ์ยšฎ๐๙7ฌˆzYศTiK7‘lˆRU<{ˆ?๑Œm฿.ง“/|๚AบฺZ0M“็†๙ัเSฤฃ‘W}ฎRUH%โlํ๋ฆฝ9M$ฤํr!I`˜&šฆฃjลr…rตŠi^๗งR@๐:o^!คเส ฉUšC~nํNฑท%AKุOะใยๅฐE7ศTTF2žพ8ฯ3ใ ผ3๚฿พƒwด%‘็๓|๋๘v~’$"์ึv.'ณล*rhkƒฯจจh4๘<์oOฒ%!ฌ‹)‡H`˜ว็–๙ž<ลrUฑyyฅ๘<ฟTเื~‰ชฆ๖:šŠrwo3[ฃ$ƒ+b n—$้ชnkŠz[พX˜bhlœh(h[ตสโr–อ=]kขเ๘ู๓FoG;–eqzd”๏=ฟŸพŽv๚ปฺinL๐๛qญœ+0ั šขR,•)W*HŽ๕‰BJ .E)@ เ๊ ฉU|.'w๕คูš ป!Hฤ๋ฦต๒วฒfšjs%^˜Zโภศ eU็ท๎ลžึเิ|Ž??2Lุ๋ฒํฺoOลxฯๆ6|N™ฉB™?94„รfํนŠŠ†ฯๅไ=›ZyG[rM.Z+ขขช1™+๓โL†#ณถSฏŸg๒๋‡Žl˜b๓—ƒ}ญ nํnบ๎ๆซบA๙฿๘๖nนyเšYหlพ@w{+ฝํmX–ลฉแQ๐†R’$ัำFoGฉD>ฏwญธผiškR*W,๒ฤ๓G่lkม๋q๎ผิ•TผฆdEีx๚ศQพ๛ะ[_k_๘๔ƒ๔wv`a1rq‚Sรฃl่ฃ)'เ๓แtสX่†Žฆ้ิT•|ฑDฅZC^็R!คเuษBH ม๚ ฉUœทu7qC{’žxˆ˜ืƒว้@ิ•ขูS๙2‡&นพ%มถฆpb.หW‘xmป๖ปา ฬ@+^งฬdพ.ค์X yฆP!ไq๑›w์$๎๗`Qฏ+%KาZ1ํ’ช1Sจpd:รC็ง7tืบ็.๖ฎˆฯำ 9ี฿แZ๛‹ม4อซe๏็ใwoป~๋ๆม›๚ฎ™u,Kด77ัท" ฮŒ\เัgโqo,Q๎r:้lmฆฏณƒdC ฟื‹ผRหOQU2นŠชั’jฤใv“ษๅ8|Tฟm(คTU#‹ะ˜Dี4ž}้8฿ปGl}ญ}“ฐฉป‡Cขช(†ฑูถฺpUDe๓jŠบa"„‚KBJ X!๕J๖ท%นฃ'M_—งCB7MJชฮLกยK3c*_0๓๙ปwณปน.คŽฯe๙7BH]~7~๗ถwn}อฌcMQH6ฤ่๎เุ87๘4>ฏg]วๅ๕x่lmฆปญ•Tขฏวƒ์p`˜&Šข’ษๅ9?6ฮมc'˜œเ๖w\ฯ}ท฿Lภ็c9Ÿ็ิะัHศ–BJ7 ยมญฉบกs๘๘)พƒnํญ์ถ…ฮ6ZR8ๅบhฒ,‹ชขิETญFฎXBำ๔ [๋K)@ ธ!ค€)คVูัใๆฮšb4ผฮตข฿บi2ถ\โไ|–#SJชf+1e˜ทtฅธฝ;Kv0ถ\ไO_8ว†BjพT%ๆ๓๐/฿น•ฦ —ขข๑๕cXฎ(NŠŠฦถTŒ้A~—Œ,I–EY5˜.”96ณฬcฃณLn1๕๎นŽ้Žอ.๓ผtอ๗๋%คnฺฝcpำŠผนะ4h8ฬๆ.$$†/Ž๓รวžฤ๏[ŸTbฏวCw[+]m-4ฦcx=’ำ2ฉ) ™lžs.rุ่Iฆ็^๕[ฎฟŽ๗u+ŸŸlกภะ่E~nทหŽื7Ÿถtบapไไi๊od›๑o๊๎d๏๖-tทท ‡qป]ศyญขชฉฬ/-S*—1LkรBJ .E)@ `c ฉUzใa๎์I๓๎|ฏ่ไf˜&5อ`ฑขpv!วแษ%–ซŠ-ฤ”f˜ู“ๆึ๎&œฃ™_}aฏำiปkhก\#๎๓๐ซ๏B2เฅ h|ํฅjšมuอq&๓eฦs%ถฆb์J7 ๚ธe’„น"ฆf Žฯ-๓่๐ฬบŠฉ฿ฟw›bXภKำ~๓ภัk๎พ_/!u๓u;๛ป:ฎฅu$เ๗ฑตทI’Ÿเ๛ ๘|Wq ^‡พŽ6z:ฺˆว"ฏŠˆช) ‹หY†.Œs๐่ f—^๗87ํูลw฿Nะ๏'W(0:1…ๅฒฅฒL ฏวM{Kร09zๆ๑l๘qoํ๋a฿ฮmtดค‰†Bx.$ษaXX8ๅzแ๒L.วา๒บ+ฃ!%—"„”@ `!๕โ็_|ฯ>zใ!$๊Eณ%ภนR˜ทฆd* ็—๒œ\bกTะbJ5L๎ํkๆ)œ‰๓Kว ็๑บ์'คห5~ฟrำV๙šฦŸฟ8ŒDฝ“เ+™ฬ—น-ฒmELฅC~๎WGLอ—ชษp`t–๑l้๊qป๖ฒ-ล^œZโท;vอ๗๋%คnป{ฐงฃํZZG|^/๛{‘&ฆ๘#ธ RๅJ ฏวอ๖>๚:‰GWD”์@7 jŠยB&หนั1Ÿ8ล์ยาO=;v๏เƒ๗Aะ _,2>=‹ไpป์(คL<-iLำไ๘ู๓ูทvCŽีแธn๋fvoูD{sแ`ทห…$ีัEี4t@ำuย’C"“อ‘+1mฒ—BJ ^็oN!คภ>Bสใ”๙๗๎aS2ŒaมtพLYีi๛ y\ธ ่หU•‘Lง3LไสO๒(บม}›ฺธฑ=‰์8ทXเฯœวgC!•ฉ($พpำโ~นšสxaฟI<บ฿™ฬ—ห–ุaw:Nsธ.ฆœบiQัtJUŽฯfylt†‘L๑๊l%‰๔ฎ=lME1,8<นศ๏<~šป๏ืKHพoฯ`w[ห5ณŽšฆแ๗๙ุฑฉ‡รมุไ4๛ศใWด†TนRรใrฑ}S}]ํ$bQผn‡ร4จึj,.็8;rCวO1ฟ”yCวฝ~วV>๎ป ไKEfๆั ร–Bส4M.]m-Xฆล‰กaพ๚ญ๏nจ1บ].๖ํฦึพnฺ›ำ„\N0L0PU•|ฑLพXย๏๓าฺ”B–d๓ฒ๙†iฺโ|!%—"„”@ `!ๅw9๙ฝ{ฏฃ?F7-žน8ฯŸโฮžf๖ต&h๊bJv`Y ™&นชสpฆภฉน,ฃหE<จฮFUำนK๛“ศœYศ๓G๊วnd* ฉ —ฯ฿ฐ™ฟ‡\UๅO‘x้Œ๊w'๓eฆ zใแzฤTุGะํ\I7ฒจj:sล*'ๆฒ<~a–แฅย•$สใฝ{ุม0-N.๒O\s๗z ฉ;๗๏์lmพfึฑฆ(|>vmภแp0>5ร๗y๏่ฒทตฉฮvโั(ทI’0M“ชRc!“ๅฬศž้8™\Mบญ›๙่{๎!R(•˜_ZFQU\6”ไฆiโrน่nmมฒ,N ๐'๋;ใ]ๆ๕ฒืvถ๔’N&๘+" tรDืujชJกTฆRฉ 9(ชJ( ต)…S–ษ dry C)@ ฐ+BH ๖Ra‹฿ฝ็:zใatำไฉฑyเ้S๘\N๎์Iณท5NOCˆˆืหQฏญก™&…šฦxฎฤ‰น,รKydว๚ืจh:ฺม๕mIภ้…๙โศ†Œๆ๚‡ศVšB~~๙›h๐นษVUพ|๐mั-!:†fš,–kฤ|nzใแzฤ”ห‰์0-จi:sฅ'WฤิะbŠฬล็’๙ฝ{๖0 c˜ฯŽ/๐๛Ožผๆ๎๛๕R๗ฐoฐญน้šYวrฅJะ๏c๗ึอศฒƒ‰้Yพ๗๐ใx.cบpนRร๏๓ฒ} —พฮv"nWฝXนiRฉี˜_สpntŒ็Žž`9๗ึ๎]›xเฝ๏" R(—˜]XBืuœN› )งLw[gF.๐ๅฏ{]ว‹„ูป} ๛{I%โ|>œฮzM(ะัดบˆสKTชตWี‡RUp0@s*‰Sv’/•ศds่†a‹๓!„”@ \ŠR@€}„Tฬ็ๆท๏MOCอ0yblŽ๚ฬ้W}ฦ้ppkWŠฺ้M„ˆy=xœ$@5-ŠŠฦtพฬฑู,็—๒˜–…cฅk฿U฿ศช:ัลž–8pr.หืฺ2e/WSi๙๙ลฤ|n–ซ*Y๚a’7_Kgนชเuสt7„hV"ฆ๊ลฯkšมBนฦ‰น,O\˜ใฬB๎ฒฮ%่v๒ป๗ผ‰๗๔ลy๓Sงฎน๛~ฝ„ิฝ7ํlmJ]3๋X(–์ูถง,39;วwz ฯeหซ"jืๆ~z:ฺˆ…รx๎zjžaPฉี˜[\โ๔๐(/œ8ฆ#ข^หŽM}<๘พw †(UสLฬฬcYฆ-…”eZศฒƒ๎๖V†.\ไ๊[๋2–T"ฮ๕ทฐนท›ฦx ฟื‡,หX–‰ฆฏˆ(E%[(PSิืํ˜งj‘`€ฆd—ำIฑ\fq9+„”@ ุ!ค๛ฉ„฿รo฿ฝ›ฮXอ0xlt–/=w๖'~~[’ป›่O„i๐{๐ศ2‡„n˜U™Bฝp๖K3หฆyี  ๏๎aWบ€ใณห๕‰ฑ •V๘FษืTZ#>ทฏŸจือrEแKฯŸeGSŒศH]สVUd‡D_"LŠ˜rส๕TพšฆณXQ8=Ÿๅภศ์eSฏ‹฿ฝ๛:zV"๑ž›ใฟ<}๚šป๏ืKHฝ๛ๆ›“ืฬ:f๓Bม๛vlล);™š›็ป=†ห๕ึ๏ใrฅF0เg็ฆ>บ[iˆD^ีmญ\ญฒYๆไะ0‡Oœ&›ฟoฝ๓กiZhบ†ช้ิ…\กˆขjฏ+ขVั4H(@*‘ภํrRชT™[\5คภฦ!%ุGHฅ‚>~๋ฎ]tFƒจ†ม#ร3ทƒ็ม๏ํi‰s[W›’โ/^งŒ,ฑาัMgฆPๅ๘2‡'ัM๋ช‰ฉ‚ข๑ฉ๋zููรŽฮd๘ฮฉq6iใฺนดG๕Dผ.2…/>{†mI|—Aฐ-WdIb กeฅˆ+ป+.”kœ]ศq`d–S๓ูท๕[ พบ๘์nก&ƒf๙โณgฎน๛~ฝ„ิ{nฝi0•ˆ_3๋ธดœ% ฒ็v\N'ำ๓ |๗กวp:฿}\ฎิˆ„ƒl๋๋yED” ึ"ขๆ—2œๆเั“หๅห:—-ฝ|โ๛ˆ†ร”ซFฦ'qสฮŸ*J64–EoG;’$1<>มๅ7ธ๚๗ดทฒg๛๚:๊=w=ฝา2ัดบˆชึjไ %4]C๋ซ๋:‘Pˆฦx ทหEนZcf~Atู#„”@ `!ี๒๓›w๎ค#D1 :?อŸzร฿฿ใๆฮ›b4ผ๘\2ฉžVั JUNฮๅxaj‰’ช]q1Uจฉ|foS1Lเล้%~xfู!ู๎**ฑ doa‹ฅฒย}๖4ทv5!_ฦ”ศลr งรม@ฒ1XํฎhAM7X*ื8ฝใษฑ9Žฮ,ฟฅ฿Hผ๖]ปึ"๑Œฮ๒G?%ฯฎฌ—z๏m๏lŒ7\3๋8ฟ”! rร๎ธœNf๙๎รฝฉ๛ธ\ฉั ณฅท›ž๖6ขแn— Iช‹จrญส์"งG.๐์‹วจTkWd.›zบ๘ไ๗‹D(Wซœวใv!ห๖R†i2ะูไŸไ‹๙ L๓สฝ๎6๕tฑw๛zฺZ‰†C+้•†iขjŠขR]‰ˆ2 ๓M‰>]ื‰†ร$bQBช#ไ7n฿Ak8@U7๘ัูIลแท~ผh[ปS์Nวi๛ื๊ญฆ-Wฮ/x~b‘…R๕ฒ‹ฉ‚ข๑น๋๛ูม0-N.๒๐๙i ฉพD˜๏๊&ไqฑPช๑GฯŸๅถฎ+Mmก\รแ€พx„ฮX๐+ฤิ๊9<ท˜gpt๖ ‹ฉๆฐŸ฿ผใญGโู…๕Rธ๋ถมX$|อฌใไฬัpˆ›ฏฟลb†๏<|€ŸvฏŠจ›๚้lm&z9"JืuJี ณ K=3ฤ‹'ฯPฎVฏส\๚:๙๔KC4JฅVๅฬ๐>฿ซบฝูหดะMƒM8ฦงf๘รฏ}EU/ห๑‰=ถฐk๓ํอMDBA\N’†aฎีˆ*–ห”+ีทZg&ัp†hฏขjŒOฯb!"คภฎ!%ุGHu7„๘ทท๏ 9ไงช|ฬ8๕า่>n*่ใถ๎&ฎoMะ๖๔ธp;$,@ัM–ซ #™/อdฯ– ธ/O฿’ช๑น๋H†1L‹gวxdxฦ–){UMง?แ„x๗ํƒัp่šYว‹S3Dร!nฟฏอา2฿y่ผŽ((Wj$ใ1ถ๖๕ะตๅvีEทn่”+Uf9vfˆร'NQSิซ:—๎๖V>๓ม๗‘ˆลจึjœ—ฬ=i๖ถ$่‡ˆxธ^!ฆŠŠฦลl‰sY†—๒ศoqใQำ >ทฟŸž†0ša๒ไุFfถ่Z`K*ส‡ทuโw9™+U๙ณ#รุ–\—๑ฬ–ชH@"LW,Dฤ๛ฒ\T ƒๅชสะbžgวxf|แU…_‰๗ƒ3|ํฅ‘k๎พ_/!๕ัw5 ๘ฏ™uBjk*สฏฒฆ ’ช๓ญใc|็ิล+๖{N‡ฤ-]MุHoทo€ฎ†z7ทวFgy|tŸหiปkH5Lถฅข|pk>—“ูb…ฏฝ4สพึฤบŽkฆXซ]ื๕บqษ,ซ.ฆฒ5•‘ฅ"O]œใ™‹๕๊๕HผํคC+‰ทQX/!๕ภ}๗ ๚ฝkfฯŽ\  sฯอ7เ๓xXสๆ๘‹๏H0ภพiKงkฉyšฎS,•™š_เลSgy๑ิ™+Rh๛ญะ–N๑๓๙๑5Uๅฤนaย’ ำˆ ร@ี4ถ๔๖เv9™ž_ไ+฿๘6™\ }ฟ)g๏๖ญl๎้ข1€฿๋E–e,หDำuTMGQTฒ…<5E{S๓*>‡ฦD^w]HMอฮc˜BH ]BJ ฐฺัใพyA/EE็วF๙™‰ซ๒๛’D_"L๏ม#ห8บaRRuฆ Žอfxiz4฿Ptอ0๙…tFƒจ†ม#ร3 ^˜ปl5ชฎ&šaฒ#ใ-๘œ23ล ฿8z=-๑ 1พ้b0ูšŠั$บRc  ฆ›dk ฃ™"ฮ’ญชkโณข]นHผ๕fฝ„ิวs๏ ืในfึ๑ิ๙"auหM๘ผ^J• s‹K4D#kQ–ต"ขสeฆ็8r๊ /:‹nj.อฉ$Ÿ๛่I%จฉ*'ฯ  lูhAื๋ัK[๛zึบ้7ฟรBf๙ง~ฏตฉ‘};ทำืูNc<†ืใAvิ›]hš†บ’š—-Qีซ#ขV๑ธ4%โx=jŠยิ<†!„”@ ุ!ค๛ฉอ _๏J2เฅจh|ํฅQ~tn๒ชŽแบ–8ทu5ฑ9!๎๗เu9‘%0,‹ฒj0Sจpr>หกษE4ใง‹)ด๘…}ฏ๊ๆ6xaŽ๐e๎ๆwU6ฆษฎtœ๗nnร็”™*”๙ู๋nุPใœ.TะL“ญฉ(ฑQ_]LI€bิ๋„อ—ชดGƒDผ.Jชฮ_ŸใoN^ผๆ๎๛๕RŸx฿ปWฃ…ฎŽŸ"ัใฝw‚ๅฦฒL ำDvศ€ต51;ฯฑณ๕ฎyMDญ’N&๘ค)GQตต”=; )MืQTm}=๕๎‡Kพ๚อ๏2ปธ๔บŸ๏้hcฯถอ๔uดF๐x8$ฆeึE”ฆQฉ)ไ %4]ฟช"jทหEบ1QBJ lR@€}„ิž–8ฟzำVEใฯ ๓ะ๙้uหถTŒ[บRlKลHฝ๘\2Iยด,*šมBฉสษนGฆ—(*ฺ๋Šฉšn๐/nุL๋J7ทฟšโษฑ9ข^ทํฎ!รฒธฎ9ฮ}ญx2S๙2฿9=ฮŽTlCŽwบPA7M’zใแตˆ)Iช‹BY’p8$jšม<:zESCื‹๕RŸบพAง,_kธธผLตฆ๒ฮฝปH'“8–Uฏ๗ฃ้…R™‹S3?wžOม47๖ฃถ1ภ/>๘!าษชฆqb%BสŽิk;ฉl๋๏ญw?ฬ,๓฿ฟ๕=ฆ็_ฬ`sO{ทoกปญ•h8„วํฦแ0Lณ~ Eฅช(ไ๒E ำ\ตŠ้$Jฎ ฉ้๙… +7_‹R@p)BH ๖R๛’‹7๗{ศีT์…aŒฬฌ๋˜บBั“fGSŒtศOภ-#K†5Mgฉขpv1ฯ “K,Ujkbสด,rU•_ฟm-แz๑์žเ้ฑy๖Kgฒ,‹=- =ะ‚G–™ศ—๙ม™ ถ6F7๔ธง e4รค/a &ๆ]ฉ&IH+็iC=5T5-สІื%ใ‘e$ 4ำขXS].๒ยิFfm)ฆ„๚‡ษdsศฒƒŽ–fา‰KDTฎPโยไลR™ปท)”J|๋Gs๔ฬ9]แ`€‰Ÿฃต)…nิ#ค~{FH-็๒ไ E๎บ้ธ]ฎW›wบa ฏtฬ+”ห”+U6z*ฉ์pะาิธ!5ทธ„ข !%vE)@ ภ>B๊๎f>{}Qฏ›LEแŸ=รแฉฅ =fฏSๆŽž4{[โ๔%ยDVŠg[Vฝ๘j๑lE7๘_ว.๐๔ลyšร๖พณ3ลm]Mธd–‹<>:KOCศv๓x~r‘_~ว&V"๑Œฬ๕นูา%๎๗\"ฆฦseM.๒่ศ eี>bJฉŸ&3 Htทตะ”L๐๙p:e, TM%[(rabŠ#'ฯpfไป6๐ภ{฿E8คX.๓ํ?ย‘“glwํ~>ษŸฃ-„n+Bส~‚<_,‘อ็นn๋ใฑตˆ'ำดะ }ญXyฎXขZซญHฦ์pะ’ชG|ี…นฅ Šชฺb์BH มฅ!%ุGHฝซฟ…ฯ์้#โuฑTV๘โณง92ฑษFBโๆฮ7u4า๓ี‹g;V6J–e1]จr`dš‘ๅ†iฎ?ปpKWŠ[ปšp:Œf |ป‰C”*eพ๓๗8t”ํฎ}ฟืห็?๕อitรเิะ0~ป)หขPช ้D‚dผ€ฯ‡,;ึžฑีšBฅZcนGQดuํ˜๗Vp8ดฎ )Ue~)CMQl1v!คเR„์#คณฉO]ืCศใbฑ\ใๆ4Gg–mท๛Zั“f{SŒ„฿ณ๖ฏ๗๚Šุ˜)T8:›แ่ฬ2šaฎuๆ่ึฤอ)œรKž›˜ง=b?!๕โL†ฯํ๋'๊uณ\Q๘ร็ฮฒPช’x)*1Ÿ‡;’lJFH๘ฝx2‡„f˜u1•/spb‘'ฦๆXฎlอขR/“+qส2m้้ฦ$~Ÿง,ื›h*น•ˆจCวOq~l’๏oํ๋แ๗฿G$ขTฉ๐ท<ฮs/ทต๏๕ธ๙Ÿ|€ŽึfLำไไะ~฿ฦฎiง๋๙b ‡$‘N%H6ฤ๐z<ศ–eญ<_%4]g~)S?ื6Qซ8$ญ้zสžข*ฬ/-Sต’852z๛‡๎ฝ๓ @๐๒๓Q)@ €ฟ๕คตTู๘ิฟฅํ๊!ไqฒPช๑OŸโฤ\ึถ๋๑]=|dGฝx6–…iCชง๒•Uƒูb…“sYN.ฺBLู“ๆฆŽFd‡ฤะbรSKดฺ0๐๘2ŸOฤ๋"SQ๘โณgศืT"^๗ฺgVลิ;ฺ“lIFˆ๊bJ^Iๅ+)ใน2/N/๑ุ่,™ x !ู|E[บ‰ฆdŸื‹์ฑฌบˆสๆ _œเลSg_WDญฒนท›Oฑp˜rตย}‚งตต๏r9๙ยงคซญeร )]7ึ ทค’4D"xฏง\Q5Ue9—g๘โ/œ8อ่ฤิ?xผ๎N>๕ณ๏!‰PฎV๙ัใO๑ฤก#ถป๖eูมฏ|๚ctททb™'ฯเ๓z6ิu RญโrนhJฦ‰†Bxn ร4ฉ) ™,รcใไ‹%๎น๙ยม Šช257nถ}gผJHi*‹™,ๅjuCŽ3๐ใqป๑z~O{+Ÿ๙ะ๛‰GฃTk5z๊Yyๆ -ŸKฟ๒™ัืัŽeYœน€หๅ\ซsท†ฎ8Nใ1"ก .ง IชKชrญสยา2C.21;iึ#  ฅ2ก@€ฟgˆ†ริ…ูล%TMรฎผVHer9Šๅสบหแp๔๛๐yฆeแ$’v6ลhz\ธ ่&ูชยpฆภั™eฦs%.็บฮ็พMญ์iIเNฮgอ‰พข๎’]ธ˜+๑ั]kฉก๐ิi|ฎ7Wนจhx]27ถ7ึ#ฆ^!ฆ ำคฌ๊Lๅ+ผ4“แ๑ัYฆ W๚ว คJๅ ท‹–ฆT=5ฯใมแxนฦP&—g่ยEŸ8ลฤฬ[ฮึf>๛แ๛IฤขT…GŸ9ศ฿?๙ฌ-ŸK_๘๔ƒ๔wv`aqvt ‡$!หWฟธฆ้่†฿๋!ู#เZ)Fฎ้ๅJ…ูล%ฮ3>=ปึMo•ชขโr:๙ไ๗‹DPT•ูล%Uลฮดง›๊BJำXฮๅษK๋& eูAะ๊ˆ(ง,c&ชฆขจีšยb6ห—็_‹.{@๐„เ—pะบซ7อŽฆฉ Ÿห‰ำ!กฏlœg ีต๓dพผnใ'{๚xฯๆ6|N™ฉB™0x‚‹ู’mื๕บ*บyIญ"ร4้KDุัฃ#$์uแrิ7_ši’ฏฉŒfŠœœฯ2’)เ–ืงƒิ๛6ทฑป9Žœ˜ห2‘+t;mw^& e>ผญฟซ.คห3ง๑ฝลฎ\EEรใ”ู฿–`Wบฦ oญF˜aZTดzDโฑูežaๆ*ŠฉkUH้บNพT&๐ำœ&‹^"ขณYฮ_็เฑ“Lฯ/ผํ฿์hN๓ูOฒ!FMQy์นCh๐i[>—>ษ่๎`่ยELำฤๅบzQ˜หน<บnะ˜h )'เ๗แ”๋ฯMื)–หLฬฬ12>มไ์<๎Ÿ โ ำBื๕ตTJES™_ฬุข+Oธm+BJีt–syrลโURk"สํฦ๋๕เvน ำDำ4UฃRSศๅ hบŽํโฟล7„‚ื>ื…ธ็ฯฑบbA๎๊mfWบTจพqฎื0ชw}›.”96ปฬc#๋#ฆ้๕ฬ@+^งฬdพฬ๏<~|]ูๅ•]WSร’๔k)บAo<ฬึT”พx˜จฯฝ๖Yอ0)(น2ว็–^*ผกณหษ๛ทดณ+ภ๑ูeๆJUผฒฺซฯซ|`k๛Jjh…/>wฯœGQัp:$nhodG:F:ไฟDLอซผ8“แภศ,SWแบพึ„ิโ™\žŽๆ4]ฤcผžWคๆ) ‹หYฮ]ธศแใง.‹ˆZฅต)ล?่hŒวจฉ*ƒฯฟภ{า–ฯฅ‰ŸcSO'Ccั4็สG:ๆ‹%jŠJsc‚ฦDŸoฅะƒ๙RuEฮ0v#ฏ!5ทธฤR†žถVบ;IฤขxW"ข ำ ZSศdsœใะ๑“ฬ.,]๖y57&๙ฯ}Tขšช๒ไก๙ฃƒถ|.๒ว?ย–n$$†/ŽSU|^๏•๙1หขPฎ ้:้D|ญะผ,หX–‰ขึEิ๘๔ '†ฮ“ษ๘฿๘XTM็๗฿G"Eัด •๎ o\^QCJีtr…™\‡รqๅ~ิฒe™P0€ฯใมํvฝ*"Jี4jŠŠขจ”*etร|ร!%ฏ๓\BJ .RซดGีำฬฮ๔kปพYฏฺ8?:2ร๘UH๛g๏ุฤ=}อธe™‹นฟuเ๓%๛n.ุูล‡^™๖๔›ซUTT4ƒ>nhOาŸจ‹)ฏSฦแะ_Q@๛ุ\†ฃำหจ†yE  pkW„ิ‹ำr5{ ฉLEyUj่<‡๛2o๘ŠŠ†[vp}k=•ฏ)ไ#เvฎl๒^Ž˜:>ปฬใฃณWคVš…ิโ๓™ez่๋jฏ‹(ทI’0M“๊JDิ™‘ /ต„ใภป๏ผ•ถhบi’Hฅษๆ๋ทอ[Bขซฝฟื‡i™ค29โฉิІฮ›ฆ…K–hŒDฮQฒ,cYZ5ฌผฌiไ E,~M๏+„”@ ผฬบ.„”@ ผบZข+์็ๆvvF้๛(nฎJEว…|p^โSืnaฯ๊v—ฬh2หง"ฉR๎˜๔ั๋ธ๛ฬJœgฟก@๒œfTvwGhkXฮ[jท, …2Gb)ฬ$ศ”๕Sฒ$q฿ภ*ถด5`9ฐwj‘xAซหP๓œnœี๚ู็Oโv]๘J/ล%ณน5ยๆึFบ#~หb๊๔ุšK๒๘XŒกลฬผzRฑล8๑dšuซ{้_ีKSค*3ชส%ญLl1มเศ{#~+ขฮฅน!ยo}เ=tถถ`˜&ฯพxˆ๙ัฯ๊r]๚๘๏bฦuศฒฬ๘ิ ษL†p0๘†%Gฑ\Fqปioiฆ!ยฃจศีVีRYc1‘dxbŠมแQ4xC"j วqธ๏Ž[ioiฦ0L้ ™|n„!IญQ>?ฆe‘ฬdHคา+"ค*"Jฆฑ!Œฯใมซช(Šฒ\qจ:eM_Q๖๋|†BJ ^f]BJ ^ปZข5่ๅ๖u]์์jฎด๒QัQ6Lb๙Gbic(žYฑใฃ๋ธ~unYf$‘ๅ?=Yอจ๋~nH๛?>w๗ ด^ไ4ฅฺถญฝ‘ฎฐฟา&IX”M‹Dกฬ‰ล ฯOว‰สoXLนe‰๛๚ุิมฒž›Zd!_ฆมซึธ “ึuข, ฉ!—|ั>฿ใ’Yืak[‘ภYโทl˜,สO๓ศศ,'€˜ช![Œ“Lg่๏๋emoM aผชŠ$UDTฑ\b!‘โ่ษ๖>vQ*ขฮฅ!โw>x?]mญฆษCG๘๊~Z—๋าฏฟ็ถoZ,หœšž%žL ‡ฮ[rhš†ชชดE›ˆ„‚จŠŠ$Igศฤ$ใำณ่บผ‚ีˆ–es฿ทาูล0M’้,้\ŽzE’$:ขอ~,ห&™ฃRE IDATฮOฅpปฯ_›ฆ…%ำ ใ๓z๑( nลฝ\qXฎถๅiบ~^"j !คเeึu!คเ๕ ฉ%Zƒ^nํ๏ไ๒ฮfบ#‚๊้ŠŽrตขใp,ลใcs_xใb๊฿]?ภต}mธe‰“๑,๚๐ tณnฏ๛น!ํ+]‰“ำ \ฒฬๅMหํ–!Uมํ’q‡ฒi‘,jœŒgynj‘XฎtbJuษ;ะวฦ–0–ํ๐ฬdๅข~O‹fYgต†~๖๙!T๗ลo=T\2๋ฃaถต75vถํP2-๒%Ž-คytdŽม…ื/aj]Hลใคฒ9ึ๖vำฟช‡ฆHชR5ฌผาšwdh˜็ฝคข! ๐ปฟ๖^บ0-“}‡๑ๅ๏ธ.ืฅ๗vlˆห%393G,ž 1~]๏aY6ฆeโvนi‹6PJ๕฿, ฅ๓๑CใLอฮc;ึ9หฒน๗Ž[่lmมด,R™ ฉl )Y’hmn" `6‰ิ๙ )ำดpป]4E*Qช[AQ”ำญyบNIำชQฅ๓QK!%/E)@ เ…ิmA7ฎigwwtYLYัฑXิ8:Ÿ:๏็%รžm\ำ‚K–8ฑ˜ๅ?์eำช๋พา~ก+qlวA’$6D#์่hค+ ไQ–s‘4ำ&UึŽg94—b<•วฏผ>ใqปธo`๋ฃaLแ้‰fณEฺƒพบำq–[Cว’9>ทw๛าeaษ’ฤ๚h˜MtEUท,แTซ*S)ž‹q$๖ฺิjUHลใไ๒๚zบ่๏ํก!Ri๏’คŠˆ*–สฬ-ฦๅ้‡j"ค:เ๗๑{z/ฝ˜–ลฃƒ|๑;?ฌหu้ร๏บ››qป\Lฮอ1;ฟHSCไ5ฝึ0MLหย๏๕าาุ@0@ฉฮรด(‹ฬ.ฤ99>มไ์ ใ>๋x ‹{๏ผ™๎ถ6,"•ษ’ฬdฉW$ ตน‰p(ˆmฤSiโฉ4ส๋RgŠ(ฏg)#JA’dlB7Ltร —//•Xฉg%!คเeึu!คเ ฉ%Z^n\ำฮ•=-t…„0๚7๗ฌขฟ9Œi<9>ฯLถ@w8PWcb;Hpร๊๖ๅึะฯํยง\๚,,วqุิฺภึ๖Fz#‚žŠ˜ฒซb*^(sl>อSงๆya6๑๊็ZcBjID๕๗๕ฒบง‹†PZษฐ1ซU5s๓‹e๏กฃ5Nํ๓z๘ฝฎ,หๆลม|แ฿ฏหu้C๗ผ][7ใvน™Šล˜ž›งนฑแWพ&•ษb&mั&ฺZš ๘|ธ]•9c˜&นBษู9†OM2=ท€z‘ฒๅtเ;nกงฃหถHgs$า๊วqhmnข!ยqS)โษŠ๒๊•ญฆiก*nย!|^/ชข *n ’eZบก“ษ.ˆไBJ ^ŠR@ภส ฉ%ผ*ทฎ๋ไŠ๎(=‘j5ฮREวbตขใใ๓šKพๆ๗๔Mูำ‚ .ค๙w žื๑?ผv 7,…ด'ฒ|v๏I|สลฉฤัL‹5M!ถถ7ฒฎ9LƒO]–O†e“ำ &ำฦ’ŒฤsHฏาITผk`k›ย–อ/ฦcLฆ ฌn ึี˜่–ว-Ÿี๚O๛NโWj+œ}]4ฬถถFV5—ซ–ฤTขจq|1อใฃฑ_)ฆjEH-‰จuซWัืIc8ดœ3dZ&…b‰นล8‡ŽŸd‘Ar…ฺ%อฃ*|๒ร๏gUw'ถmsppˆ๓ญ๏ีๅบ๔มwลpปLฯฯ393Gดฉ๑e6›/ iญ-ด47.‹(วqะ ƒl>ฯไlŒcรฃฤ๘}ท…ทฌ๋{๛-ฌ๊์ภฒ-2น<๑K1ถRุถMKS#M‘HEH%S,ฆRจฟBH™ฆ…ช*ๅ๑ * Š] +wlLำDำuฒ๙"๙BW]์ฯ!คเฅ!%ฌผZ"์Qธ}};;›—œ—*:ดฅŠŽ…4Ožš็…™Wฏ่xเ–์์Š"GๆS๛‡ิ๕uใ๋ธฎฏา>ฯ๒น}C]|ไu“?ปบข๔7‡i๒ฉx.$IZSณู"‡็S -d0l๙eXB…{ทฌbuSรฒy|lŽSฉ<๋šรu5&eำ" บyหชV\ฒฤะbEHjqท@ึ4‡ธฌณ‰† a‚rF>Xผ 1ด˜แััน—S—ZHลใหeึ๔tณบป‹†pจฺ:Tyˆฮ—Šฤโ<~’ฝ‡ŽR,—k๖พqป]มG>ภ๊ž.lๆ๐‰a้฿ฉหu้oฟ“+ทoEqป™™_เิ๔,-อg)ว![(b˜&ัfZฃM๘<^\.Žcฃ้้\މ™9Ÿ8I2]‘๓ฮ‡bYใพofUw'Žm“ษXLฅจW,ห"ฺุHดฑ‡…dŠx"…ชพTH-UD5V3ขwฅ"ชา๚zZDer ฅา?v!คเฅ!%\8!ตDƒWๅฆต\ั}ลŠŽ‹ๅลูWฎ˜๚‹[/ใฒฮf$เP,ลY} ฉรึsฤวUน$ว’ำ Zƒ>ฎ๊‰ฒ>กู๏ม๋v!หฆeS0Lf2Eฦผ8“Dท์ณะ#^•wm้ฅฏ1„aY<2:วx2ฯฆ–H]I^7i๒ซgต†~~0มZRKฉถอฺๆ0;;›้m๒ชจฒ„CU5N,dx๒ิ<ฯO-.ฟ๎R ฉ‰™Y๚บ:YำE$ชถQiอ+–˜™_ไศะ0ฯฎ่iม%มฑ๙4g๐%—ื‚nูlˆ†ูัD_cฅbส]อำญฅVพ ฯL,๐๔ฤย%R๐ตo๏ู=ฐ้๑U]„ƒมๅ หฒศ‹Lฮล8zr”็Fำบบw>๕ัะฟชวq862ส?~๕[uน.ฝ๛ฎ[นv็TEav!ฮ่ฤ$ถใเ๗y้jkฅ1ฦฃชห"Jำtโฉ4#SฅT*_rตDพXโ]ทฤฺว!W(‹'๊VHฆIs$Bkด ‰…d’…xGล4-ผ•H(ˆ฿๋EQ”j |ED™ี๓2ู<…b Iพธื@)@ x)BH OH-แW฿ม5ฝญฌjจ๎๘ๆ’qœำฮƒ ž:งขใฟพ“mํ8ภ 3 >ศ‹u}ฯอฤ๚ง}รDผต!>ršAPUุีฬ@[#ํ!3ฤTษจd‰ฅ80“ มง๒ฮอฝฌjขYœa$‘ใฒช@ฌ%H€•ึะฃ๓iพp >„ิšiฑ>ak{#อกŠ๘ญfธ้–Eฒค3ฯ๒ฤุrูE}@\H$๗DBมว+KืEfๆx๑ุ ฌ;ตฤ'?๒~ึ๗ญยมแ๘ศ8•oิๅy{ว-\ท๋2<ชB*“er.F{4J$ฤฃจศฒŒe[”ส‹‰$'OM28<†n5#ข–ศKผ๓ึYทช‡\กาzฑeฬJก๋ a:ขQ$Ib!‘d!‘$เ๗ำโ๓xฮQT[๓ช"*—งP,"ษ๒%9v!คเฅ!%\|!ต„OqsKW๖ดฐ๚WTt<=ฑภณ ๕ปhkภLวyเัƒu}ธeปบขHT2ฑพฐ„ฐทถฤGN3pหWtทฐญฃ‘ฎฐŸ€๊ฦ%หXถSmน,3•.ฐ.&๊๗R6-~24อษx–+บฃu5&‹ล2kC\Ui =K๑ๅGk3C๊UะL‹พฦ ปปฃ๔5i๐V‚๋+ญ|6ษ’vcWุQวู<ฎ&๙B™๙EdัALำช๋๙{zึฌ`h์๓KR—็qฯm7qำีปQ –eaูึ้–/หขX.ฑH121ษ๘๔ บn"ืจเ)–สผํฆู๋ฐบ‡|กฤ์ย๒%’2oxN๋: แ]ญญHฒD6Wภq์สŽyชŠRอณ,ร4)k™|ฅ"๊RŸณR@๐R„.Zย๋vqsWvทฐถZักV3ฆ–*:FYV5้Ž๘ฑุ;ตศ_ฟo˜'วcิ๋Jืw์dk[E|˜I๐อ#ใuU‰cฺ๖้ฌขฆ>u9,ุดmE๑dž‘Dh๚jœ&3.๋lZ—3qพst๕ฆ™๏Eรค'dggำ7ฌiฟจˆณฟ#;[–฿็ฅ!ฤใ๑ ธ]ธ].$I^ฎŽ*keๆใI๒ลbอK6!คเฅ!%ิฎZย-Kนก›\Oะฃ,WIูถƒnูdส:ฃษฟ<5ฯ/ฦ็1ํฺorห2ํŽlj`ูฯM-๒รใSu[‰“ื ไ๚ญด‡|ุŽCAทP]žjศฎaูไ5ƒ™l‘แD–‚fา๐ ิุ_๓ว’9ฎ^ีสๆึ–ฯO.๒“กi\uบ+ื+1—+2™ส฿๘ˆR+wn๏น‡ํ›ึ#ห2งฆg๙ฬƒ_ล0ฬš9พฮึvmฬฦตซimnฤ็๑โrนpM7H็rLLฯbZ—mˆฯ๋%‘N๓…>Z—cbšoูนƒ›7, ฉุ้|MgHY–…ฯ๋ฅ1ฦซชธ๎ๅ]๓tร\1‰D:อ|~๋e๔7‡pะ, Y’–ย™ัชbj,™็๑ฑ9~yjพฆ+ฆผn๕๖lh cูOO,๐ำ“3u[‰S4L๘๚ฺƒ>๒บษำ ธe‰ ัอ~^ท Y–0-›‚a2›-rh.ลX*GGะGO$P็1’ศr๊v6VวๅูษE~6<ณ\™๗f!–+1‘ส !ต‚|์พwฐc๓F\.™‰™9๎‹_ฃฌ้—ธVuupลถ๚๛zˆ66,W?ูŽฎ$3Yฦ&ง8p๔8'ฦNqำีปy๋ืแ๗๚Hฆำ<๘ึeปTชŒฎฺฑ•หถlยํr‘/kVHูถ฿๋%แ๕จ(n7n— วก’ฅ่†AฉT&ฺิˆโv“ฮๆˆงRหู~ตŠใ8!คเ%!%ิ‡Šผ๙-;่k aXว2” “ตอ!ฝr๏นผ*>&f็๘Ÿ_๚:ลR๙’ฯ๚ีซุ9ฐ‰U=4FยxTuYDišN<•fxb’‡ŸžY~ž+w๑ถ›ฎ'เ๓‘สd๘าw„ปN+7maืึอ์ฺบทห]ูe/6TCBสถm>แPฏวƒโvใ’]€ƒaZฆฆ้คณ9rล"^J_W'ชขษ็Iค2ฆYำใเุใ‹BH มน!%ิ‡j ๚๘ฯท์`UCอฒxxx–ื๖ตr]_๋šร4๚TT— Iชdฅห:ฃ‰{งใ<::‡VCหGผ*y๋eฌmcX6OŽวxbอ‰ล อ~ฯ%S'YnZำqZŽฯ๓ฤx์M7็ eฦBHญ$บ็mหโc*ใ}้ไ …‹~›๛ืฐ{Vww ๑(*ฒ,cูฅฒฦB"ษะุ)๖df~แ%ฏฟnืeผใึ=|~Rู,_๋V”;์ุผ+ทT„TฉศฬR œm>B!TUฉŠจŠ([QฅฒF&—งฌiธ\.4]ว๏๕าูŽช(ไ EๆI,หช้qฐm›ฟ๙โื…‚sBJ จ!ี๖๓้›wะ  Y?šแณ{‡*‹9pm_W๗ถฐฉตฆช˜‚สno™ฒมฉtžg'xtdŽr ˆฉfฟ‡?ฟๅ2V7…0,›วF็xfrกn๏!หq๘ิ[6ำ๐’ี F9 ห:+หด$ฉr๎AUมงธ๐).\ฒŒe;”M‹Dฑฬะb–ฃ๓)ผ๊ESC๑ ทฎ๋dmSEb<ฦSงๆ฿ts>^(3*„ิŠ๒มwลU๑1=?ฯ?|๙›คsน‹๖๙;6m`ืึอ๔vถ …PI’0-“bฉฬB"ษเศ๛ ฒHพโ๛\s๙v๎นํ&‚~?้l–ฏ|'ิsว๊ึ ๋ธjว6Tล]mู[X ๔Rเุ6~Ÿ†pZiอsนd ำฤ0 สšF*›ฃฌ้gUง้บ฿็ฅปฝ ช/•˜-โิ๘^ณ–e๓™/ !%็"„”@ PBชท!ภŸธ๎H€ฒi๑ใกi>ฟ๏ไK~๎สž๖ฌiฏfฉ•Pm@ทฒe‰t_žš็๑ฑฅK8๔๒ภอ—ฑบ1ˆnY|dŽ็ง๋๚>๚ไ5›‰tr†3‰บฝ‡dIโ“ืlขษ๏!]ึ™Hะ-ล๕ซ โQ จ.ผŠฟ…ฒToVฺ.‡ใYF’Y\’DgศAฯใ๘b†ป6tำืฤฐ,™ใน:…/Gฒจ1,„ิŠr[o็šหทก* ณ ‹ใWฟE<•พ Ÿๅ๕xธjวVถฌ_KW[+Aฟy'6รดศ‹ฬฮ/r๔ไฯ:Bฉฌฝๆ๗ตu3๏น๋6Bู|žฏ๐!Lหฌqูฐบ๋v_^ฉ(*–^ถM๑‚โ8~ยม^Oeื<—\‘๏บab˜fต"*‹ฆฟ2ฏห4MBมญMMx=*%Mgj6V๓Rฆi๒ท_†R@pBH ๕!ค๚›C‡=่ ๙)&฿œไห/Žพ๊๋vwGูณบญš|ี$0l‡ฌf0žฬฑ&ฮ##sUL๕DูM้ฉV|dhšƒsษบฝ‡—ฬ๏^ฝ‰&ŸJบค3•) Y6๎ื˜ีโ8๖T๒ฅŠฟ๊FYสSฑ+;(žJๅNdqh๚.ศy .ฆน{cฯYYe๛ฆใoบ9Ÿ*้œ\L !ต‚ผ๛ฮ[นvืTEan1ฮฺทek๙ูฝm36ฌฃญฅ™€ฯ‡ๅฎฬำ$—ฯ39ใศะ๛;ฏฐ๋ห6oไฝw฿N8$[ศ๓=Œn่u;.ซzนแสxU•Bฑฤ๔ERŽใ๒๛ ‡‚xTทห\QKญy%M#อฝbEิน˜ฆI$ขน1‚ฯใAำ &f็จ๕็0๘Ÿ_๙ฆR@pBH ๕!คึGร๛ถั๒Q4L๕่_;4๖š_ฟป;สต}mln๕{๑œ!ฆršมd:ฯฉ8ฬ’ฟbชฏ1ศŸธ๎p€’i๑รใSOีํ=ไuป๘ํซ6า่SI•tฆ3• ฉื†lู!BƒWลงธ๑*๒i1eูไ4ƒฉL‘กxวจ฿ณข็qd>ล=[V•U๖ยlโM7็ำeก!คV’wvื_ฑช‹'๘ื•นล•‘™ญอM์ฺบ™อkhmnย๏๓โvนซU6™\ŽษูŽ๒โเะ๚ฌํื๓ท฿I8$W(๐ญŸœRน\ทใฒบป‹›ฎพฏง"คfๆ/|ๆRภ็#ฒ$ขฮฉˆา ƒRนL:›C7ฬืตƒกeY„‚Z๐zฝ่†ฮฤฬv?ฯhบฮ๚๊ท„‚sBJ จ!ตฉ5ยŸ\ฟ•๖ผn๒อรใ|๓ศฉื>;:šุณฆ-ญ Dณ*ฆršมtฆภณ“‹<6:Gบ|แช^ฎโ๋ฤbฆn๏ก€๊ๆWl มง’.WŸi;œ๏fVฆๅเW]D^|Š …๊’‘$ รฒษkณน"ร๑y ู๏YWo„}3q>ฐ}อrVูNLq8–zำอ๙lูเ๘BJฉไท์aฯUป๐ช*๓‰$๔/฿yรํam-์บ… k๚hmnฤ็๑โrนฐmอะษไ๒œšže฿แc]‘๓ุบกŸผใ."ม๙bo?๔(…bฑnวฅงฃ[ฏฝ ŸวKกTษบฟ๐$$~แ`UQP7ฒ์ยq์ำ"JำHฅณๆ๋QKX–Mะ๏ฃฅz/ิ‹*—5๋฿BJ ฮ!„”@ ิ‡hkเฏ฿J[ะKN3๙๚ก1พslโบฺนym›[hYSฒ„น\…Sเ๙ฉ8OŒอ/j+~>ขไ†ญt†}t“o=ลH"Wท๗Pุฃ๐๑+ึำเUษ”*]ถใผแ์`ำr๐ธeZ^ชีUSฎ๊X “ูl‘รฑcษํA฿ @ๅฤซŸBj%น๛ฆ๋—+q)>อ๏25;ฏ๗๊๋๎d๗ึ-๔๗๕ะาุˆวฃ"K2ถcฃ้:ฉLŽัษ)=ฮะุฉ=-๋ึ๒มwEC8LพXไป?F6Ÿฏq้lkๅŽ๋ฎม็๕R(Uvู[ั‡ $‚Uล๏๕เQ=ธ\2ถ] +ื “RนL2“ล4ญ๓QKุี๚–ไรฮ@‘ IDATคฆ๋Lฮลฐํฺ/–Jใฟ|G)@ 8๗wˆR@PBj{G๖ฺ-ดฝไ4ƒฏใ๛ƒ“o๘}ฺธym'[ฺNWLน$0m‡œn0•.ฐ&มฃฃsฤ +ืถฒนตwภrลื7s*Uฟ}>•ณk=ฏBบคs*ฝฒ็bZช[ฆู๏! ธ๑ธ]x2ฒ$a;Eรb.Wไh,อ๑ล ก๓SŽฮ๒;WozำTฎฝyเXLฉ•ไฎ=ืrห[ฎฤ็๑ฐ˜L๓ฯ฿๚งff_ื{lXำวฮMฌํํก1ยฃž!ข4ลTŠ‘SS์;rŒSำณไ<6๕ฏแื๙Vรa ฅ"฿๙คฒูบ—ถๆf๎บ๑Z^ลR‰ฉุส์J'ก`ชโ๕จxT—\5ฯ0ะชญyฉl๎ ‹จ%วม๋Qi‹6/ ฉฉนV ฉ|ฑศgฟ๑]!คเ฿%BH A}ฉห;›๙ิต›i xษj_|a„Ÿ˜^ฑ๗hkเ†ีํlmoค5เลซธ‘ซb*ฏLgŠผ0“เกแ’+P1ตตฝ‘?บn`นโ๋k‡F™ฮิo[LKภหGv๖๖(คซไำrpษั€ฟโฎไL!ฆJ†ลbกฬฑ…4'24๛=ฏKLth†?ผnหYYeร‰์›nฮt“ฃฑคR+ศํื]อํีJœx*ลพ}ฦฆf^ำkทฌ[ห๎m[่๋๎$ โUU$Iฦฒ-Jๅ2 ‰Ccงุwไณ๓vืวk๚๘ะ=oฃ1กP*๑ฃวž$žช฿ถีๆ†๎พ๙>ลr‰ฉน7&คdI"๐ใ๕x๐จj5ฐUฉˆชŠจbนL*“ลฒ์Qห8ชขะฺR 5ื˜ŠอcYต-คr๙Ÿ๛ึ๗„‚sBJ จ!ตป;ส'ฏูL4เ!S6๘็รlxfล?gcK„›ึvฐตฝ‘ถช˜rU3ฆ zฅ=l฿tœGFgYศŸลิŽŽ&ํu[h T*พพ๔ย(ฑ|ฉn๏ก๖]ถ–G![6Kๆ*%ำreh๖yจ >ล…Oqแ’+ญ2%ำ"YิZฬpt>Eฤซพช˜า-›‡Gf^’U6^ว•kฏDั092'„ิJrห[ฎไฮ‚฿๋#‘N๓เฟ€‘‰ฉ_๙šห6od็ภ&z;;ˆ„‚จŠ‚$I˜–IฑTf!‘dpdŒGW|วพWb๊U|๘]wำ‰P,—๘๑ใO]ดฯพDB!y๋~Jๅ2“็ูF้’e~^งRฅจธ.,หฎŠ(bน’eู+,ขฮภํrัีึ‚ืใฅฌkฬฤ0-ซฆว “ห๑๙o@)@ 8!ค€๚RW๕ถ๐๛Woขษ๏!]ึ๙“<6:wม>oC4ยอ ด5าฌˆ)ท\ ิ^ส-:Pmๅ›อพสฆ]]อม[ถ, ถ/&qฒช.]a?ุฑ–ว]Rฉ‹—‡%KŠ_uแuป๐)nWeW+อดHuFYาxฎWSษ’ฦ๓S‹ั๕ด}ไ4“9<ฦdบ๐ฆ›๓%รโ๐\Bฉไฦซv๓ึฏ#เ๓‘ฬd๘โw~ศษ๑—ๆ)Š›[ท0ฐพŸUํ„‚ท€i™J%ๆa๏แฃd๓๗[ปช‡๛vš(•หไฟ$ถBป^ ~?๗q3A€RนฬTlวถyญw.Y&่๗แ๑xชUQ .น,ฏ:บaP,iค2,น`"j๙x\2mmx=สบฦ์"†iึ๔ค2Y๙;?BJ ฮA)@  >„ิต}m๖Ui๒ฉคK:๐ žŸฟเŸ฿ๆ–ถต7ั๔โWธd หถ)่&3U1๕๘ุ๋jนปชท…฿ปzอUม๖O{O’ีŒบฝ‡zผo๛‚ช›LYg,•ฟRฏHุฃโฏVK๙ซb @3mาeแx–ัdY‚ฮฌืNe _ฬœ•U๖ีƒcฬd‹oบ9ฏ™g…ZIฎ฿}9oฟๅ>?ฉL†/}๏วœ_wŸืร•ท2ฐพŸฮถ‚~?JU^ฆEพXdf~c'Gy๎เสฺฅิkzบ๘่}๏ ฺุ@Iำ๘ูSฯ2›ฏq๑z<ผ็ฎ”ด23ฑ ำD~•]9]ฒL0เฏfDUDิRž—ahzฅ5/ษ]ะŠจ—;ฎฎ๖V|ี ฉน๙E๔R‰t†ฟ๛#!คเ„๊CHฐบO\นFŸJฒค๓๗ฯ็้‰…‹๖๙kšBผถƒMด…|๘ืrnั’˜:8—ไแแูืT1u]_ฟu†`๛ว็‡(fCkšBผgk~ลMVซTHI—่XBžJ_@qใW(ี‡OรถษT3ฎFYlฺƒ>Ž/f˜ษ๘รkทœ•U๖FZ3kฒyq&.„ิ ๒–;–[ราู,_๙O86-ขสšNYืษๅ X–ลJ๔ur–า4ๆใ่Fm1c1™ไK฿ฉR@pBH ๕!คn^มวwฏงมง’,jณวynr๑ขG_c[๚;ูHGุฟ,ฆ,กh˜ฤr%^˜M๒๓‘Yฆ3ฏjณgM;ฟyลiม๖ฟž=ŽQใมดฟŠuอa๎X…_q“ั N]เ ฉื‚e;= ^Ÿโฦใ–QซS†e“ำMฆ3N,fศ”uEผfœีJ๙ฯ†W$ฤพึ0,›„ZQฎฺฑ•{ซญa™\Ž?ก`€อkhmnZQŽใ ™\Žษู๛Žใะ๑“5s=ํ|{hijคฌ้<๚์^NMฯิํธศ’ฬ๛฿q'‘`ˆ’Vfn!Nฉ\ฦํv/ŒiZธd™†Hฟื‹ช*จสูญyeญ๒_พXผค™Mฒ$ัำัถœ![Œฃ้ต-คๆใ พ๒ร‡„‚sBJ จ!uบNอฎ๕Dผ ‰ขฦgžd฿๔ฅห5้k rำšvt6ั๖Ÿำสg1Ÿ/qp.ษฃ#ณ/Š}K'ฟพ{ Š`๛gŽcื๑๏ค-๎ู‹Oq“ีtฦ’๙‹]8๐Š˜–ƒ_u๕{๑).ฒณŸฐGaฑPๆožไ…™ฤ%?ฎU AnZมๅMด‡|T7.Y>ซb๊ะ\’วF็Mž๚พ}}นŽˆW!^ะ๘g๋๚ฺาฺภ7๗โsปศhใษ\อฉ%Lหมใ–i x๑ซnTWEL™ –ี ข~^ท‹ิ› •๒•ฐ‡S‹BHญ w\ wํนUQ‡สwL ฑัtT&หศฤŽูฐ๓Zกณต…฿x๏ฝดE›ะtƒ_์=ภ๐ฉ‰บำฒ๙ะ;฿Jc$BกT$ถ P*ก(nB!|^>ฏUQ‘$ฉ* 4]งฌiไ ElปvชWeIขปฝ ŸืKYืYˆ'(iต]ล9=7ฯ7zD)@ 8!คธ้Ÿ~ภe๓’LคV๑๎M=|่ฒต„ชB๊ฟ?uŒƒsตณygศฯ-๋:ุูฅ3์[ฎ˜ฒ(&sน‡cIฉˆฉทn์ๆร—Ÿlใ—วpฟJศn-ณตฝ‘ป7๖เuปศh:ใ—(ิต= :จn™fฟ‡€โฦใvแqหศ’„ใ€,’Dูฐ๘๚ก1ฮ% y”7ีœท‡}BHญื๔ฑs`[ึญฅฉ!‚T5ฑถmS,—‰งา Oฒ๏ศ1&fj?‹ฉ-ฺฬ'wํ-อhบมS๛_dhlผnวG7L>ฎปiŠD(–KLฬฤdhŽD–CหeI^ฎ`+k:Z5#ชซVฯRšฎฑORฌa!U*k<ฝะ??ง>๐@Z|ใ‚ำ!%U๖<๘Dƒา?#K|ธ๏ž-ฝผ๛ZB7๓๙2฿SG9Kีร\ะวํ๋;ูััLwฤO`YL9” ‹๙|™รฑ$–ํpบ.B7 ี๓๑\ค]š.;:šธkC๗i!UC-{ฏ„i9ธd‰hภƒฟ*ฆ–ฦ ภq e๖Mวู? YาTb๊๙ษ!ค[ึญๅŠm[XีIC(Tg;‹ษ๛c‘Af๋ๆผZ››๘อ๗Ggk0๘ๅƒซq*i:ฝ๗ํD0-ซRๅvใU=gดๆ้”สšฎ“/–jช"๊\ฮnูำYH&)–joใ…RYc๘ิฤใ?๕์ว๗_?pJ|ห‚—"„”@ œรž๊s[๒ต&ฆฝต๛ทญ&จบ‰ๅK?ฟ8สเBํฑต#ไใฆต์์jฆ; xF+_ษ0ั-›GA‘%ๆ๒%฿'โWu{฿์์jๆŽ๕]x\.2ๅj…”TวnZH๖(Dผ*ํA๏้*—ชHL5†โž›\dฑP~Sˆ)!คฮใ‹ฃ—mศฮอ๔tด QI’ฐl Yชd“้†ฮOž๘%=๙Lcscฟ๕wำีึ‚n˜<๛โ!Žžฉห๑*หtถต๐๎;oล๋๑Tฏƒ$I˜ฆEYื—eTกXฌ‹?‰Jจนฯ๋E3t) ฅRอŸQ@๐:ึt!คเๅฉ51๕ํซy๗@ีอ\ฎฤ_โC‹™šฟŽํ!7ฎigww ]a?Aีโ’+๙2U้QิM>ปwˆSฉ|ŠŽQn_ื‰๊ชŸ ฉs1ญŠ,ผขงฏโยqlวม%WฦK3-Eัd–}ำqฆา‚u,ฆ„zํ(Š›+ถ 0ฐ~-ฝํ„‚A”๊.mฆeR(•ศๅ‹D๐z<JE~๐ศ/xr฿ uw_4Fยฮ฿Cgk+†i๒มรฎซs(ห๘>ถm่gsZšฯjฅ,”JhบAYำศJ8ิฯ๓ภi!ๅAำ โฉ4๙b๑’Wฉฌ18:ถ๗—ฯ์ฝ_ˆ(@ xkบR@๐ซนํมŸ๏ภv>p)ใƒ;ึ๒ฎ-•]ๆrEหGId๋ๆ:Fn๎๏ไสž(a?zVkุlฎฤ™ฯO-’ำŒบSW๕ดpKŠหEถFCอ_ ฆํฐ>&์Q(๊&ฑ|‰ฏZฉfsU2พtห&UาId9K1žศแQ๊ฏRฉWว็๕pีŽm ฌ_Kgk ฟฅฺZk˜๙B้๙Ž%™ษ๐ทAS$BกTโว?ลใฯํซป๛" ๒;ฟv?mm˜–ษCG9x|จ.ŽฝP, Xฟ–U=4FยxชปๆIReญMฆ3,&ST3็๋๏แ่้hฏ)ร ‘สห็นT nฉฌqth๘่“/๚=Z.ฏsMBJ ^ท|ก=ฒ,?ภ%Sนผyท™l‘๒ฤaฦฮุตฎn๖ผ wฎ๏ๆญปi TZรภฒสฆลbกฬั๙๛งค๊(ณ่-ซZนqMŠK&[g-{gโ8ะ฿"ไQXศ—y|,FkะKณ฿CGศGฤซขTร็ &[68•ฮs$–โd๑4<๓|อP ภ๏~่~zฺ1-“Gyแุ๑š>ๆBฑL8`†uฌํํ!VE”„eูศฒ„$ษ˜–ษ‹ƒ'P ^Zทฟ{ซBJ7L้4™\~น์b!D”@ ผq„‚ืษฅSตnyท้Lฟ|0้|^ว฿ฝzwฌ๏Bqษุvฅ5ฬ-KX”M‹DฑฬเB%ณจฤิu}mฐบฝ"ค๊ดe*bp}4BศSษ*{dx–ๆ0ฒ,aชหEgฤGฃืƒวฝ$ฆršมtฆภมน$'38Tย‡k!ค^J[ด‰][ทฐน ญอ๘ฝๅ8บก“ษๅ™œฑ๗๐QŸ8ปmMOฝ๏D)•ห์ฉg๘ูSฯึ๘|‡฿KoGฆeqเ่ Žึไฑ.‰จ›6ฐบป‹†pช,หงBฉD2•กฉ1B8@7 NŽO`;ตŽ…Tg;>OEH%3า™’|qึ›RYใภเ‰…็ฝ_ˆ(@ xc!%็ษm๓ุŽ๓€,ฑ๊b|o\ฑž;ืWvq›ฬ๘‹ว2)ึํ๕๛ฤ•–Cภำe๙|‰ถ oน5ฬฎVLล‹eN,fxfขถลิ ซน~unนพ…”ใภบhธžŸ+๑ศ่,ข‘ๅv=ำr(š&>ท›ฎฐ&ฟฏU Iถlrบมlถฤ ณq^œญ์ฆXซc&„ิiบฺZูฝm Vฏขฅน ŸืƒKฎฬCอะษd๓ŒOฯฐ๏๐1_aวนพฎN>๖๎wาาิ@Iำxไ้็๙ษฟฌป9เ๓z๘ฝฎ,หๆลม์;|ดฆŽฑP,ำ 1ฐพŸ5ฝ4†CจŠŠ$iVvา‹-ฦ9x$#S|๘]w/‡ดNNašชZฟ๙oง…”A*›#™ฮ _เ๊Lร0yศฑ…}ษ็๊ฯ฿‚เ#„”@ ผA.–˜๚ญ+7r๛๚N<.้<๙ัƒฬๅJu{~๛ชห!เงาy๛SGูาึศ5ฝญ๔4yTนาฮW6-โใ i๖Nวkr—ทืดsm_nYชfHีง’‘XยฏTย๓›cSK๙œ๊ำrศ๋ช[ฆ' ู๏ล๋vแ’ภr บษLถศแน{ง1kPL !kzปู5ฐ™พข x<*ฒ$c;6šฎ“Lg™˜ไ…c'89>๑+฿ซงฃ฿-M”5GŸห{ฒ๎ๆ€GU๘ฟŸพ๎Nlๆะ๑“wัึDYืyโน|‘'๊oธ]มG>ภ๊ž.lๆ๐‰až}๑ะ%=ฆ%5ฐพŸพ๎."กภฒˆฒ,‹|ฉศิ<รใ“Lฬฮ.๏€P,kึ–3ฑ&g็(k:๎3~ฆฎ^่๎hล็๑bZ&้lŽลd—kๅ…”ฆ้ฦไ\์มท฿|รoˆo9@pึt!ค`ๅุ๓เ ฒญหๆ$™ศJพ๗'ฏูฬMk+กูใษŸ~ไEEญnฏีงฎยžjๆาh2หONฬ0ะvZ|ฬๅKธ$่oณถ)Dศซขศาฒ˜Ju†โ๖N/2—ฝ๔b๊ถu\ีSR9อ`ฌN+คT—L_ch9<™ษึGรฏ๚:ำrˆหธd‰พ† ํ!?ี…K’ฐ‡ฒaฑXฌTนํ›Ž“(^๚๖ห…ิ–ukนb๛ซบ:hฮฒ,‹’Vf!‘โฤ่8๛ 2ปฐ๘บปฃ%สoผ๏^ฺฃอhบม“{๐‡ซป9 ห2Ÿ๚่Xำc;99ฬำ^’c)ห47Fุฑiซบ:+Q’$aš&๙b‘™๙Gฦ˜Ž-,๏€x&ลR™w฿uซ:+™X3ฑy ฅR] ฉฎ๖^฿B*ตบฟhšnœšž๛ฮ๗žyโ>๐@Z|ป‚ ดฆ !%+ฯ…Sxํ–ๅะ์ัd–?{๘Eาeฝnฏั_7ภuีฬฅแx–Ÿ ฯฐๅe*qb๙Ž[#ฌn ๖ชจ.วqะL‹dI็d<ห3 ฬ็/˜บc}W๔ดเ’ [6๊v—=หE_cp9<L‚ีMมื๚%1e;kšBt†7๎3rมE“๑ ฯMลYธ„c๖‹’$‰หทlไ๒-›่ํl?Cj€iU๒†)Ž ฒ๏ศ ๑d๊ผ>ง-ฺฤoพ๏>:Zข่†มS๛^ไ=R—๋ำง>๖A๚{{p‡ฃรฃr ๕๓ ล2ญอMlะฯชฎ"ก Šป2f†i’/™]Xไ่ษfb‹จ๊+หฅ|๑g๏พใใ:๋DN™>าŒzณ%Y๎*.)NO์!$ค„ะbฒ–ฅ„ฝห.q~„ป๗ {—ป\n–5,BIHœุ๊Ž‹mYฝKฃ้ํฬœrI‰Yž‘ž๗?๐bญ™93ฃัœฯ>ฯ๗คธ๏ึ[h˜ฺ‚8<>A<‘œี€3ง๏g$j*ห๑บ่†A(%š %B” ยฆ‹ %‚pแฬf˜zsภyไ้}ฤดlม>7sCื4Tขศ'&ข<}j๘๗ฉiรฑ†eาZUBฃ฿‹ฯiห…)@ำM‚)“(ป'Š$็‚ผ Q]Q†ืใฦ4M&Cกะyญ๘Jฅ5:{๛ž๛๕žw‹%‚0‡Ÿ้"H ‚ \xท?ูจrป,๑เนฦงnhใฺฉ€s2ๅoณTV/ุ็ไ๏6ญ™ูโv|"ยoปFhฎ๐ัŸŽฅฐ,‹U>–”z๑9ํุฆNฌ2†I(ฅq|"ย‘ }แฤœEŽทฏZฬฅueH@8ก?œ(ศR^ปE>๗ฬ๐cใjŠ]็u›๑4‰ฌAฃ฿Cๆ‚MฟfแT†ฮษ(‡GCtc8ินYน1_ƒ”้ไŠumดฎXFme9ท{f+WV7ˆ' ŽŽsธณ‹‡Hkณณาฒิ๏ใ#๏น—ฺส๐์Wไป?ฒ ?Ÿ>เฌ\าˆ…ล๑ฎ^v์ฺsA๏/ฅiิTTะผฌijt<”ฆVD%่ฅณท‘1gq…ผh<มฝท2ณq<$n’$*หJ)๖zฮ;HM‡จ็^๙ะWm๏฿VAๆ๘3])A„นs>a๊ำืpU๋็oŸ‹f˜๛\|ๆฦต3[ŽŒ…yพgŒีgพˆl8–ฤด`YY+ส‹๑อlๅ› SiS๛†๔…ธm6Lฑz1๋ksA*˜ส0Mไ๋R์ฐQW์žž2กบศ5+ท=Kก้&ีล.šJN‰Yำ$šฮาŽsp4Dg ‚rO˜็[*).ๆฒ5อดญXFUy— UUฐ,ศ๊Yข๑รฃt?ษCGั cV๏฿_TฤGw‹ชชะ ]‡๙๖OUฟ{ปXูิภ‰๎>ž{u๗นŸTZฃบขœถ•หY\]I‘ืsฺึผh<มภศ(GO๕04:†ห้8๋๛ˆฤณ๕&–7ิca† EฃH…XฬษฉŠ?พโ",ำ" 3 6ศLžwขA๒เ3])A„นทq๛“6SzLBzว™ฬ#›ึrE}.เ๐7Oพ†n๎gx๛M๋ธlQ9ph,ฤห}ใฌ*?๛]ƒั†™[1ตฌฌ˜—ดญ|แt†๎`Œ]๔Gx.P˜บณนžต5ฅL&5Fbษ‚|]N;5E๎™แ๙]ม•^็ฌ‡ฆ›คu"ปZŸ‹ง‡*#ำ"ฆeŠ$80โD ‚eYศเไyพฉช๒2.okf๕ฒ&*หJp;](Š‚eYdฒ"ฑ8}C#์9x„ƒ':/ุฑy<|๔๗ฯ\อํตCG๙ๆO~Qฟพ๛Yฝt '{๛๘ํ+ปf๕๖Sišส ฺV.cQuE๖ฉฯฆLV'30:NวฑŒOฯ)DM‹ล“ผใ–3+พ‚แมHด †–—๘)).ฦฒ,&Ba&‚มฉซ๑็๐‰ฮร/ํ=๔พฏ}แำA.*คA.ข›rฃ,หํภ ์฿~v*เศภ‘๑0๋ื ๚ุแ–๕3+Š:FC์œ`Yi๑9฿`4A:kฐฆฆ”ฆา"J\ถI)ั IDATvSยดฉmaมป'่ ฯ~˜บปฅ5ี%X@ ‘f4ž*ศืฅิๅ ส๋šž฿JPแq\๛า ‹DVวฅ*,๒น)u;pชJ๎ b†I,“e8šb๐$๛†ƒฆ9ซณม =H-ชฎไ๒5ญฌXา@Ei .งEฮ ืฒยั=Cผv่(GOu_๐c๓ธ\|๔๏šนšพ#วุŸ?+ศ฿ƒผ็>š—5!I}<๓๒ซณrป้L†ลีUฌljคพฆš"ฏUQ‹ฌฎ‹'่ๅHg7#ใ็ขฆล)nฟ้zV65"!ŠF „ {LRฉฏ˜2ฟ ‹‰`ˆ‰ษ๖ทุฦ8ข^ุื๑ฑว?ศA„ผ ‚” B8“0๕น›ืฯฬ(:4โo~ณท ๙ ›/a]M)p`$ศแ KJผ็}ปƒัรคนาฯฒฒbS[๙$ ฒFnลTg JวHn^‘ห6;๓Š๎im ญชงง r†T™;คฆ‡็F”น๔>uร"žษbWd๛<”yœ8UEรฒHdt†ฃ):Fƒ์ 5f'LjZZฟˆKšYึฐ˜rฟ‡รŽ,ษ˜–‰–ษ G9ีืฯรว่์ํŸณcs:|มhจซม0L=ฮื๔ำ‚|๚๐ป฿I๋๒eH’DWOฟ*็๓9“ัY\› Q‹ชซ๐ž6ืKŸYลvฌซ‡ั‰ภฌ„จi‰dš[7^“ lHDb1ฦฯ๑JŠ๙ขคธˆ๒’’?คDˆAศo"H ‚ ไ‘›r#ฒ˜ k฿{ใŠข#A๎ฉ}}ฌnน”ถฉE{‡&9:ฆฏๆ๖๛ Fhบษส +ห‹)q9ฐ+ฏฯ+Šค3tใž<๏Aฺ’$qokอ•~L`4šd"ฉไU๖*ฤas*•ึุ{๔๘๘ž‡>๕ต/|fป๘v!‚ŸDAศC›ฟ๔6ำฒฺe‰†้ํ+Š๖O๒™ง๗์๑ษ’ฤฃ[/ฅe*เผ6 3ฅฎุ=๋๗5Iึ VU๘XYแฃิ•›WนS‘t–pœืtŸc˜R$‰wถ5า\้รฐ`8’d2™F.ภ"UๅuQ๎vL ฯ2‘Hใsฺๆ๔1่†E ™F–$–”xฉ.rใฑ+(’„aYคณคฦั๑\˜šLj็ฆ %HตฎXส†5ญ4ิีโ+๒โฐ$ร0HฆำLL9ึหk‡Ž02ธh๏E‘yx{fฎๆv๐D'_๛ไgิ๏ป‹ตซW ห2=C<๒ซg1>ซิUUะฒ๙๗ฒด~1–eqธ๓_ฮ ๒3๊ก{๏d}๓JdYฆop˜ง_EVฯžม{ึ พฆ†•M ิUWโuนงฎt8ข๔ s่ฤIม ขฆi™,7lธt&ฐ%’)†ฦฦ :HนNj++ค\'Oค=้ฟเ๛I|{A( "H ‚ €-ฬถ/mนไฑ–*ฟozEั็~[ธrจ _r)ซ*Š1L‹W๚'‰&ฉ๐\๘“ณH‚xFงตสฯŠrฅn;EA–ฆฎ๐–ฮะŠำ1ไิdU–ฯเxd๎iidๅิ๑๔…„ำิ RPWไฆฤํ@ŽŽ‡‰jYงยT4ฅ/œ Šส๏ Š๙คJ>.kkฆmล2*หK๑8]S[ผ^z=02Fวฑผv๘(†aๆ๕{่c๏+›8ัว๚ๆw ๒s๖}wฦๅkZP•ัQ~๛๒.’้ำƒิโ๊jV-[BuE— U™ž•!‰า30Dว๑“Dc‰‹ขฆ้†ษeญซูฐถUQIฆำ ŽŽ…คRi Y’[๓๒%_ดl"D ‚ 0คA ิฦํ;ฒ™yX…ฯฺc/u;๘ฏ7ฏงฉดˆฌa๒\๗šnโฝˆ[ร" &“kชKXUแฃย๋ฤ95c*k˜ฤด,‘๛†'้šŒ๖ณ^ปสญ ,--&k˜tNFIft์ja)รดh,ษลศ]อศ๋ญ‡šnึ Š์vj‹]”L ญ—ศmมŒkY# :ฆVบฆ…</fชฎ(ใฒถV/]BeY)nงsj‹—I&›โี?<ย๎ƒ‡9tโTมผ‡ฝ๗ณzู$$N๖๖๑ๅํ฿)ศฯื๗q+ึถaSUวฦ๘ํ+ปI$“duƒe ‹YฑคแดQ–e’ฮdˆLmอ๔๑D๒ข†จ7^ฏ[ฝ‚+ืญมnSIฆา `Jฅ5:{๛ž{๎ล}๕ั๖^๑-@ก๐‰ %‚Pเ6nฒQ5ไvYโมByฬ'Ÿปy=KJผd ƒgN`ZnลŸU4I0‘Lณถบtj+Ÿ—ช ห๚T˜๊$่ qd<„M–๑9lีาภ’า"ฒ†ม๑‰i8ง+๖]์ืฦ/~ง}ๆjŽฒ$ฤpvฐHdu\ชBฯM™;ทาm๚u‹gt†ขIŒLฒo(ˆหฆ\” ี/_xีšึ็–/i ฒฌงร"็†ดk™ แXŒž!๖:สฑS๗y๔g๏น—–eK‘$‰S}<ถโWอn฿ส•๋ึ`SU†วว๙Ÿ’ีห–ฐz้jซ*p9(rnF”–อŽฤ8ีืฯก“]ฤโ‰ผQำ, ZV,ๅšKึbทูHคา ŽŽฬk!B” ย%‚” ยHM‡จ๖u|์๑ฯ?ฒAaAJažบ๙๑'7สฒN†ฉ†/lZรขb)เว(u;๒zขษ@$มh>u}ีE.โŸ๎ฃถุ]ฯ็@$มH,ลวฏ^ืa˜Yy`˜i •5Hfuยฉ &๙๛wื˜š!ๅŸ Rป&fŽiพyฅoœ฿ž๔“๗ดc.๏๗ƒ|~ฃ๓6Hฝ๏ฮธ|M ชข28:ฦฟว๗ˆฦy๗8ซ+สธr].D••๘q9_ฟฺaZำศ๊:ท EV˜๙ทืํ*ุืฅบผœญ7\ƒวๅ"•ฮอบAJำ2ู๗๘ฟ{๐?…AคA€›ํฉ^Y’ฺŸz่–ํ ํุo๙๚Scา.ษ๘ๆ๊>ืึ”๒WืตPแqำฒ๐P/ ~oม>‡?;>ภ฿ะFตืE2ซ๓b๏อ•~$ NปŠ*K่ๆt˜า๓2L™ฆEcฉฟำAึ0ุ5 ุ9?WHํ๐รC="Hอฒwฝ} Wญ_‹ฆ246มฟ~๛y1+ซถช‚+ืญaๅ’*JKp:ศฒฤ๔ีก0งz8ูว่D€ตซWฒ๕บซq9B!?†้(ุืฅขด”6]‹วๅ&•N346Žašsvš–ษ๖Ž๘‰Wv|x{{{X|๋A@)A6) ภด่[ˆajใ๖~ูฬ<ฌ˜<<a๊ฒบ2>qM3'Q-ห๖ฐคคจ`Ÿฟ_žไฏฏoู‚ธg0€SUฐ+2ฅn^ปŠfรe“งฏ๎6ต•O'‘ั™ศ“0eYะXโล๏ด“1 ^ํŸภ็ฒฯห๗กIพ฿ั-‚ิ,ป๏m›นๆาตุm6†ว|๕;?d"บhgqMึถฑrIๅ%~;ฒ$cš&)Mc"ขซ€๎!2ู “แ-ห–r๋ฦkp;]รaถ๘็8์…gK}>nฟ้zผn)-อะ่)ขA„ท"‚” ฏฉi&t`šฯ๕ษ๊ล6Wa๊Šล|๊ี”น„ำพฐ—eฅ…ค~}r่ด-ˆGฦr'เN›€,I”ธ์ธT—Mมฉ*(ฒ„iYคu“tึ žษHค1/b˜zcา ƒ”ฬำ u`$ศw๖w‰ 5ห๎ูz3ื]ถ‡ฦ่ฤ$_๎ Lฮ๙ใX\Sอ•๋s!ชิ๏รaทฃศ2†i’JkŒ&950H๏ภ๐LˆšŠฤXฑค6]‡วๅ"‰๐ปญpทฏ๚ŠผผใๆMy<ค5กฑqtรธ`๗—Jkt๖๖=๗๋=;๏!JA๘CDAเwƒิyM ๅQ-K_(NZ7ฐ‘ฒ$แsุqU\๊t˜’0-ะtƒิ‡ฉ7ฉ}ใ”yๆg:6แ฿_;)‚ิ,{๛ฆ๋ธ้๊+p:์LC<ƒŸะ?นœN๎|#โbาšฦศD€L6{ท›Jk>ัy๘…}{๓์@Aฮ‚R‚ œyšfZ|CWฬ๖…ฆ6ozฆ๕pร๙ฮ–uOƒิษ@”วwŸAj–zร5rํ•ธก0๖ร'่ž๕๛YXฯ†5-,kจว๏+š Qฆi’Lงะ?HฯภฆuvรปำZ†_1๗ฝํผn‘xŒ๏์I ำ(ุืล้pp๗–›().&ญฅ L’ึ2Hาน}–ˆ%‚ ฬคA8๛ ๕†๘ฆn~ษฒ,ทsŽa๊ถU‹x๐’e;lL$า|`oAฉ—๚ฦ๘ุUซ)า>Iๆ‚ิYn๑™S.›‚ฆโถฉSรฯsaJำ ™, ฌaฮz˜2-h*๕โsุIfu^้งยใœ—๏แฎ`Œ๓๊qคf๛ณ๔ฺ+ูz5ธœN&รaG?Z4;–7ึsๅบ6š๊แ/.ยiท#I2†aHฅpขงแัณQำ2Yฏอo฿LฑวK4็{ฟ๘ Y=[ฐฏ‹f็žญ7Q๊๓‘าrณด’ฉฒ|vsฑDˆAf“R‚ œ{ฐL"†ฬcฆllวถ ๊jB็ฆั\ฯ{ื5Qไฐ1O๓ƒC…คvLœ6ค} ’ c˜(็8sFFขศaรm=LฉŠŒiZh†IF7Hduฦใ้Y SฆKKs+คโW๚ฦฉ๔ฮฯ ีŠ๓ฟwAj–tีถ้ZNมp˜ํ?9ฝ็}ป+–4pลฺVš๊QR\ŒรnC’dtC'‘J161ษฑฎFฦ8฿ญu†aโฐyเ๖ญ{ฝDq~๘ซงIkZมพ.6ีฦ=[oขฬ๏'ญiŒƒฤ)”3ิžJk์=z||ฯCŸ๚ฺ>ณ]|kAfƒR‚ œ_šถ ริฟ=u'๐˜,ัp&žึX„ืฎ2O๑ฃCฝฌฎ๐์๑๏ ฬ iงณ๔‡ใ่ฆล๙ฮ@–ฆย”วฎL]™Oล6ฆfVLes3ฆ2๚๙‡)ำ„ฅeE๘œ6bšฮ+cTy]๓๒=N๐/ฏAj–mผโ2~ใ๕3Wง๛ฦO~ม‰๎sพฝ–ๅKนคeK๋Sโ+ยnณาi+ขŽw๗า;8|ฦqๅ~–[ (2๏พใV|"b‰?z๒’ฉTมพ.ชขrฯึ›(/)!ฅฅ รฤ EyหŸ3 ƒ‡EˆA.คA˜ 5s2ณ€ริๆฏ?ฝอดฌ๖?ฆ๎_ณ„๛ฺ๑ุUFbน ี\YธAj๏๐$z๙ .;‘t†พpรดfiGe1uU>—}*Lษ–Yำœน*_ ‘F;0•[!5คฒผา?Aี<]!5I๒ฯ/Aj–]wูzqหF<.7กฉซำ;ี}ึทำบb—ถฎฆi๑"|E^์6ิU๓r!jhlœฮž~z††PHT9วฏศผ๗oรWTD<™เ?๓,๑Dข`_EVธg๋MT”–ึ2ŒMNO$QU๕Œฆeฒ๛Ž๛C๗๙๑-AAธDA`vƒิN๎๛dIj๊ก[ถ/ผ็๓ญริ{ึ5qOK.›สH,ษ๔๔ ฉ#Aไ๒ๅ๘v"้,ฝกุน—eAฑำ†KU๐8l3aสด k˜dŒฉ0•ิHgณ S–Hฐฤ๏ล๏ฒีฒ์ PๆžŸCอGข)้ฅร"Hอฒซ/Yห]›oฤ๋vŽF๙๖ฯ~ลแ“]g๓-ห—rลฺVีžขt žJ2<6ม๑ฎ^FGQd๙‚‡$ษผ๛๖ญ๘‹‹‰'“<๑๔sDbฑยย/Iณ๕fชสJIg2 ŽŒ‘ึ2ุlฟค4-“ํ๙๑ฏ์๘๐๖๖๖๕TAๆ๘๏“R‚ &HM[จajใ๖~ูฬ<ฌ˜<,ษœ6 ๊มK–๑Žๆz\ชยP4ษOŽ๖ั\ภA๊เXhๆช‘t–žะ…=qต€"ป ทMมcWqmุงร”™ส—ฬL$าgฆLำB–%^J\นฐvp4H‘ร6/฿ŸcฑใEคf†ตญ{๋อง]ฎใ๘ษ?๚sญ+–ฒamu5๘ŠŠขtโษ$รใ้์bhlญˆzำd$ธใVJŠ‹Iค’์™็ F"๛บศฒฬ]›oคบผ -“ฅgpˆlVวn๗[„(Aaฎ‰ %‚ภ… R3'"Lอ„ฉ‡.[ฮํซใT# ~zl  ‡šฯ\50šฮา𛕖^ป:ตZJมcทaWd,๋๕Sgฆtำยฎศ,๖yฆfae8>มฉ*๓๒}9‘H๓ฯAj–]ฺบš๛oB‘ว3suบGมฟพyPkย IDAT๋šWาดธ_‘›š $บกO$p๔T#cุm๊\~EๆทR๊๓‘Hฅ๘ลณ/… ๖uq:œผmใ5ิT”“ษf้์ภ0 v;ฉดFะ่๗EˆAๆšR‚ ฬMzƒ็MำlŸ๋แ‹ํa๊CWฎ๐ฝmๅ"ŠB$มฯŽ๖๔ ฉ๏[ฟ”ข9RำLำขศiรcSqูTผ๖๐s€Œa’1L™,“ษ ษŒ{รTึฐpช2u>ฯฬีปC1ไู„•g‚IGwAj–ญ[ฝ๒wฎN๗ฺกฃงY–ธคe5๋Vฏคกฎ†bฏw&6้†A,‘dptŒฝ aทซแH$x๛J~’้ฟฺ๑cษ‚}]Šฝ^nผjuUdฒY๖Qฐฏ‹ชจถ้:๊ช*ษ๊:ป:}ใป?yปQ‚ ยล$‚” -HM{Yz๘ฉmทXHฯy2ซ7ฺฅฝ7{๐ู๎Q–๘ฝ{,ฝแ8๗ฏY‚ืฎัฒtO^œ 5อ0-Š6ผSWไ๓ุีV>^_1•สๆ†Ÿ'ฆย”ฆจฒฬาฒ"N;มคฦ‘๑๐ผ!ีฒ|ทDšeญ+–๒w6uuบ$?y๊Yv๎๏`๊U\ฑฎ•EีUงญˆส๊:ัx‚กัqž่ddb—#้[๗ฟ}3ๅ%~RšฦS/๎dptฌ`_—ด–แทยโ๊๊็uC฿ๆฐ{ล_~AแbAJ‹ค0-พก+f๛Žm[ิ‰ย๑@ค๑ห/๛โๅue๏Z\ ซค" ๎mkฤmS‰jo…ิ›ฆ…วฎRๆvเRUœ6ิŠฉŒiข้&้ฌฮxB#šฮ ศ+ส}๘œ6&“{‡&ฉ๔:็ๅ๛.‘ั๙3๛Ešeซ—5๑พ;o›~๐x'.ง“๚ฺjŠ<l๊tˆสฮlอ;|ฒ‹‘๑ œ{ˆ๗ถ…ŠR?i-ร3ฏ์ขohธ0฿๋ษ4แh๔ล?}๗;พiQA!Oˆ %‚@~ฉi 5L๘“WV๘ฟti]ู†B Sรฑ$๗ด4เสณ 5m:L•ปธl 6Eฦฎผพ•/5H๋ฃฑ %^Š6&i^๊gI‰w^พ฿RYƒฯ>ฝOฉYถชฉ‘๗฿};ฅพb รDหdPUิp้QรนญyCใใ๙ฑ"๊๗ธ๗ึอT–•ึ2<๛๊z ๊ตH$ำ‚ก—รษไ#‘‚ BžAJ Rำraส๐ŽmิU 1L%Rนบ>oƒิดำVLูr๘loš1ๅRTYb<‘ๆฉฮaZช๓๒}ฆ้&ŸyjฏRณศfSy๛ฆ๋น๑ชหฑlไพbZXVnET4ž wp˜c]=ŒŒpปy|4๏z3Uๅฅค3ž฿ต—S}๑:$’iฦBกX"๙~ขA„|&‚” ๙ค,“ˆ!๓ุฒŠฒวพv๛ฅ"Lๅฉ@Rใ๖ี‹qฉ Q-Cw0N>_œN7-ผv•R—๗ิ|)ป"#H ้ฟ:9DฉำN‘sอ‘ส&๗คfƒfใ’ึี\ึฺLC]5E๏ฬ๛_ื ‚‘รฃt?ษฤdปถZpฯญ7S]^†–ษ๒ย๎ฝœ์ํห๋‡<ข๑ฤ฿ํ Ÿู.ฒ ‚ ๙N)A๒7HM[Yๆ‹|jSc5^ืcŠ,…ึk๓๔ถฟ็๓WีWิๅk˜ ฆ4พj1NUษ๋RoฆnปB…ว‰หฆโRs๙ฆฮว ฅ4z‚qbZงช`Wๅy๓พ2L‹ฟ}๒5คฮƒรngรšึฎ^I]UEชช’”ป๊ใ๐๘8ฟ|๎EB‘Xa„จ)pฯ–›จฉ('“อ๒โž๏๎ษหวšษ๊ ŽOˆ%‚ คAศ ี\้็ฏohฅสใŠ$ฒ๚cล[๛ย{rajหŠฺ:_> ?"Z†ทญ\„C)ฌ 5M7,ชLu‘‹ Y’ศํถฒศ˜‘T†pŒมpงMกบศU๐๏'ห‚OzR็ภaทsี๚5ดฌXสโ๊*ผn7ŠขY@QdY!“อ๐›wฒ็เ*หJ ๊M ๎ูr#ต•dฒY^ืมัฮฎผ{œฉค |๙หŸซGฤ_rAกะˆ %‚@ฉถ๊๊บVชผNbšฮทt๕=qt ฉ‡nูพะ^ซ?๑๊Gฏ\\uล๙ณ"žัูฒขถ`ƒไ†|๋ฆษ†E8m †iข›6YF’ kZDำบƒ1๚ร ๔ฎwR]‘โž}์^=pˆมแณบmฏอวฎ™ูK{ๅลื๖ใv: ๋ย‚-ื_MS",ำโเ‰N^ูw`ึ๏F„(Aa!AJR[–ื๑ะeห๑9m_~ๅ({็qฒe}9ฃ8ฺwlธ ฎึtกย”CUธขพE‚˜ฆำŠsc˜~—ล>ช,“ศd9ˆขศg^ึtรB‘%*งfL9Uปช LmๅKduย ๚#‰ฉซ๗]0ตะ‚Tฉ฿ว5—ฌeีา%นญy'ฒ,cZf.D…#œ์้g๗มรgขฆนN>๖wัPW;3{้…ื๖ใrุ ๊๗มฒ`หuWฑด~1–eqธ๓/ฝถึn?‘L3 $โ‰ฟฺ>ณ]A"คAศ ๕ถ•‹ุv้2Š6&i้ฅฃ์ž<ฟ.“ˆ!๓˜)[ˆajIi๑ทฎชฏจ›0ๅฒ)\พธˆerƒฝ iZ”ธิปsณฐ2Y:ฯ2HM›SๅฉSUF–$Œฉ05I2ŽcSeJ]g๕ฬB Rฅ%\นฎๆๅKฉ(๕Ÿถ"*ั„ยt๖๔๓๊ƒ ŒŒื}9์v>๑เ4Lmu;p๔/์ู‡รn+จ฿ห‚อื^ษฒ†z,หโศฉ.^ณ๏ผo7“ีŸ!JAAJศ ๕Žๆzปฎ‰"‡๑xš๑า:F‚ณsโต€ริๆฏ?ฝญม๏๙๙†)]ๅาEๅน ฅe้ `ฒ ํ ฆศ5ณ๕๐ไdU>๗ฝ‡บa!KPแuโฑูpูoZ15MัŠa“J=sปŠfพฉšŠr6ฌme๕ฒ%”—”เr:Pร0gBิษ๎>vuf`dtV๎ำฆช|bปYฒธำ49xผ“็w๏ลnS ๊๗ม0L6_w+ฐฐ8vช‡็wฟv^ท™Jj๑๑P๐/๛฿ลuAA)A„ฉ0‘฿A๊๎–XD‘Ce,žๆ_8ฤแฑูmG–I™๖งฺุย{sajหŠฺ:฿9l-*rุธคฎ ˆjY๚ 0HYTxœTyฏฉ@U9aXบa!หLอ˜z=Lฉฒ„nš$2:#ฑ]ม( Qแvฮส1๓5HีT–ณaM+ซ–.กฒฌงร"+ฆAZำ˜ G8ัีหซ146>ซ๗-ห2Ÿภ{ff/:ูษ๓ป๗ก*rA>duƒ-ื]ลŠ% œ่๎ๅนW๗œำmฅ’Z<e$xt{{๛‚Š‚ ‚๐VDA ƒิ}mทf ›สX<ล{แ0Gว/ฬyiั'KR๛Sฒ}กฝไว/u Uิปg๓s>—u5ฅภT ล‘คย;J“ ฏ EสGg †mรnXHR.Lyํ6ช‚ห&ฃศ2†i’ศ G“Sa *=ฎ ฆๆ[ชญฌเสumฌhj ข4ขdIžบjžF ๆXWปbd"pมŽ๑“xฯi[v์ฺ{N[?/&-“eหuWณji#'zzyv็๎ณบ ขAแญ‰ %‚@ฉwฏmโžึ6•‘XŠ/=ˆศฝฯ…ฆ6n฿แ฿PS๔อๅพži˜๒O) ˆฆ3๔†โgtuบ|SใuQ๊qฮl=์œŒbป+[tร *NผงชโTsWๅ3-‹Dฦ`$–ค'รฐฌ ฆๆKชซชไŠumฌZฺHน฿รaฯ…(ห$ญiŒ‚œ่้c็ฦม ~Œo{7ห฿ฐีmวฎื .ะฆด [ฎปŠๆeMHHt๖๖๑ฬ+ปฮ่gษ4‘hโK"D ‚ ย[AJR๏[ฟ”ปš๋qูT†cIพธใ ง&็ๆJn&t`šฯ๕‰๛ลv6aชฬํ ญบ ˆL)ฅƒT]‘›ทcf๋แฉษู]!๕fบaa‘ NปŠหฆโฒๅ†Ÿ›–E2k0Kq*ร4M*f9LzZ\Sอ•๋Xัุ@™฿—[%หฆA*ญ11ไhW{ftbrฮŽ๑ใ>pฺVทgw๎)ธ •Lฅูrีด,[Š$Iœ๊๋็™W^ๅญพ6'’iยั่wรมะงฟ๚h{ฏ๘ห*‚ oM)A๒?Hmปtwฌฎวฅ* E“|แนzๆJnฯ›ฆูพริe•ž/7W๚฿‡Ÿ—{œดV๙1H*Co8~^รภ/ห‚ล~~gn†VTหา=›“YNบaM=นซ๒นl .›2ต•ฯ"™ีง่ ลษ&ๅณ4cชPƒTC] Wฌmcyc=ๅ%~v{.D)-อฤdˆฃงบูีq˜๑ษเœฟ—>๚พwถีํ้—w\ %’lฝฺV,C’%บ๛y๊ฅพ๏อ"D ‚ ยนAJRผ|ทญ\„SUŒ$๘‡็:่'.ึรY a๊ษฦตๅฅsmuษ]ง…))7{ฉฅสaA8ฅัŠ_ญn’iAฃ฿ƒฯiŸูzุšฐ6ฝ•ฏz˜rช ช’ S้ฌฮ่T˜าM“2ื๙…ฉB R‹jงBิbสน%Iาi+ขŽœ๊f็ƒร‘‹๖^๚ศ{๏;mซ“/๎,ธกๆัx‚-ื]อšUห‘e™ž!ž~้U ำ˜๙7‰dš@0๔r<}ฏQ‚ ‚p๖DA ƒิ‡6ฌไึ•u8…H‚๚ E“๕1YX?อสึร;ถm]P'boS’$Qๅuฒบา‡aZ„ำz‚q์j)ำbIiลฬึรžะล[้%~—ทMลฅ*8mนซ๒™Sa*M_8Nฦ0)s9ฮ)LJZZฟˆหืดฐผฑžRŸป63ฌ<™N3:เXWฏ์๋ ]๔๗า‡฿}/ญหงถบ๕๐ซ/aS•‚๚}Gclฝึฎ^,ห๔๓๔Kฏข๚Lˆ '“<๙Gv ‚ ยน}฿AJ!ƒิGฎ\ลๆๅต8…พpœ๖฿`4–สa๑ ]1b˜j)๑๎ึ† U^ซ*Š1L‹P*CO(†ฃภNภ ำขi*HMo=์ _YX2>——ชไโ”M™~žฮŒ'านS†E‰ห~Va*฿ƒิา๚E\นฎฅ ‹)).>mktˆ:าูล๎ƒG.๊Šจ7๛ะ๗ะถb๙ฬVท_<๗bมฉ`8สึ๋ฏf]๓*Eฆoh„g^~•ฮž~ขAa–ˆ %‚@ฉ]ฝš›—ึ`SzC1>๛ฬ&้ผzŒ 5L๑g6>z๋eํ+ส‹oะงƒT0†ำV˜Aส็ดอl=์'๒f๖,I;r๘<ถพq+฿DRฃ/Gำอ3S๙ค–7ึsลฺVš๊Q๊๓แฐค\ˆJคRŒ&9t๒{:ŽŠF๓๎ฝ๔ม๛๎šYYิ30ฤฯŸ}กเ‚T f๋๕ืpIหjTEกoxค๏ฑo~w?_ํ@A„Y!‚” ๙คพฆ™MM5ุ™๎`Œฟf?มค–—U‡ฯ™ฒฑ6.จห๋ฆตQ7อ๖pโ†๑DW!ฉฉฐ6M’oณจeIขศaร3ตZสmSQำดH๋นSแ8iฤ๏|๋0•oAjUS#—ถ5ณฌ~1%พbv อฌˆ Lr๐D'ฏ๎?D,‘ศ๗าC๗ษ๚ๆ•ศrneัฯ~ปU)ฌ฿‡๑ษ[ฏฟšหฺš๛TEmWyป๘K)‚ ณK)A๒?Hๅต-ะT*หtMFyไ้}Dาูผ}ผ–Iฤyl!†ฉ'O๙lื่ฟพzQตวฎฬใ~s ฆ2 ๅaz#ŸรŽž‹RN›ŠM–ฐ,H๋‰4}ก8Yำขุa๛ฝa*_‚T๓ฒ&.i]อฒ๚ล๘‹‹ฐlนaๅ†A"bd<ท5๏ๅฝHฆาy^ฺvฯo\YฤOŸูQPCอ3Y๎มแ๛฿vหgฏฟ’ํโ/ค ‚ \"H ‚ A๊ฟ\฿สuUจฒLg ส฿=ต—xFฯ๛็u!‡ฉอ_zฦฆ๊/]ืXYYa๊๕ eG7M‚I‘X Iส๓๗เwุsซฅ์*ฎฉ0eZ ้d.L้ฆ…ื~z˜บุAชyYึถฒdQพ"๏ิึ< 0H$S sไdป:O& ๆฝุป๏0ป๎๚ภ๏{ฮํm๎๔*iFฃ^Fอ]ถี โฤุdƒึ ๙%›‚Ilร€m„ˆeI xBIHศbY’-ษEถl๕^f4ฝท๋)๛วฬศ˜bd{ส=šฯ๋/|๏นง|๏นš๗sฮ๗ั๏ผ—›–/มฎฺ้่้ๅ฿๖@QฌคRษLผซo๐k_๛'–_F!„brIB๒?H=ธn9k็”ก*6. D๙ฬcคrบe๖ฏiฑ)ถ๖ฟe๗ฬ[ฃajหผส25/7๚๙ •ำ FRzโ)lฺื—รŽฯiว๗sa*ญ้ ง2t„ค5CลeWง-H-Ÿ7๗ภญ+—S[]E(่ว้pކ(M#žJา?ศ‰๓—8z๖<‰dสrc๛nYฑ ปjงณทŸ์;€ขไ๗HJ%3๑‘h=ษมปร!„bาIB๒?H=ดกf•ข*6.๔G๘๔ณวศ๊†ๅ๖ณaาฆุl31L=ดฤ7๎™_QCuไ้ฑกฎะ-H %3๔'R–ื~งฟslŽ)งงช`šฃsL %3tFำคŸ8ฝพ~V๕‚ภ๘ญyำ4ฉ}œ<‰ืNŸ#ษXvฌ่}นmeป๎~e๏๓(yzฉ„(!„b๚HB๒?H=ฒqทฬ*Eตมนพ0Ÿฺs รย็๏ู!#W4ฮ ๙vฯคqถ~๗มะ‡jžXPผ7฿ยิ›ƒ”ฮ@"ร`2mู}mšpู๑:๘ฦ&?wช &ฃท๒ %3\่oุ2ฟ๚เTฎW:“]๏tุhบN<‘คป€ำฏ๐๊ษ3dฒYห๓฿ญmฑบงรAw๒์๓yw๋g"™&SorไฟKˆB!ฆ‡)!„ ƒTใฆ•ฌฉ)Aฮ๖…๙ิžฃ–฿๓Š|f}•๏กdNk ธgาxหว0ešP[่'ไv’ัG'Jf,ฟฏ ำ$8>ว”รŽ฿iว>6ŸQFื7x๖){†aฎืtํ@<‘คฃง3—›8r๒ ู\๎†฿๗ฝg wดงรAฯภ ๒์syณnใ!*<<๒™'v6ถสฏŸB1}$H !๙คพฐyซซ‹ฑง{G๘๔ณว,ฝฟ–๐เ๚ๅT๘=$s?:z่{'šง๚๖ฉ้ถ~๗มะ}‹*ฅก"ดaบ'>ล ีKNgo˜}m&ท]ล7vKŸCU6(6”Žนกpd}Woใ็.p๔์yr9ํ†ื๗nฤ7ฏฦๅtะ;8ฤ๗์Ÿ๖u’%„Bไ RBAฉวถฎfeeงz†yh๏qK๏๏%e!>y๗2ส9>ยฯด2 c†ฉ=ต๗-ช{j:ร”aยฑ[๖าฺhŠdฒ7พ6 Ÿk4H9UeCน฿3ฅcํษ๚gฯะ4†ฯุฒuทฎมํtา78ฬž?Z<งA"™fpxไๅp2๙๐“=<ฃฮ+B!Dพ“ %„ไ๚โถ5ฌจ(ฤNt๑ศพ–฿ห+ ๙ฤ]ห(๗ป‰e4๑T3zฎh`๒ดฆwloIใp:ร”๙ssHฅ4žh’X6wร๎k0yฎฉ{รƒ๋Nๅ็~ไแวึซpเFว๏x7oฟทหIะ?ณoส็ผ“%„Bไ? RBAฉืฐผผ8ึ5Hใ“–฿++‹๘ซป–R๊sหไ๘ฮ๑f~zฑใ—^7Sริๆ'๗ฌฟgัฌฏ฿\Sฒlชย”aย"?.'ฉœFW4Iโผ์็MวS๖fBบgl^{+—‹แ0?|f/S๕๏M QB!„uHBเกฝวอื;๓๓Dmณ๑•ํkXRย^๏เ ฯŸฒ๔พฉบ˜ึ.ฅฤ็"’ฮ๑วฎฐ็rืฏ}ฝ„ฉษSฆ uE \’9ฮH‚ิ |[Hš,๎พƒmwŽวๅfpd„l๒ƒT"™ฆodค#O|๖ฌ: IDAT[?ฒ[~ี„Bˆ'AJ!€๖pย<ืๆ@s'{†๓j์Šย—ทฏaqYบa๒jว8m้}๋ฌRโŽล{]„ำYพฺežk๎yห๗˜]a—ก8wฑ~F=ฆ}*ย”9~…”I"ซัNั%HMด™ค6ฏฝ•{ึ‰วํf(ๆ๛๗ูI›C*›ำ่์%„BX)!„tร4ำšฮ`2อนพ0{ฏtsพ??š‡หฎ๒ฅmkXTD7Lท๐ฅƒึRwฬ)ใฯo_L‘วI8•ๅ๏\โPK๏uฝw&‡ฉญOํฑ~nล—๏ช-+›่0e˜P?คโYึ‘8šaะ๛S‚ิไุpอผwใ]x†#้ง{€‰๗f*™‰๗ ๅW?—฿–_1!„ยz$H !ั ำฉ*†IZำ้‹ง8ำ;ยฆ. Fฆu|N;o]อ‚’ ša๒Rk_yแฌฅ๗๗บบ ไึ…zœ งฒ|ใ• ผึถ–1ฆžฟkใLฏ“ฆL๊‹bึ‘๚ o R“ใ๎[ึ๐M๋๐y<ŒD"ใฉT2‰ฦฟั“นปฑ1ŒB!,I‚”Bวบ†ฬ9…~.ล†aBZำ้ฅ8ี3ฬ+]ดŒฤงe‚.m]อผโ ša๐BK_}ัฺAjc}%|หBn'รษ _;|#๏hY†I›bณ5๎ฝห๎™6nวริ–y•eชb{Wหฝe/@A,“ใ๊p Rm&ฉตkV๒;[7เ๓x Gฃ|๏฿6!ห•%„BX$H !๐฿}|ฯ‚jnฎ)กฎะ฿ๅภฎุ0L“Tn4L๏โู+tFSบn…'_ุฒŠ๚ข 9เ`K/๛า9K๏๏m๓ซนฆ๙ธ &2|ํ๐yํค๒35Lญ฿}0ดถฆเ๑{ๆWิใP๏d&`๊ GƒT4“ใ๊p์†฿wค&วmซ๘m๑{}Db1พ๗๏?{W“š'’i"ัฤ—%D !„7 RBl}jฏ r;ู4ฏ’f•2;ไว๏ดcWtร ‘ี้'9ึ9ฤฆnบฃษ)Yทฏ‹/lYEma€œฎ๓\s๋๐K๏๏฿ZTร‡Wฯ#่r0H๓?_:ว‰๎‰™L0iุ฿ถd&แ๕ป†>P๓ฤ‚โเฝo7L&จ6s }„Nย้,ญร๑ัJu“ 59nnXส}๏ูBภ็#๑Ÿ>K&›EU•ทตœD2M8ง๐๐ศgžุูุ*ฟTB!ฤE‚”B๐FWโuฑy^ทฮ*ฅบภ;ฆอ0Id5บข ^๏ไนๆzcฉI]ทrฟ‡ฦอ+™๒“ำu๖^้ๆฏ^ด๔ภ’ูมสz.;๑4_}๑,ง{G&๚c†ั8ีมaบ‡ฉyE฿ฟ๙ฅtรฤก*ฬ.๐›hพe$ŽM‚ิ„› Aj๕าE{ท๔๙‰&โเ๎%–Hโt\฿x”%„Bฬ ค„‚_RใJ|nถอฏโ–šRช‚ผ;vล†nšฤณํแGปูwฅ›กdfRึญ*เๅณ›V0'ไ'ฃ๋์นลG.YzฒZ>ธขฟำNo<ล฿ผp–s}“v'ฮ S{j๏[T๗TCEhรo Sšaโถ+ิGƒิH*Kˆ\!5fBZฑx๙}๏!่๗K$๘แ3๛G๐ธ]o๙พD2อเ๐ศห๑h๔%D !„7> RBมฏRใสณฐšU•ลTx๑:T› อ0‰gst„ผึ9ศ3—ปˆgrบnณ |<ฒqณ |ค5Ÿ]๊ไฏ_ถ๔เŠ:๎[V‹ื1คv:รฅIšแ!{wl99“ฦ๖๕„ฉœnเuุฉz =๙ฐ=ฟแ๗ฉษฑ|แ<เ๗PO&๘๑ณฯำ;0ˆ฿๋๙•ฏQแd๒แ'{๘ B!„˜$H !ฟ9H›๒ณi^%ซชŠจ x๑8์จ6ศ&๑LŽ๖H‚—๚ูwฅ›dN›uซ-๔๓ะ†j‚>Ršฮ\่เฉcW,ฝฟหชz~gษl<;=ฑ$_7.ปŠ ะ ƒp:K๓PŒ—๛9ะƒfผฝZTZภงึ-งย๏!™ำ๘แ™Vพบลา๛๛On]ศ๖ีธT•ถpœ/<Š๎hrฺึว4ˆ่ ป ลนk&†ฉตuO~จกฎพ2เ!เrะOsq Bะํธกท]‚ิไ˜_;›๗พขPˆd:ลฯพฤพรฏตูLณQB”B!ฦIB}ืPQศฦ๚J–•R๊sแฒ^a’ี "cWLผฺห ญ}\๏๙wiyˆฟพ{~๑ฌฦ๗Oต๐ฃณญ–฿v"ถฮฏย1ค๗Ÿค/žš๖๕šษa๊‰#—v|hลฦ€ห>ง/žๆL๏%>ื ฝอค&วู5ื฿}?%……คา้ศ3๏๚ฝ{65ส/B!~ž)!„`โ‚ิธUUEl™Wลขาล^n๛่\<`8•กi0ฦพฆnŽt ฦe5T๒‰ป–Qๆwหh|๏d3?9฿n้w,fS}%Uฅu$ฦg๗`0™ษ›๕3 "(4๎ป๋ฎ™๖]0LsGO,ีxฒ{xNeะsCoซฉษQ[]ล๗} RZฺ•สdv๙<ž0B!„ฟ@‚”B0๑AjญณJูT_ษ‚’ …ฎ๑0ฅ†ฉ a^ํๅตฮม_ปŒUUEๅK)๕น‰er<}ผ™ธุa้—w.e]]Uกy8ส#{ONg๓n= “6ลfk{–3ํ;๑ํื.jIy่QCฝa๏“ 5_"5•ป>๚ก์ช()‘%„Bˆ_K‚”B0yA ภUWฮ]ตๅ,() ะใฤกŒ†ฉฌฎ3˜ฬpพ/ฬก–^Žv า๛ืT๓๑ตK)๑นˆfr๚pCอ Šƒ๗ˆaJ‚ิ„{:cืุุ(!J!„ฟ๙๏$ RB1นAฺ๊ X?ท‚;kหYP$ไvโT 2บฮ`"รน0๛›บ9ำ;rํ}ทิ”๐ฑตK(๖บงณ<๙๚๖7u[z?ธn9k็”ก*6.F๙๔ณวIๅดผ_oรค ำุ1ีcบจaJ‚ิ„yฺฆiO์ll•_!„B\๗฿Gค„bj‚ิ8ลfc]]9๋+ฉ+ Pเ Sฆi’ส้ $าœํa_S7๚#1ปŒ?ฟc1E'แT–ฟ?r‰C-ฝ–฿mhเถYฅจŠ‹sŒฌnXi†ั8ริ,ญ๎ขาะ{}NปๅทG‚ิป&!J!„๏˜)!„`jƒิ8งชฐฑพ’ปjหฉ+๔p;q*6 RšN<ลฉž†’i~g้ =NFRY๎ี‹ผฺุg้ศฦ2ซี็๚ย|jฯ1 Uผ‡>ปiEใขภม™๔}Yฟ{Oํ}‹๊žjจmฐr˜’ ๕ฮ˜†yศPlO>๖๐Œ๗B!„˜Xค„‚้ Rใ<•ญ๓ซนmV)s \ca*ำˆg5B'.Ua(•ๅ๋‡ฯ๓J๛€ฅ๗wใๆ•ฌฉ.Aฮ๔๐เžc–Žš/l\ษ์฿กดฆ๏๐9ํญ3้{c๕0%A๊ํ‘%„Bˆ‰$AJ!˜ 5ฮ๏rฐu^ทิ”P[ไ'เt` SŠ ฐูHๅ4พyไฯX|R๓GทฌbUU16เT๏ŸyึšAjNศฯรจ)๐‘ึt~zฑใ้'Ž_j<ธc{๋L๚ฌ฿ฝง๖๓f๔ๆš’eV Sคฎ„(!„BL RBA~ฉqE๋+น}v)5>‚.ชbระ4้Š&9ิาวพฆnบฃIK๎๏วทฎfEe'{†yx๏qKnG]กŸ‡6ฌ :่%ฅ้๛…vvkย0yZSฆ6?นg=‹f}*aJ‚ิ[3 อfš฿z‘๒+!„Bˆ‰&AJ!ศฏ 5ฎฤ๋b๓*ถ/จฆา๏มfRบaฯๆ่Œ$yฝs็š{่‹ง,ตฟwn[ร๒ŠBLเXืŸย’ใฆพ(ภg64P๐’สi๋๙vพ{ข๙ฺืเ๓†โupว๚๐L๚>Y%LI๚ี$D !„b*HB๒3H๛ƒ•s๙`CNปŠišืnแำ “DNฃm$ฮฑฎ!žนE$อ›/o_ราฒpดsฯ?wา’ใfAIื5P๐สi่\x๒๊›^cDt…]35LmœWฯwี–•ๅc˜’ ๕ "ฆอ|@B”B!ฆไ๏ RB‘฿A๊๗–ี๒มu๘v’YกT†B ฏรŽbm์ŠฉŽp‚W;x๖r๑ฌ–ท๛ฺฎ(์พ†%e่&iเฑง,9n•๐ฉuหฉ๐{Hๆ4~xฆ•๏Ÿn๙•ฏษaj๋S๛vฌŸ[๑ๅ| SคฦDtƒ]š[ตปฑqFM!„BL RBA~ฉ6ิq฿๒Zผ;ฝ๑฿=ัL}Q€••ETข™n's‹”๙o SัLŽ–แ/ท๕๓\sMฯ›ํ๑9ํ<พu5 J‚h†ษKญ}|ๅ…ณ–7ห+ ๙ฤ]ห(๗ป‰e4๑T3zฎ๚Z€I›bณ5ฮฤ0๕ะ฿ธg~๕G=ี1๋1“ƒ”ฎ๑y QB!„˜Nค„‚Rดบž,™ƒวฎาK๒Rk%^๗Xš&UanQ€RŸท]EฑAฮ0‰ฆณ\Œ๒jวฯ5๗ำi฿žทƒวถฌฆพ8ˆfj้ๅผxฮ’ใfEeu็Rสnb™฿=ัฬฟ_่x[ห˜ฉaj๎ƒก7ิ<ฑ 8x๏t…ฉคžถiZใ;[ๅฬ/„Bˆ้$AJ!ศ๏ uš๙ผw๑,‚”i˜‡C฿!!J!„๙F‚”B฿A๊On]ศ๖ีธT•ถpœŽH‚ฌ๖›oฝS>‡Y!E.ปr-L '3\ SG:ฆt{*>ทi%sB~2บฮณ—ป๙๛#-9nnฉ)แck—P์uNgy๒๕+์o๊žจลฯะ0ตง๖พEuOME˜บ‘ƒ”i˜‡ ลึ๘ไcฯจ๑#„B๋ %„ไw๚ณฑu~Uฅ=ง+’$ปIสvNMศKก…SUฐู ฃ %3\่sจฅ—ื:งd{j ||vใ f๘Hk:?ปิษท_ฟlษqs๛์RSไuNeyโตKผฺ;กŸa˜<ญฉFใม[gาwr*ยิค$D !„ย*$H !๙คโŽลlชฏฤกชtDโt„“๏่ฉy‡ŠSU™๒๒8qช ฆ ]g(™แ|_˜W{9=4ฉS[่็ก ิ}ค4ธะมSวฎXrY[ฮŸถˆB“‘T–ฟ{๕"/ถ๖Mสgอิ0ตu๗พ•็U}๗ๆš’eฆnค e@› ;$D !„ย*$H !๙ค>~็RึืUเP:# ฺย๑๋บe๏ื๑:UN'7Nล†aBZำLฆ9฿แูห]œ๏Ÿœงมื๘ฬ†ช^R9Ÿ\h็;ว›-9nึีU๐งท.$ไq2œส๒ฟ_นภแIž›kฆ†ฉอO๎YฯขY_Ÿศ0u#)ฺlฆู๘ญวู-gr!„BX‰)!„ ฟƒิ'๎Zฦuๅุ…ฎh‚–แ89xWหดู ฤ็&ไqt9๐9cWL™คr:‰4g{Gุิอฅศ„nฯ‚’ ฎk 2เ!™ำ๘๑ู6๑ิUKŽ›๕•๑- น '3|ํ๐…)™“ห4ˆ่ ป ลน๋เŽ๕แ™๔]ศ0eๅ %!J!„V'AJ!ศ๏ ๕ษป—qgm9vลFw4E๓pMŸ˜ีUUทŸCล๋tเPl˜&ค4พxŠS=ร์ฝาอีแุ„|ๆ’ฒŸผ{ๅ~‰œฦNท๐ƒ3ญ–7[ๆW๑‘›Pเv0”ฬฐ๋ๅ๓ผ>Esqม Sg๏6ึW~๓ฎฺฒฒwฆ,ค "บมฎ'w>(gn!„BX™)!„ ฟƒิงื7pว์Rิฑ ี4E7&vuUลFuะ‹ฯๅภ๏ดใuุฑ+6Œฑ+ฆ๚โ)Žwณ๏J7mแ๘ป๚ฌeๅ…๕ห(๗ป‰e4้ิUๅ\›%วอ{T๓_ošOะๅ`0‘แo_>วฑฎก)_™ฆถ>ตoว๚น_~'aสRAj,Dinmื๎ฦฦuŒ…Bqc’ %„ไwzhCทอz#H]Œ2Y็n‡ชP๔t9๐:ฦย”ช &ษœFo,ลฑฎ!๖5uัIพฃฯXQYฤ'๎ZJฉฯM,“ใ;'š๙้…KŽ›๗.šล‡Wืp9Hค๙Ÿ/ใD๗๐ดญaาฆุl{๏฿ฒ{ๆ}‡Gริ–y•eชbปฎ๗X"HIˆB!ฤ J‚”B฿A๊ณWp๓ฌR ;–ไ๒`&ymv•ช€‡ ‰หฎเwฺฑ+ ša’ศjtG“ํไนฆบco/Lญฉ.ๆตK(๕น‰frรั+‡พxŠฏผp–๓yy1ห!ร0ง:พLท฿ฆ๒0HIˆB!ฤŒ!AJ!ศ๏ ๕๘ึีฌจ,FƒTำ4ฉk?6Mg^q€ช รŽjƒœaฯไ่ˆ$xนญŸMฤณฺฏ\ฦuๅ้ญ‹(๔8Ie๙ฦซyฉตฯ’ใๆC+๊๘ฝeตxvzใ)v:รฅH>ฏ๒ S{j๏[T๗TCEhรฯO|ž/Aส4ฬC†bk|๒ฑ‡gิqB!ฤฬ&AJ!ศ๏ ๕ฅmkhจ(ฤบ" š†bำพNYรภก(ฬ- Pแw†)ลFV7ˆerดฤyกตƒW{Iๆฆ6ึW๒วท, ไv2œฬ๐ฟ^นภซํ–7ธฒž{—ฮฦใฐำK๒ลƒghŠZaีกุุปcหษ™๔=S๓ŠJ}๎iRข„B1“IB๒7Hู€obYy่ฮ“ 5.gธ์*u…~สv๕ฺSัt–ๆแฏดฐฏฉ›œnŒ๎๋๙Uท›Pเv0˜ศ๐ตร็yฝsะ’ใๆรซ็๑Kfใฑซtว’<~เ4W‡c–YรไiM5๎ุ:“พ๏๋w๏ฉต๋J#ฆฑ{:‚”b˜ข„B1ำIB๒7H)6_พ†ฅๅ!ts๔ ฉๆก เP๊Š”๙ธ์*6@3 "้MรQ^iเนๆถฮฏbวšy]i๖ฅ๓๏ฒไธนอ|ปxปJg4มใNำ:ทvธ์๊ำ_ฺพบqYYaซœ „B!ฤT %„ไorจ ;ทญaqYบaาMru(ฏภ1ท]aNแa ซDาYš‡bฤณทฮ*!เrะO๓?^:วฉžaKŽ›ผ€{ึเถซtD<๚):" หm‡฿i็๑ญk˜_|Z3Œv5,g!„B1™$H !๙ค<•/n]รยาเhŠ$-qK˜อfร๋T™]เฃุ๋บvลTF7ศ๊^‡ŠjณัO๑ีฮrถฯšใปe!๏YXKUi$๘ยs'้Š&-ทn'mYE}qœnDถ๔๎๚๒แ+ป๎X/aJ!„BLฮ฿ ค„"ƒ”฿i็ฑญซYPR€ftF’ดXhŽ"ปjรcท3;ไฃะใผฆฐูH็4พ{โ*?:jษq๓฿o[ฤึ๙UธT•ถpœฦ็NาKYn;Šผ.พฐys‹ไtƒW{๘ฯGt…]†โ”0%„B!&œ)!„ ƒTมc[VS_ R Z†ญ7G‘กโTUf…ผ”๙ุำ4้Oค9ู3ฬ -}–›ฯo_ฬ–y•8T•ึ‘8ฯ ?žถ๑)๕น๙ๆ•ิศ้:๛›{๘๚แ ฃวศ ข+์zญrฆB!„E‚”BฟAชศใโ [ธrฅ+jอ 5ฮiWฉ/ P๔`ปJJ7L2บฮP2ร๙พ0๛›{,3งิว๎Xยฦ๚JชBหpŒฯ๎?มP2cนใR๎๗ะธy%sB~rบฮณWบ๙ปW/พ้5†I›bณ5๎ฝหn9c!„BˆwK‚”BฟA๊ฏ\้Œ&iตp๐9ํฌฉ.ฦiWั ร4qจ ฆi’ึtโiฮ๕‡ู{ฅ›๓๙}งุว๏\ส๚บ ชB๓p”ฯ๎;มH*kนcR๔๒ู+˜๒“ัu๖\๎โ‰#—~ๅk%L !„Bˆ‰ AJ!ศ฿ U๐ะธiๅตPะuฉวษา๒.Ue$•ก;–ข2เ!่vโTl&ค5พxŠำฝ#์o๊ๆ๒`4/ทๅw-ใ๎บr์ŠBำP”‡๗'šษY๎˜ฬ*๐๑ศฦฬ*๐‘ึt~vฉ“oฟ~๙-฿c˜ดa;๖d๛A9ƒ!„BˆทK‚”BฟAช:่ๅณ›V2ปภwรฉRฟ›…%AชJ{8ฮ—กกขf•RW เrเS9xŠS=#์k๊ฮป' ~๒๎eY[Ž]ฑqyp4HลณšๅŽImกŸ‡64P๔‘าt~zกƒ8vๅz฿~ศ0ŒF SB!„โํ %„ไoš๒๑ศ†ิŒ]นาณ~ช*๐2ทะ?6xŒฟ;r ]%‘ีhจ,dEEu…~.vล†nšคrฃWL๋โู+tFyฑ-ฎ[ฮฺ9eจŠKQ>ณ๗ฉœnนcR_เ3จ xIๅ4~rก๏o~ป‹‘0%„B!ฎ›)!„ ƒT]กŸ‡6ฌ :่%ฅ้๔D“ดŽX;Hอ)๔3ซภ‡CUธ:ใ๏\ฤ๋ฐฟ๑ๆ•YS]ฬฌ~ง‡ช &ษœFO,ษฑฎ!๖7uำIN๋ถ<ดกf•ข*6.Dxpฯ1ฒบaนcฒ $ศƒ๋จ xHๅ4~tฎ๕ฬQฌ๘ซบด<ฤ_฿ฝŒ ฟ‡xVใ๛งZ๘ัูึ Yถ„)!„B๑+/AJ!`็ก3ๆก–^๔<ปบeIYˆOฝŒŠภh(่ป‚ิา๒ล^ืตพyไAท๓7พฯญช,( าP>zล”ืaGฑf˜ฤณ9:#I^m`ฯ•.โS๔คปฦอ+YS=คฮ๔๐เžc–<& …|โฎe”๙ฤ2฿;ูฬOฮทO์‡˜ๆืฒชซ๑เŽ๕a9ใ!„B RB๔ฦRfำP”W:8xต—\žฬดฌ<ฤ_฿ฝœ๒ฑPะOา>’ฐ๔พ^VQH‘ื…jƒs}aพ๕๚eBืคฒบAฮ0ธcvซ*‹จxFร”bCำ ข™‘/ต๖๑|sฯค?๑๎ั-ซXUUŒ 8ี;ยgžตfZYYฤ_ต”RŸ›X&วwŽ7๓ำ‹9ฆADWุe(ฮ]ฆ„B!f6 RBฆifuƒH:Kหpœ๚8tตwฺ'จ^QYฤ_นt์ส•=ฑakฉฅๅ!Š}nเl_˜oฟ~‰B๋m-#–ษแPึฮ)ceee>7๎ฑ[๙rcaชu$ฮหmฃajฒž|๗๘ึีฌจ,เTฯ0ํ=nษcฒฆบ˜ฏ]J‰ฯE4“ใŽ^แ™ห]“๖yฆ„B!„)!„R9t`๔*œp:K๋HœZ๚xกตŒฆOหzญฎ*ๆใw.กิ็&šษัMN๛“ๅญ%ๅ!J}nlภ้ž:vๅบฏ๚EฑLรฮํณKiจ(คฬ๏มmWQl3Lข้,MC1Žt ฐฟฉ{ยใทญaEE!&pข{ˆG๖ฐไ1นนฆ„ึ.กุ๋"’ฮ๑ไ๋—ูืิ=้ŸkDPhwึ]rB!„˜Y$H !pจฅืœ_คะใฤฉŽฌaIei‰๑J๛ฎN•6o >vวJ|ฃก ;šค;jํ ตธ,D™฿ ภษžaพsผ‰‚wคฦล29.ทอ.eyy!e~7.UลfƒX`ผ:็ฅึ>\ํ™ฐ'แํพ†ๅๅฃA๊XืŸoอ u์Rโ๖ลy]„SYพ๙ฺ%\ํฒฯ7Lฺ›ญq๏[vหูH!„bf %„ภถง๖šwฬ)ใฮฺr–Pไ}#L฿vu8ฦ๋ƒ์k๊!•ำฆdฝnUสว๎ ้,]ั$ฝั”ฅ๗๕ขฒ*Lเxื฿;u•เ[๚TพH:;iกเOn]HแX(่Š$่[7Hูlฐฐด€ส€็Zฤ๙๑ู6|N๛ค|^,“ฃ*่แ–šR•P่qแTl6ศhฃa๊|˜Z๚8า๑๖ย”SUุน} ‹J ะ “W;xภiK—๕•๑- น '3|ํ๐…ทฝ?&ษ!ร0%L !„Bx$H !ฟ:H[YYฤๆyU,*ฝbสmWQฦžๆ6zลTœื:9pต‡‘ิฤ†ฉ_ ั$RŠbc~qช 0yฅ}€ฟะŽวaŸิฯerฬ)๔ฑบชd,L9qช ฆ Y]g(™แ|„W{8ึ5t]หtUพดm Kƒ่†ษหm์nƒ‰ _;|žื;๓i%L !„B`$H !oคฦญฎ*ๆ๎บr––…(๖นฏ=อM3Lโ™ญแ8วป†ุ{ฅ›๐]1ตe~นinCษ ‘C‰Œe๗ณชุ˜_ค2เA‹8?ปิ‰ฎNษ็ว29j :ซ”yลB๎ฑ0ค5มฤ่S{ฏtqถ/–ห๒9ํ<พu5 J‚h†ษKญ}|ๅ…ณ–<.๗,ฌaวšy]i๖ฅ๓๏สป๕41-ง˜ฑฝUฮZB!„ึ&AJ!ธพ 5nEe๋๊สYZ^H้ฏSั$ฏwฒ๗Jืปพb๊CAg4ษฐ…ƒ”CUจ/P๐ข‡Zzู฿ิƒSUฆt=9ฺŸg—RW ภใฤฉุ0TNง?‘ๆl฿๛›บนะ๙•หบ<ถu5๓Šƒh†ม -}|๕Ekฉ๗/žลYUOภๅ ?žๆผtŽS=รyปพ†ษำšj4J˜B!„ฐ. RBม Rใ–”…ุT_ษา๒e~žฑ[๙4 –อัM๑Z็š{้‹ฟณ'ใฝo๑,h, $าtF’ 'ญคœv•๚ข9เภี^ํล1ลAj\&ง3ฏ$ศš๊b๊ NŠ ำ„”ฆำOqชg„}M]4 ล๔ษฃ[WQ_$งฦต๙า9K—{—ฮแC+ๆpู้‹ง๙›ฮrถo$๏ื[ย”B!„uIBYทธฌ€อ๕Uฃaส็ฦํฐc›c*žี่Š&9ฺ9:วTO์ํ…ฉ฿Y:›ผขZ(่Œ$งฒ–ฯn‡สขๅ~9]gs/ต๖aW”i]ฏŒฆณธ,DCE!s‹\์Š ร4Iๅt๚โiNtฑฏฉ›ึ‘8ล^_ุผŠบข9เ๙ๆพv๘ผ%ห}หk๙†:|;}๑_yแ,็๛ร–Y >o(ฮ]wฌหูL!„ย$H !๏.H[XRภฆy•,ฏ(คฬ็ฦใPQm64ร$‘ำ่Œ$9ั=ฤฆ๎๋Sใกภ๏ดำOัIฑp๒\ส่:{ฏt๓jวชอ–๋g˜&๓Šƒฌฎ*fNก€ำ]Uะ “dNฃ/–โX๗๛ฎt“ึt>ฟyต…ัธึิรื_น`ษใ๒กuฒZผŽัqถ๓ะ. D,ต ฆADWุ%aJ!„ย$H !คฦอ/ ฒฉพ’ๅๅ…TฆบฃINtณ๏J7ฑไ[.๋ƒ+๊ธ๏็BAg$I4m ๅuฺฉ+ P๎s“ึtžนษ๑ฎ!lyคฎ8bcAiีUET}๘vช‚6ฆบฃI.DXS]LUภ{-ฎซ-y\pe=๗.วaง'–ไ‹ฯะ4ตไถH˜B!„ฐ RBมฤฉqs‹lชฏคกฒช€รŽj4Id5zc)Žwณฟฉ›ŽHโบBAg4I,ณ์~๖น์ิ๚)๓yHk:?ฝุม™ซศ†%ๅฌฌ,ข*่ล7v;ฆ>v+ŸCUpฉ iอเ™หป”ีUลิ๘๐9ํŒ฿l˜ส้\ŒpธฝŸM=ฤ,ฆ>z๓๎YXƒฎาI๐…็Oั๙kฎฺณ* SB!„๙E‚”B05Aj\uะห–๙Uฌช,ฆ*8zล”:๖DทdNง/–โT๏่S๋+yฯ‚ัPะIะM’ดp*๐8ฉ ๙(๖บIๆ4~tถอrsล29tำไ‹gณnnN๕'ๆtƒh&G[8ฮKญธฺc‰€๘งท.b‚*\ชJ[8ฮž;๕็7ณฐC†a4๎ศ๖ƒrๆB!„˜>ค„‚ฉ Rใช‚^6ฯซdUe15^|N๛ุSฃ๓๕'า˜&ิxq( mแ8ั$ฉœnู๒8™S่งฤ๋"–ั๘ม™ZGฌwkXw4‰วa็s›VPๆsc9รDตูPmฃ;šษั<ๅีŽ๖_้&ฃyป=~๛bถฬซฤ1ค๗Ÿค/žบัฟ๖‡ฒŠฑใเŽํญrB!„˜zค„‚้ Rใช‚^6ฬญเฆ๊ช ผ๘v์ส่LำฤฎŒึMั2#mแ U่u1งภGฑฯE,“ใŸN]ฅ#bฝ+qzbI|ŸZทœส€‡Œฎำ6’ภeW(๗{pูU่S‘tŽซร1ท๗๓\sน< Sqวb6ีฉ–แŸ‚มdๆ††ฑAฎ”B!„˜ค„‚้ Rใส6ึWpKM)Uมฑ0ฅ*ืๆ(สh:W‡c„ำYโkถWไs1ปภGฑืE4“ใ{'ฏาต^๊ฅ๐ป์|๊๎ๅ”๛=$r?8ยน0›๊+Y^^Hฉ฿ฎฃa*œฮru8ฮก–^ต๔ข๙๓๛๛๑;—ฒพฎ‡ชะ<ๅณ๛N0’ส๐฿{ RB!„ำG‚”BAj\กวษถี\]ย‚’ ฎฑจaษฌFค„‚ Rฎ[ฮฺฺrŠTN'ฃ๋๘ช‚a˜ค5มdšŽp‚ดfไ}˜*ธฉ ๚yœŒคฒŸฃWˆคญwkุ@"Mศํไฏ๎ZJฉฯM,“ใ;ว›๙้ลŽ_๙๚ตsสธซถœEฅz\ืžฬ—ีu†’Y.๔‡yกต#ำsลิงื7pว์RTลฦล(Ÿy๖ุ่x78 RB!„ำG‚”BฟA๊3๋ธ},\Œ๑bkทฬ*กฆภGะ5ฆLs4L $าtDd4รศฯs{EะCuภKศใd8™แG/[r>ฌมDšBฏ‹ฏ]BฉฯM4“ใŽ^แ™ห]o๙พป๋สนซถœ…%zœcว2บฮp2ร๙๛›บ9ู3<ฅ๓ะ†n›5:ฮ.๔Gx๐ูcy9๙๚D“ %„B1}$H !๙คูธ‚[f•ขฺเ|„๗ลeWู2ฏŠf•2ปะOภๅภกุฎ…กd†ถpM7๓.*TฝTฝธ %3|๋ตห$sึ RCษ ล^ฌ]BฑืE$ใฝฬ+ฟ๙‡ธณถœM๓*ฉ/ ปb๊็รโ๙{ฏtqฎ/<ฅใLฮ๗‡๙ไžcฬ„HB!„˜>ค„‚ RŸด’›jJP€sa>๙ฬัkอ๋ฐณu~7ี”0ทะOภํฤกุ0ฬั[ม†“:" ฒบAVห0U๔R]เ%่r0H๓ํื/“สY๏ึฐ‘T†bฏ›ฑ˜"ฏ‹p:หท^ปฬ๓อ=ืฝ ‡ชฐ~n๋๊*จ+๔t;qŽฟดฆำŸHsบg˜M=\ŒL๊๖4n^ษš๊ัqvถ/ฬง๖฿{ RB!„ำG‚”BฟA๊๓›Wฑฆบpฆw„Ÿ=๖Kฏ๑:์lจฏเถYฅฬ- ผ)lduแT–ฎH’”ฆM{˜ช zฉ)๐p9่ง๙ึ๋—ษhV RYสn๖ลyœ„SYศ%ต๔พํe_๑v๛์R๊~!,ฆ5XŠำฝร์ปาM๓plRถ็ั-ซXU5:ฮN๗Ž๐้_1ฮnDค„B!ฆ)!„ ƒิฯ‡‚“=ร<ด๗๘ฏ}ญฎrw]9wืU0'ไ#ไvŽ dดังบuG“$sำฆFƒ”€หN_<อ7_ปdษนŠ"้,ๅ~ถEŽMะW/๒Rk฿;^ๆ๘oทฬ*ฝโอๅภฎุะMHๅ4๚โiNt๑์•.ฺร‰ žวทฎfEeง~ร8ป‘HB!„˜>ค„‚ Ro]อสส"LเD๗์;๑฿ใRึฯญไฮฺ2j Œ…) S#้ แ$Y]'ฅ้0…[^๔2;ไร๋ฐำO๑อื.กึ๛ŠฆsT=ษ- G'hOe๙๚แ๓ผา๎Ÿ’Wเvฒฑพ‚;f—1+ไ#0๖TEอ0Iๆ4zc)Žw ฑทฉ›ฮศฤ„ฉ/n[รŠŠยท5ฮnค„B!ฆ)!„ ƒิฮmkX> Žu ๑นื œชย†น•6ปtl๒l'e4Le๕ั0ีI‘ีu’9ฉ๘9จ z™๒แqุ้‰)ร‚ฟCัLŽš —ฒ€ษP2ร:|#๖E›ๆUr๛์2ชƒ^N;vUA7LYฎh‚c]C์o๊ฆ'–zwใl๛–—bวบirF|๏%H !„BL RBA~)›อฦ—ทฏaiY8ฺ9ศ็Ÿ{๛กภฎุXWWมsส˜_$ไy๓S‘t–žX’TN'™ำ'๕้jUA/s x์*ฑ$Oนdษ๑ฯๆ˜]เ็›ๆSเv0˜ศ๐ตร็yฝspย?+ไv๒[‹jธนฆ„ช ŸรŽชุFรTNฃ3’เhื{.u1œสผฃq๖•ํkX26ฮ^๏เ ฯŸš฿{ RB!„ำ๘๗Ž)!„ศฯ eWl์~Kส ะMxญc€G฿E(ฐwึ–ณ~n๕ลŠ<.\๊WL…ำYzb)ูฉœ1)aชชภKmศฎาM๐อื.cณเxId5j ์X3๏ฺ๖ๅ๓๏šดฯฌxุ6ฟšUUEิŒ๖จุ@7Lโูั0๕jวฯ^๎"šษฝqฆฐs๛šัqf˜้ไฑค„B!ฤไ’ %„ไgrฉ _ฺพ†Eฅฃกเ•๖พx๐๔ป^ฎbณฑvNูต0U่vแฒ+ุxs˜2L“‘Tc็xช.๐2g,HตG|๓ศEิฑญ$™ำ˜[เVี R_}๑งz†'ณg‡|lžWล๊ชb*ๆลณ“๒Yk็”ฑvN‹JC{฿ฆ9dV#–ั่‰%฿U˜ช RUฅu$ฮ“ฏ_FUฌwำ^ZำYXRภWิแwฺ้ง๘›ฮrฎ/<ๅ๋2ฟ$ศฆ๚JVVQๆ๗เถซ(6ศ&ฑt–ฆกฏv ฐฟฉ›ฌnา๛.o]อผโัq๖BK_คq–o$H !„BL RBA~ฉษฃ[WQ_$งj้์wt\i^เ๏M•ซTฅR*IVvฮvปsป: /ณ K\e†ษMำ“ ห ;ภ–xู]Xย๎พคmwปฃsJถ%U)”Jชœ๎ฝ๏Uฒ3ำูvU๕>็ฬ9sfฌาญ็+ฉพ็yžหz๑์mžบ[ุ5aeK€ฐว‰Sื*K๙,›lฑDถd’ฬ—ˆฅs”ฟEx;• ๅวะTF็SูัaqฉBูdu[ฌ๏รc่Lงs|ๅะiฮฯ,ึ์˜Vท5ฑgฐ“๕!Zฝ.\๚จธ˜/1:Ÿโล+ำ์‰Qถฌš^g๕B‚”B!DํHB๊3H…=Nžฺณ™f?%ำbH”ฏฝt๎Ž|๏-]a๖ FXฺูT Sš†ช*฿0cชD,•ฃ๔.ยTwะKศ‡ฎช ว“ท#X ๘kจhZฌm๒แตฝx h*ว—žโา\ฒๆวถฎ=ฤ#ห;YำึD›ืu#*V๗‰งุ?ๅ…๑lฎ้uVkค„B!jG‚”BPŸAชอ็โษ›้ ๙(™&ฯ G๙๚ห็๏่1ีๆแVทฏฯ˜R([6ูR™tฑLถXb*๙ฮยิฒ —พ]Uธ4—ไžWAซ^”L‹๕!พoMnC'šส๒ล็O1Oีอ1nŒ4๓่๒NV/Eล›ยิ|ฎศๅน$๛Gฃ ว“5ฟฮjE‚”B!DํHB๊3HEn~u๗&zƒ> ฆษ3—ฆ๘W/ิไXถt…ูืฮฺถ -ีY7K๛ๅJerฅสSSษ์[ฆžjาT… ณIๆLc)ำฒู ๑=ซ{p๋“ษJOีฑณฌ•ฌlmzรฦ๕…ฒE"W`<‘f0์งลใช๙uvงIB!„จ RBA}ฉ๎&Ÿต‰ž&/๙ฒษ?_šเ_ปTำcZืb๗`„5ํAฺช๛ฝ1L™$ซK๙ e๓›พพ'่ฃฏู‡ฆภน™E๊ิ(ธ‰”ilŠ4๓ซ–แา5&3|ภ)ฎ,ค๋๖˜๊kฏl\฿ึDณ‰CSฑํสŒ)]Uะ5•Bูไ.\ซ๙uvงHB!„จ RBA}ฉ ฯ์@w5H…kษ‘หuqlkƒ์์dM{Vฏ ทฎกU๗˜สVรTชX S๙า0ี๒ั๒กgg๘๓cรธ ฝแฎถูๆ;Wvใา5ฎ-fxjI&3u์๕ตณc ƒๅแ!ท‡ฆ‚ข T฿ื๘B†ฏฟ|žำฑฤพ— %„BQ;ค„‚๚ Rอ~>ตc]นฒษw๎*zlธฎŽqM[]ƒึ-อ˜2tด๊Sน’IถT&S,3•ส’/™๔Uƒ”œŠ%๘ำฃร\FC^3[ปย<พข งฆqe!อS๛N2•ส6ฤฑซŠย๖vv DXัR SŠR™ฉV2-&“YฮN/๐๐็f>ฐ๗ฝ)!„Bˆฺ‘ %„ิg ๘ิŽ๕Drฅ2w๖*qbค.วoUk;"ฌ๏ัแsแ24TEมฌ†ฉtฑDฎlข) 'ฃ๓๑๋—h๑บ๒šูึยcห;1ชA๊ษฝ'˜N็๊=84•kc??ฐฎ—ฎaุ6– ๙ฒษt:วฉX‚ฝรSu๑ม[M‚”B!DํHB๊3Hญlmโฏงร็&[*๓ืgฦ๙ห“cu=ŽCแป#l่ัแwใพiฦTฆTฦPU††iู›Š๓ฏ]$โ๗4ไ5soO+{#šฦx"ล{O0—ษ7๛Xูาฤ'wฌ'โwcฺP4MtUEW•J˜*•™ฮไ9>g๏pด.7nฏ$H !„BิŽ)!„ >ƒิšถ ฟ๒๐::|nาล2ujŒฟ>=ใ9๖ณ{ฐ“ !ฺn<†Žฎ*ุถ Šถอd2วŸ?…ฎ*๘ทl๏6vD04•ั๙O์=ฮ|ถะp๏cM[_ูพŽ๖j๘<=ภฅk๔}๘บฆVgบ•™N็865ฯณ—'นบi๘๛^‚”B!DํHB๊3Hญ๏๑หญฃ็"U(๓฿OŽ๐ฟฮ^mจqํ๙ุ3ิษฆH3m>7ง†ฝІใ)NF็yebหฒ*Lm๏kg{†ฆ2O๒™็Žณ˜/6ตฟฎ=ฤวถ฿ธฮวษQ๖Dู5แ6บ›<๘†ฆRถlฒฅ2ัd–ฃ“q๖ŽL1ฑ˜mุ๛^‚”B!DํHB๊3HmŒ4๓หญฅี๋"U(๑็วG๘๛๓ืr|{‚^[ล‡Vu_ชž ˜–EถdMf9K๐สีส ฆv๔w๐P;บชry.ษgž;FชPjธsณ1าฬ/=ธ–6_ๅ:๛‹ฃŸs•๐t9x|Ew/kฅปษƒท:ำอดm2E“‰ล วฆโƒิถ๎~แ5„=N๓%๘ศ%žป<ีฐc์w|แั- …˜ถอฤb†Bูค+P บZYVูซ(ฯ้X‚—ฏอ/™uฆ๖ urO+šชpa6ษ'Ÿ9Jกl6yนซ+ฬ/<ฐ–oๅ:๛“#—yๆ๒ไทท]{†:ูาฆซษƒ็ฆM๋Sล“‹Y_™a฿ศ‹๙๚Sค„B!jG‚”BPŸA๊พžV~พี4{œ,ไ‹มซ90kุ1น<๕ศf›”L‹็วbJ&A/aƒ ห‰ฯกฃk*V5Lลชa๊•kณไJๅบ S.๏ไe• u~f‘OŠฆษ3—งะT—ฆ]7N]ฃ3เฦ๋ะ๑•h7…ฉูl3ำ ^ป6วbพXำ0๕]+ปฺู‚ œ™^เใOiศ๓๒P_;?w๏*Bี๐๙ปฏ\เลw>Wถ4ฑ{(ย†Žm>7.]C] S๙"ฃ๓)^พ:หแ)Šu4‹L‚”B!DํHB๊3HํŒ๐ำwฏ ่r0Ÿ-๐ต—ฮ๓๊ตู†ใฎ€‡'voขงษKม4y๚า$>‡๒-ญำะ่๐น๑;o„ฉ๋K๙ส&๑Lžณ3 ผte–dก6a๊Cซ–ฑต+ŒœŽ%๘ฤ3G๒ผ์่เg–ยgถภ๏ผ|žWฎพท๋lu[{†:Y฿ขอ็ยฅWbcษดXฬWfL‹qp,Fูช-'AJ!„ขv$H !๕ค[ลOตœ&—ม\ฆภื^:ว๋s ;ฦฝAŸูน๎&/๙ฒษแ)<†–_ใะ5"~~งปฆŒj˜ส—Mๆ2yฮฯ.๒๒ีYนย S฿ณz›;+A๊DtžO?{ฌ!ฯหžกN~jr‚.๑lฏ>วk๏๓:[฿โัๅฌn า๊uโิ5EกX6IไŠŒฬงxnxŠ—ฎิvฦŸ)!„Bˆฺ‘ %„ิg๚ฮ•ุึ!NƒูLž฿~๑วฆโ ;ฦอ~>ตc]นฒษกั†ฆพฃฏ54•Hภ฿aเq่ธ CUฐm(˜&ณ™<็f921วl&Gยิ๗ฎ้acคจฉฯ4hz|E%|œ•๐๙‡ฯrt๒ึ\g[ปย์Œฐช5Hุใภกi( M‹๙\‹ณIล8\ฃ0%AJ!„ขv$H !๐งG‡ํ็วbL%ณusLbMjำ~งมL:ฯoฝx–“ั๙†ใๅ->๙๐z"~นR™—฿รฒ0]S่ x๐:Œ๋๛Lี=ฆŠฆI<[เฬ"G&็ˆฅrท5L}ฺ^6t„ฐc“qžุ{ผ!ฯห‡V-ใ_oฤ_ Ÿ้ลณŸบตืู=m<ิ฿ฮชึ&šNีนฆฮอ,๐ย๘๔{^*๘^IB!„จ RB,ไ‹๖T2ห‰่<Fc\Iคk~L฿ฟถ—8€฿ฉ3ฮ๓‡ฮpf:ัฐcผชต‰?ผžˆ฿MฆXๆ๕‰9ฬ๗ธฎฉDn|ฝฆŽj˜*˜&๓ู"—ๆyๅฺ์m S?ฐฎuํA,เ่ไO๎=ั็ๅ{ื๔๐/7 โw๊ฬค๓ๆ g8ป=ืูC}ํl๏ogEKอn†ฆbCL7ฝc3%H !„BิŽ)!„,ถ-&[2‰ฆฒœ‰-๐XŒ‹ณ‹5;ฆฌ๏ใ#๚๑9tbฉฟ~่ ็fvŒืถ๙ุ๖ut๘ค‹eŽผ ตDืฺ}nี=ฆ|N‡ฆb6…ฒI<[ไr<ษKWf˜N฿บ0ฅ( ?ธฎ—5m• ๕๚ตYžฺฒ!ฯห‡ืUยงฯกK็๘อCg83}{ฏณ๛ฺู3a0์'่rเะ5l{i_ฐสŒฉg/O๖+AJ!„ขv$H !,”lกก* –m“+U๖%:;ณภกฑ้š,•๛่ฦ>ผฎกMๅ๘สมำ\œ[lุ1iๆ—\K›ฯEชPโ่Tำผ5ฟƒ4Uกร๏ฦ๏4๐:>‡~}ชByiฟขEŽMลนบy฿aJS~`}kฺš0mx๕๊,Ÿ?ะ˜A๊‡6๔๓‘๕}x ้tŽฏ:อ๙™้ชสށ๎oง?ไงษU‰‰KณฆำyNว์žโยm รค„B!jG‚”Bไจฝ)าLgภƒฯกฃฉ7žไฯVbฦั่-์๙๘‘อƒ|฿š†ฮT*ห—ž?ลp<ีฐcผฅ3ฬ/>ธ†Vฏ‹dกฤฑษ๘๛ž!๕TUฉ.ๅ3p~งกุฏ(‘+pi.ษ๑hœ+ ผo๓”ฟ7cจ• ตชต ำฒy๙๊,_|TCž—nเรko„ฯ/<ลฅนไ๛NMe๗P'๗๗ถั๒p9ฎ๏ –/›LงsœŠ&ุ;2ลๅ[|\ค„B!jG‚”BPyส^gภรŽ๎๊ำ้๗เsี=nn,Ž'94>อแ๑in๗Oฯ:ฤ๗ฌ๎มญkL&ณ|แภIฦ๊`oซ๗j[w แ5ดx,ๆKœˆฦ)›ทgUU!ไv`ะไ!่บyฟ"‹…|ๅ\™œใ๊Bฯป SN]ใึ๕ฒข%€iูพ2ร—žnศ๓๒แ๓‹N12็รงะxdจ“{–ต2ะ์ฏฦDำ†\ฉฬt:ฯ‰hœg.Oฒ=$H !„BิŽ)!„ ค–{ศํ`็@„{–ตฒฌษS๙`|ำ๒ฏ…|‘หsI^Ÿ˜ใ๙ั(ำบ-ว๔SV๐]+ปq้‹>wเ$W2 ;ฦ๗๕ด๒๓๗ญฆูใd!_ไT,Aฉlึ๏ฉ(เ24ผ†Nฤ๏!่vเ\:—ฆลBฎศ่|Š—ฏอpm1๛ŽgLน ฏํeyK€ฒe๑ย๘4ฟq่LCž—฿บœ๏^ฝฌnยgภiฐk0ยฝm,k๒^ฟส–MฎT&–สqt*ฮแฉ๗}?HB!„จ RBมƒิกณ{(ยถฎ๚›}4นื—•,‹ล|‘๑Dšื'ๆุ7%S,฿าc๚™ปW๒+ปpjW3<ต๏“ษlรŽ๑C}ํฝซน$rEฮN/P(›wๆ—.]รm่t*3ฆœบŠยอ3ฆR›Œ3šHใ1ดท|=ฏฃคร• up,ฦoฝpถ!ฯKฝ†ฯ หมžกN๎๏mฅ+เล็ะัซ3ฆฒฅ2‹ŽNฦู7e*๕๎ RB!„ต#AJ!๘ึAj‰กU6_พwY+Cแภ๕˜PฒlR…‹^น:หมฑ๑lแ–ำฯปŠG—wโิ4ฎ,คyr฿ bฉ\รŽ๑ฮ~ๆ๎•ๆsE.ฬ.+šw๔–fL95ฎ&!—‡ฆข(Pบ)LŠฮ3Oแ|“0ๅw|บ^š”L‹ฃQพz๘\Cž—zŸM.ƒ๏ZนŒปบ[่n๒เ5t4ต๒๐Lฑฬตล,G'็x๚าไปพ๗$H !„BิŽ)!„เญƒิอ๎๋ie็@„กฐŸฐว‰SืP…’i‘.–˜Jf92็เh์}จ๙๛Vณg(‚กiŒ'R๊ฬf๒ ;ฦ,๏ไ'๏ZNะๅ ž-0O’.”ks0ีS†ชา๔rฟ1L-ๆKŒ%RŸšg8žฤฉฟ1L59+Aช/ไงdš์‰๒;/oศ๓า(แณ็ๆัๅlํ ำ๐โuhhŠBูฒIหL&+Q๘™หS,ๆ‹๏่5%H !„BิŽ)!„เฉ%wu…ู1aek€ฐว…Kืะ0ซณ6&“YNF2๗ใ๙…ึฐs ‚กฉŒฮงxb๏qๆoั์ซZ๘Ž]๘]ห 8 f3yฦi’๙RอหะU\šFw“ทซK๙,›ไMห2วiีงBn฿ทถ— ’i๒p”ฏฟ˜A๊แ3อฏ๎=^ืแsY“—=Cl้j&โ๗เฉฮ˜*›ฉB‰k‹^บ:ร‘(‹os}IB!„จ RBมปRK6FšyจฏuํAZฝ.††ชT–eK&ฑTŽ3ำ žqav๑]ฝ๖/=ธ–‡:ะU•‘x’ฯ๛ญhZค๒EฦiŽOอs~v๎€็z*˜&ฯ\šโ๗_ฝะ็ๅๆ๐96Ÿโณ >{C>๊dsg˜vŸ ๗7„ฉ๑Dš—ฎฮผๅnค„B!jG‚”B๐ƒิ’-v tฐพ#Tตq#LๅK&ณู็ฆx~,ฦษ่;zอm_วC}ํ่ชสๅน$Ÿ~๖(้bนaว๘๛ื๖๒ร๐;uฆำy&๋+H-14‡ฎฒฌ:cสกiจสยฦๆS วS฿JwภKม4๙ง‹แk—๒ผาƒkู฿ก-…ฯใ๏xษ[=l๖๓ศ๒N6Eši๓บp:ชeห&Y(1O๒๊ต9žป<๙MOฤ” %„BQ;ค„‚๗ค–๔…|์่๏`Sg3สฬบฆbY6๙ฒI<[เโ"Fข™Œฟๅk}โแ๕<ะ†ฆ*\œM๒ฉg’+™ ;ฦ?ธพฺะฯก3ฮqm1หbฎ~ร‡ฎ)่ี=ฆZฝ.œšVูcสฒษหธ งฆ’+›ร… ๘๕ฦ R{h๕฿>Ÿ;Fบะx3๑Vถ6ฑg0ย†ฅ0ฅkื๗KJŒฮงx๑Je)_ฉฆ$H !„BิŽ)!„เึฉ%~ดsWW ]>งก*ุ@กlฯŽ'ya|šฏฬ๐ญ~z็๎]ึŠฆ*\˜]ไOฅ๘ 3<ษG7๐แuฝxŒส ฉk‹’ 0GQบJo“—V_%Lฉ  ((€iูœŒอ๓๋ฯ0Ÿkผ=พnŸ—ๆ’|๒™cไJ;om{G†:YคีW S@ฑ๚ลั๙4๛Gขผ0>Mู4%H !„Bิ๊๏l RBq๋ƒิ’&—ƒƒ๎^ึBO“ฟำภจnŒ]4-นJ˜zmbŽ็Gcส7f@}vืF๎^ึŠฆภู้>๔Qฌ™#›๙พ5=ธส ฉซ R4GงฎัไฅอWYฆ6/™\š[ไต‰9Œฦ˜k ง!~jว๎๋น>?๙๔ัoZฺึˆ6t„xtykฺšn<ณz฿ลsŽNฦ๙ำใ;๔z^~ !„Bิเฯk RBq๛‚ิทกณg0ย]- 4๛hr90ิJ˜*Yษ|‰๑…สำ๖O‘)–yr๗&ถvท gฆ๘๘ำGzŒb๋r>ดzn]#–ฮqu!Mบะx3qL&่vฐต3|=.ฺPูLปXโฺB†ฃSq๖G"L>ฯอ,๒‰งPถ>8ยށVทiv;ph60ฮ๑Wงฦvวื>/?…B!๎< RBมํRKtUeว@๗๕ด2๖r9q๊jeๆFuำ์‰ล ฏ^›e[W ๋:B(ภฉX‚O>sดกว๘งทญเ;Wvใชฉ๑Dšlƒnา~e!อ๗ฎ้!์qbSูWJS”๋›iง‹%ฆ’YŽLฦy๚าd]?ต๎Wwoโฎj๘<;ณภว๙ฤฟ ่mใกพvVถ6แu่ฤณๆ๔๘ฮ?ผy๙ („Bq็IB๎\บู=หZู5ayุOณวY„Yน>ำฦPU<†Žeœˆฮ๓้g5๔์=ซxlE'NM#šส2žศ4์^Eษ,ญ่คร็&W2Kคq้ีฅ|ฺ๕0U&šส๒๚ฤ๛FขฤRนบ{/ฟถg3[ปย(ภ้X‚O4x๘|;๖ตำ๔ฯๆ9—%{B!„5"AJ!จMZrWW˜‡:XีฺDุSู„YS–~J+`DS9~m฿ ฦ้†ใw฿jŠ`hฑTŽฑDŠ|ƒ>50–ฮฑgจ“vŸ‹Tกฬ89ส™้ป;Y฿ข็ยm่่ชBูฒHหL%ณ›Šณ$ฦฤbฆnห็ูฬๆฮJ:K๐ฉxบ™บ••ญLหๆ๐•พ|๐๔ทอ}/AJ!„ขv$H !๕คBnO=ฒ™มๆ%ำโ๙ฑฟโู7]Uyธฟ๛zฺj๑r9q๊* PดlR…“‹^ฝ6วมฑณ™|M฿ำฏํูฬึฎ0 Kๅธ0ธAJQ6w6r;˜ฯ๙๚ห็Iๆ‹ธ ]ฟ–ฎ)ฌi ฒฆ-Hw“ท:cชฒ๙yพd2“ษs*–เ๙ัุ-บขฯก๓๙Goฬฤ{a|š฿8tๆๆพ— %„BQรฟฉ%H !Dฉ“งูL_ศOษ4ู7ๅw^:ฆžeญ์่`EK€fงฆกช eำ"U,1•ฬql2ฮ๓c1&j๔Dทฯ?บ…M‘fฆำ9.4๐ )CSู t9˜ฯ๘—ฯ“+™84๕}ฝๆ๒p€๕!–Uร”ฎU–๒ๅKefณฮN'ุ;ฝeaชษe๐๙Gถ0X‰wp,ฦoฝp๖ๆพ— %„BQ;ค„‚๚ Rํ>7O๎ูD_ะGั4y๖๒ฟ๛ส…ทบญ]av๔wฐชต‰ฐื…KืะชOt+3•ฬq26ฯ‘(cw๘‰n_|l+;Bุ4~rฺ๋C4น โู_=|ำฒัTๅ}ฟถฎ* …lŠ4ำUฤๆง+ฮd๒œŸY`๏p”3ำ‰๗๕ฝš•๐9ะ์งdZ๒ีร็พm๎{ RB!„ต#AJ!จฟ ี้๗๐ฤ๎๔}L“ง/M๒_^ฝ๘Žฟ~}Gˆ‡๚ฺY฿ขอ๋ยmhจJeXถd2“ฮq:ถภมฑ[ฟ ์[ฒพ๔๘Vึท‡ฐ€ูtŽ๓ ค|NีmANƒนL฿>|…สRพ[ฦ†ญMlŠTfLy—žฎhCพl2—ษsvฆrOอฟงoัโu๑ิžMืgโํ‰๒Ÿ฿b&)!„Bˆฺ‘ %„ิ_๊n๒๒ฤฎ,k๒’/›ำล ่๕K๏๚u›์Œฐก#D‡฿ƒืกก) fuใ์นls๏3jผชข๐•วทฒถ=ˆi7~jr;Xูภ๏4˜อไ๙ํฯขฉ๊m๙^ฆmณบ5ศ๚๖ ฝ!พj˜ฒl(”Mๆฒyฮอ,๒ยXŒ#“๑w๕ฺK3๑zƒ>Jฆษ3—ง๘ฝw0๏ƒB‚”B!DํHB๊/H๕†||f็บ^re“8?9z๙ฝฟ^ะวรํlŽ„้ xฎ๏Oดด l>Wเา\’#Q^Ÿ˜ปๅ๏วะTพุVVท5aZv%„M/4์๕า์q2๖ใwฬค๓|๕๐น[ฒ\๏ญุถอPK€ อ๔…|n SK็๐ย์"Fข๏8Lu<<ฑ๋ฝฯฤktค„B!jG‚”BPAj ูฯงwn ำ๏!W6๙฿็ฎ๐็วF๗๋ถ๛์่`[w ]>งCUฐBูb>W`8žไ๐•Mcข฿nCใ‹neekำฒ‰g œmเ ี๊sั๒ใw๊LWƒ”~›ƒิำถ๙ฺูฆ7่ล๏rเะTlฆP6‰g \œKฒox๊mริฒ&/Ÿฝ3๑•)!„Bˆฺ‘ %„ิ_Zเ“o โw“+•๙ณW๘o'Foู๋๛{†"JOะKภi W—œ•,‹…\‘แx’#“q๖Dษ—อ๗๕|Nƒ/<ฒ…ๅ-•งนล3…;ฒwีําpำ๔แs่ฤR9พ๖า๙;ค–M‹กฐŸญ]-๔VฯกQ}ส_%Lน0ปภ‹ใ3ผtuๆ[พฦญž‰ืh$H !„BิŽ)!„ ‚ิชึ&>๐z"~7™b™ฟ>=ฮ_žปๅ฿วmh์ŒpWW Ca?M.ฦMa*U(1žH๓๚ฤ{‡งHห๏้๛]>๗่f›”L‹™LŽKณษ†ฝ^บš<,k๒โ1tb้_{้๕qปำŠฆษ๒p#!๚C~š\7โbั4™ฯน8ปศแ+3ผxe†›๏ใLผs๎*vl๘ๆพ— %„BQ;ค„‚๚ Rkƒ|l๛::|nาล2yrŒฟ93~พŸฎ*l๏๏เž6†ย~Bn'N]EŠ–MบPbb1รks‹1“ฮฟซืo๑8๙ต=›้oฎ<อm*•c4žjุ๋ฅ'่ฅ+เมm่DSY๓ห็ฏG Z)”Lร~6Fš ๛ บšŠmWยT"_dx.ลก๑/Žฯ`ูvu&z"~ฯm™‰W๏$H !„BิŽ)!„ ‚ิ†Žฟะ:ฺ|.R…2ํฤ๛ี;๒ฝ๏Yึสฮ–ท{œ85 UU(›้b™ษd–ใSqžqm1๓Ž^s้in}AEำไ๊B†ซ ™†ฝ^๚š}DบฦT*หื_:ฎฉuqlน’IoะหหZh๖ฌ๎1/[$๒Fโ)๖DIไŠืรgถt๛fโี+ RB!„ต#AJ!จฟ ตนณ™๘เZZฝ.R…vl„ธpํŽร–ฎ0;๚;XฺDุใฤe่hJeSํLัd*™ๅ๔t‚#QF็฿zถำ7>อm,‘fj1ฐืห`ุO›ฯ[ื˜Hf๘W.ิlษ›ษ^S- „•0ฅณฒOุt:GOะG“ห ],๓Wงฦ๘๋ำใ฿6๗ฝ)!„Bˆฺ‘ %„ิ_ฺฺๆXK‹ืIฒPโOŽ\ๆ้K“59–uํ!ถ๗ทณฎ=Dปฯ…ะPหถษ–Lfา9Nว84{ำ'็๕ฝ|v็FบซOsปO2๛.—ี“ก–m^.]cb1ร๏ฝzกๆK๖Lถdา๔ฒฅ+ฬP8p}ฦ”ข@ูฒัUUศ—L฿ใ#ทuihฝ‘ %„BQ;ค„‚๚ R๗,kๅ฿฿ฟšฐวษBพศฟ~™ฝรS5=ฆf?ป#l่๑{๐:44Eมด!_*3—-p~v‘ƒฃ1ŽMล฿๐ต!Ÿน‘ฎ@e๓์๓ณ ,d‹ {ฝ …ด๛]85ซ‹~• ืŸpWฏ2ล2}!/#aVถนช๛„)ชjPผ IDAT `ู6W2ู+ตใฦๆูงงค ๅ†ฝ^ร:ชA๊สBš๒๊ลบRKR…M๎Yึสฺ๖aฅ๚•-‹๙l‘๑…4‡ฦb›ฆP6?ฐ๗ฝ)!„Bˆฺ‘ %„ิ_ฺ฿ฮฯณАA"Wไw_นภ‹ใำu5fํ>7๗ทณญป…๎&/>งCUฐBู"‘+p9žไฅ+3Lง๓|l๛:"~7™b™ฃSqJๅฦ3๖๑ป14๑Dš?|ญq‚ิ’Tกฤถ๎>ฒพงฎaุ6( Eำ"™/2–Hsx|šƒcำdKๅ}/AJ!„ขv$H !๕คv F๘7Vt;˜ฯ๙ฯ/ใๅซณu9v>งม#Cถuทา๔pื๗S*Y•อณg2yzƒ^ฮสๆูฏึ้{yงnRc๓)๐ต‹8tญแ‡ฎ*}•ฅกEห&S(แ24œš†ข@ษฒIๅ‹Œฬงx}bŽฝรัT˜’ %„BQ;ค„‚๚ R u๒“–t9ˆg |ํ๐น๋ห฿๊•Kืุ5แฎฎ0ห[4U7ฯถํส“๙–6ฯ.”M๑ยงัฐืหPK€ŸCSO๑Gฏ_ฤก5^r๊?w๏*šซ3๑๖Ot;Xำ$์q~S˜บฒแีkณ<7ฯKWfฺุfGซ‚ดxธt (Z6ฉB‰k ^พ:รั(‹๙Rร๗ค„B!jG‚”BPA๊Cซ–๑ฏท โwฬf๒งฯr|jพแฦ๕๎๎v FX฿ขลใDฉFฉฒe“.–ศห,ไ‹,ไŠ 5ใๆๆ uy.ษ=r g.ู๓; อ+บฬg |ํฅ๓ผzํฦrส‘f๖ EXีฺD‹ว…KืPU…’iUยิb†Wฎฮ๒XŒ๙lกแฟ)!„Bˆฺ‘ %„ิ_๚5=หMƒ๘:3้<ฟ๙ยNล ;พjำ ูPู<ฦฒAU*K๙2E“™Lމล,ูR‡Z›ƒUƒ”ฆ*\œM๒ฦฉซ w^Bn?yื š\๑lฏ>ว๋฿bi่ฦH3ป#ฌim"์ญ„)ญบ”/](qe!รัษ9๖D‰7P˜’ %„BQ;ค„‚๚ R^ืหoภ็ะ‰ฅsฦก3œ^hุ๑}จฏŸฝwaทƒ‚i‘ศ๑:t<††ช(XถMถd2“ฮse!iู(u~†ย:n4Uแย์"ztธ!gHตz]ุึ!ี™xฟ}๘วbi่ฦH3๛ฺYืขตฆTๅฦŒทk ŽNลy๚โ$ ๙bฟ RB!„ต#AJ!จฟ ๕C๚๙ศ๚>ผh*วWžๆย์bรŽ๏ฮ~ๆ๎{‰%๐:tZฝ.Bn'^‡†ฆ(˜6ไKeโูW3M หชฟ฿SCแM4ฮอ,๒gว†q5`๊๐ป๙ัอ7–†ๆ g9}๛ฅกkฺ‚์่`}Gˆ6Ÿw5L•,›Lฑฬd2หkณ์Ž2›ษืํ๛— %„BQ;ค„๘่_ฒ็๊่ƒ๓G7 ๐k{q• ๕ๅƒงธ4—lุ๑ฦงŽ%า”M CS นx^Cวmh่šŠeูL“xถภไb–|ูคdZu๓~†ย~:›ผจภน™ุ.ฃ๑‚Tw“‡nฌ, ฎ. =.–†ฎjmb๗`„u!ฺฝ.†ŽVc*],3•ฬrdrŽ#1ฆRูบ{ค„B!jG‚”BTข‚}t2ฮพแh]|pั-ƒ|๏๊†ฮT*หœbd>ีฐใ{๓S็ณEฎ.ฆ)šํฦพKM.Cรm่ธ ‡ช`…ฒE"W`2™EQrjซkจ%@gภƒ œžN๐฿OŒ6ไ’ฝพฺะ}i่ฏ<รน™wฟ4tEK€=C•S7…)ำฒศหL,f96gH”ษd„) RB!„ต#AJ!€ฒeู™b™ฉd๎๚็k‹™šฯOl]ฮ‡V/รญkL$3|แภ)ฦ้†฿›Ÿธ/26Ÿฦดmt๕;Eู6\n]รkธFu“๓’Uyฒ[ถT&[,Mๅ0kดœoy5H)ภฉX‚ฟ:5†ก5ฆๆƒa??ธฎQ R_>xš‹๏ci่P8ภฎม6Eši๓นฏ๏fZ6ูRe)฿‰่<ฯ^žbชย”)!„Bˆฺ‘ %„T‚TeฃสS฿&“ND็ู7\›0๕ำV๐+ปq้ื3|nษšฒ๗๋ๆง.ๆK ว“(Š‚ชผY(ฐ๑ป šœ<†ŽำPo„)ำ"S*“+™ค‹%ขษ_ฮทคNF็๙ณWะฅแฮหส–&พmOuih–/<อๅ[ฐ4ด?ไcฯP'"!"~ฯ7…ฉX*วัฉ8{‡ฃLิ๐บ– %„BQ;ค„ธ8ทhw๘8{V๒๘Š.œšฦ•…4Oํ?Y3Jซ\฿w}iุbพศp<…ฆพ}ภ)[6>‡Nุใฌ,ใำTšŠBeํlฉLพd’*–ˆฅrไKๆy?ห[t<ุภ๑ฉ8็U” Rkฺ‚‹5=ธuฉT–/8ล่-\ฺ๒ฑs0ยๆH3‘€ฯ–๒™Lงsี๐;ลX fJB!„จ RBิ฿ถ๗ vฒ1าLgภsำS฿์7|p~nxŠ+wเƒ๓}๏*]‰Cำ_H๓ไLงs ;พ?ผฑŸจ. [,y‡AjIูดqญ^Cรกi84UU(›ึ๕ูR‹๙"‰\‘Lฑ|[฿ฯŠ๊ )8:็๏ฯ7fZ฿zราะฯ8u[ฎ๏ ƒ6w6ำแwใu่hช๚†S'ฃ๓์‰ัฝา$H !„BิŽ)!„“gm€ž —]6w†้ T>8๋ชJน๚มy&ใd4มพ‘)†ใท๏ƒ๓ฟฟ5ป#šฦx"ลฯg.[hุ๑‘อƒ|฿šสาฐ๗ค–”Mงฎ๖ธ๐:tœšŠCW฿g39ฎ-fษ•สื—๙j+Zt๚=Xภ‘‰9ยต†\ฒท)า†ฅกOํ?y[—ะu๚=์Yakg ๗๕S– นj˜:Kฐo$สp๖?UR‚”B!DํHBnฉ%]ป‡*œ#7^CGื*3:๎ฤ็_|p-;๚;04•‘๙$O8๛7ftไซ3:Nลr~ๆp•ํ๋xฐฏ]Uธ4—ไำฯปํ๛"N7oาžศธฒแVฎp[ Sอ'>‡KW๑Tใ†mไห&๓ู‹Y๒e๓}=•OS†n R/]ญ)ทัxA๊พžึบXฺ๎sณkฐƒmญt๘บฆbY6นฒษL:วู™๖ G97ณpหพฏ)!„Bˆฺ‘ %„ผ}บ๙ƒ๓ฮถuท\S7ฯ่˜อ83x฿œ?นc๗๗ดขฉ f“|๊™ฃไหfรŽ๏า&ํ†V™!uๅอz3MN‡†หะ๑:FuฟชBู"‘/0น˜EUน"๏๖๗`%H๙้ x([6‡ฏฬ๐๗็ฏแu่ w^์kฟพ4tt>ลgŸ;Vำฅกa“ƒ๎YึJW“Ÿร@W์๊lทสŒฉฯฦ8Kผ๏๏'AJ!„ขv$H !๏๑๔ั†฿m_วC}•Mฺ๏tZRถlผทกใะTšŠข(ืรTพฆฆS9rฅoฝDากkt<๔…*A๊ภh”ธ0AศํhจsbZ6.๏ไ64Uแโl’Oึ้าะ หมรืำJOะGภi`ด?ุ\ฆภลูE๖D฿U˜’ %„BQ;ค„‚๗คnเผk0ยo>ฃใย์"๛Fฆ8>๕ๆ3ฆ>๗ศf6w†Q€“ฑŸzฆฑƒิ'^=|ฬg‹Œ/คั๏pZR6m\†Fซทฆœš†CSQU…ฒi‘/›ค %๓Eนโ7อrฟ›พŸ’iฒw$ส?^˜ ์q6ิ9)™฿ตช๛ KC?๑ฬั๗ตแ๛ํๆs่์Œ๐@O=A/~—‡ช`S ฟูf94>อซืf฿๖๕$H !„BิŽ)!„เึฉ%M.ƒ‡๛;ธฟทž&/—ใ]อ่๘ยฃ[ุiเDtžฯ<{ฌกว๗ๆ=ฑๆณEฦitMฉ้1•Mงฎ๖ธ๐:tœšŠCWQ•สำ3E“ูLމล,นฒ‰^…eht<๔}M“g.O๑ฯ'h๑บ๊œM‹๏YฝŒป—ตข)pvz?}ซ.p: U6?๏ UfL้ีe˜Esi)฿"/]™แ๐•™7} RB!„ต#AJ!ธ๕Aj‰วะู=แž6zƒสŒ)Mลถo|p>7ณศ ฿0ฃใKmeCG86็‰ฝวz|o+‘+0–ศ`ิ8H-)›6บฆ๖8๑.CรuS˜ส•*{%า85…Nฟ› ‚i๒๔ฅI๙โ$mพฦ R๙ฒษ‡ื๖ฒตปฒ4๔ฬ๔๚HCฝ—ฎฑgจ“m- …•๐[รญhšฬ็Š\žKrh|šรใำ|ใM.AJ!„ขv$H !ท/H-q:{ช3:๚฿bFวแ+3ผ|e†/?~ฺ๋ƒXภั‰9žwขกว๗ษ=›ธซซ˜ฯฏฃ ตคlฺ( ดTgLน ทกกฉ*ฆU™ู–ศศหZ<.๒e“บ8มำ—&้๐ป๊œไJe>ฒพŸ-]•ฅกงb >ู KC]บฦ๖v๊kง/ไ#่rเะิ๊R>‹Dฎภp<ล‘(/_นฆ$H !„BิŽ)!„เ๖ฉ›?8๏ŠpOw+ƒีŽ๊SK3:†ใIzƒ>บ›<˜6ผvm–ฯํ?ูะใ{๓žX๓นW™š/ู{3Kaชูใฤ็0p้*CGฏ.น,”-tUAืTŠe“u๎*ฯ\šค3เiจs’)–๙่ฆ6U—†žŒฮ๓้_jh*๗wฐฝฏfM.GeVP0-ๆณŽLฦ๙฿็ฎ0ฑ˜• %„BQCค„‚;ค–8uํ}ํl๏ึ3:TUมก*”-›—ฎฮ๐…งz|ฟ๐่6Ešฑฉ,ูปฒฉูฆๆ๏Vภ้ภ๋ะp:CวPEAlๆฺb–ฟ=s…k‹†ึ0็$],๑#›‡ุX]z|*ฮgŸ;ธŸ Meว@๔ด1ะ์'่v`จ•๛k:ใžใŸ/MJB!„จ! RBมRKี4ฃรกฉ7‚0“ฮ๑วฏ_ๆะXŒF‰ๅวทฒพ=t=H]]ศ 5Hฐmธ \บ†ฯat(ีMฮห–E<[`l>อ้X‚ห๑$FuVN=KJ๘ึก๋็ๅศไO๎=๑บฏuUaว@„{–ตฐผ%€วะ‰g ™+<7<%AJ!„ข†$H !ต RKี๗๗ด1๖ำ๊uกVƒ‡iูLgr\žK๒๒ีYล([๓ณ[Uพ๒๘Vึถ1mHd \[lฌ ตฤฒlŠฆลๆฮf\†^๙m(™ฉB‰ซ‹NF ฯ%กŽ฿bฒPโ'๏Zฮฺถส^eฏ_›ๅฉ_๚ฆ์๛;่ z‰g œŠอห’=!„BˆZ&AJ!jค–่ชยwฌ์ๆวถ แsืgI-…ล|‘‘๙/ŽOsplšฒeีุ๊ชสW฿ส๊ถ&Lห&‘+2ฑ˜Amภ Mๅุiฆร๏ฦฒm2E‡ฆเิ5EกdZค %&“YNO'ธ8“คh™ืcฝHJิถฌikยดแีซณ|ภษoซ๛^‚”B!DํHB๊'H4ป<๕ศf†ย~l f%fผ9๓bพศ่|šฃQ^Ÿฎ๋S.]ใKmeekำฒ™ฯ™Lfiะล\ฆภบŽ >7้b™รWfะU…•-M„=N\บ†ช*”M‹LฉฬT2ห‰่<วฆโห~งQ๏#](๑ำwฏdU๕ผผ|u–/>๊๊พ— %„BQ;ค„‚๚ R-^OํูD_ศOษ49;ณHฎTf0์'ไrโิU hZ,Tริ‹Wฆ98ฃhึ฿Œ)ŸC็ neyK€ฒe1Ÿ+MๆP4H-ไŠฌn า๎s‘*”929‡Kื๐์yt%w}็OํUwืฺRki๕ฆnป๏ฦX†8!&ยd&v ž $$มa˜็<99Cกำฃ์CN†yf’ฦ6  ุํ}มฝช7ต๖ๅ๎ทถ_ี๓วฝ’ป—n[Rj}^็p’CิาญบUาอ๛~฿าUคu iCCJWกซ2dIZZE5Yฎโนษ<›ํ‰ศรTล๕๑๋1ุž„๘—Sำ๘โรฯฎฉ๛žAŠˆˆˆ(: RDDhฎ ต.eแ๗^‰ น!๐ภัqำ gp๙บ,ฎํiวึถ Z,บข@’๊ณ‹๒ถ‹ใs%<:6‹๏Ÿ€ใ‹ฆ9ทYSว็nฟ ›2๐D€…šƒษr-ถืJล๕1ุžAGาDษ๑pdถO05พกศฺ“’šSS`žฆjžภLลฦ๓Syป๗*llMร๕'าMWโคl_`sk}๐|ั๑plฎOชฒ๔5พ!I๕cO้,Mฅ)Pd"a๛sU‡gŠxไฬ f*๖ช‡)๘ภ ƒุZ…Ÿ˜ฤ๐๙5u฿3HE‡AŠˆอค๚sI|jฯ่อ&a๛็๐:6ŽŽคน๔5%วCWฺย }ูEz}จ67Qด]œสW๐ร“S๘่$jžู๑tฆLUุุ’‚'fชf*vlฏ?1Kก=i `{8ฑP‚+่_็}ญฅ0ฅยTXš M‘†!_`ฎ๊เ่\ Žอเlกบjaส๑~๚mKก๐{ฃ๘“๙ษšบ๏คˆˆˆˆขร ED„ๆ R๘ไž+ะ“I ๆ ๏Nใ๛'ฆะ–0~๊kKއŽค‰7m่ฤถ๖ ZCต%I‚+”l'๓๋ฉi<|b%ว[๕ใYŸNเำท] น\!0]ฑ1Wuโ{ฑ„๕hุš0ท]œZจภ4Ezญ†ฌก#ฉ+05 Uถ8จฏoป<:[ฤ3“๓81_†ฉ)+zŽ/๐มถc  :6/่…5u฿3HE‡AŠˆอคถดฅ๑๛Cปฑ>@อ๓๑?r?:=ƒKลSr60 ŒQŸ/•ิT$tš\S^P‚โษ…2ž™\ภัูโRดZnž๐มถ7ซ์O|hM๗ RDDDD~ฎf""jฎ 5ุžม}ท๎FwฺBี๓๑?ž;…วฯฮ!cพ๖Vฎล0uMO.๏ฬข=aย8'L•ง๓e[จไxhต \฿ืŽ9ด'อ๓VL•c… ~tz฿=>ผํฎุ๑œปโห๑&ส5V๐็ญ†\ 9KGฎ>?q‘=j‰/B$tํ –ฆภP่Š I’เ‰eวรxฉŠg'๓84S€+dIzรว`๛ฟyำeKณส๙ะลcGืิ}ฯ EDDD)""4Wฺน.‡฿}ห.ฌK™(9>้Qš) ฉซฝJއฌฉใฆ\™Cวb˜’%๘Kซp*xไฬ,FF'0ปณถตg๑๑[wa}ฦBอ˜(UQŒ`–ีrhI!g๊(ิ๊3บ‚ฐTฝ7ย! UFGาDBWก+๕0ฅ4ซŠ็cผXลำ“๓x์\?xCะkžผใผYeร[S๗=ƒQtคˆˆะ\A๊Š๎V|์อ;ะ™2Qr<อSฃ8>W‚๕†\—CรMุฑ๎ลSŠTj\ษ๕p&_มcg็๐ใ˜]ฦงเ]™ร๏ฝe'บาชžภxฑŠฒ๏ ตฑ%ฌฉ!_sq2_^ึ๏ํ‹บ*ฃ-a ฉฉ0T†*C–$aˆj#๊=7™วฃcณจy๋ Sืรวnูyฌฒฟ~๒๘šบ๏คˆˆˆˆขร ED„ๆ RWฏoรoฝ๙rt$M๙ฤ1Œชะ—aธ๕b˜บฎทปบZะ™4aj*ไF˜*ปฦ UwVู฿>5Š๏'งืิ}ฯ EDDD)""4Wบuc>xร6ดX:ๆk.๔ว/ภ๑W'เ”š"ใฦพ\ูŠui MYš[ดฆžš˜วGว/hลิ-๋๐กF`+;ฺไ•@ IDAT>Nๆห๐ƒ๘)SUะ—M"กฉ(:๕RRDฏ% ดQ฿ฦ—ิT$tZckง(4f\=;น€ฃsลฅmŸsUYSรoฟyวyณสฯกฑ5u฿3HE‡AŠˆอคn๗_7ˆœฅcพ๊เห?>ด๊+ŠJŽE–pS'ฎ่jAw&ฑฆDข๊๙˜,ี๐ฤ๘<<6ŽฑBๅฟืะฆ.๚๕๕ภVr}œ˜/!ˆ๑฿ž„ฆข'“@BSQp<œ\แRB!R††S‡ฅฉ0Tyiพ'”\c… žŸว 3yฬUฌK™K[) ถ‡ลทœ]S๗=ƒQtคˆˆะ\A๊Žญ๋๑kื"kj˜ซ:๘ฏ?:ูŠขล0uCoฎ\฿Š๕๓โV>ฉr OMฬใ;วฦqโež8ทwหzผ๏บญศ™:Jއั๙2Bฤ๗oOJืฐ>mมาTฃ๓eHRsผ6_„H่ ฺ&,Mก*ะ’TŸ Vv<Œ—ชx์์๒5ฟtๅ&ด5f•ํ;x_S๗=ƒQtคˆˆะ\A๊ฮmฝธ๗š-ศf*6พใCAด/ฏไxะื๖ถใช๎Vtฅ-$uŠ,Ÿทb๊้‰y|๗๘Žฯฟ8่๛mƒ=๘ีkถ"kjซ>|%คu ™,UAม๑pbพิ4Aj‘/BชŒŽค‰„ฎBW๊a๊™`EวC{ย€ฉ*Xจน๘ณGใแ“k๊พg""""Šƒš+Hฝ๓ฒ>๒U›‘^ R?:ั$ฟซƒ0„.+ุั•ลฎuญXŸฑ–VL!P๓|L”jxfr฿9VS?ปฝ๗\]lEวร๑นๆ 8#k๊่JY0Uวล‰ˆ†š__„ะUm IM…ก*0Tฒ$! Y Iฐ=ฟz™k๊พg""""Šƒš+HŽ~ป+6#mจ˜*ืWH5ใ๏jM‘qyg—wถ 7›@r)L…จySeฯLฮC!๎ฺุƒดกขไx8:[„,วทHต˜::ฯ RMดe๏•๘"„"KhOH4ยิโ๛abบbใเุ,พb OMฬฏ‰๛žAŠˆˆˆ(: RDDhฎ u๗ฎผg๗Fคt“ๅพฃCM}๎ Eฦ`G;ืๅะ›M"uฮVพš็รา†M–Ph)%ฦAชี2ะ™2a( vc…TLว! Ckฌ๔2!5^bHœซ:8<[ภ๗ŽOเฑณs—๔}ฯ EDDD)""4W๚ล+6โ๎H๊*&J5|๙ว‡‡ก+2ถถgฐปซ=™Rบ M‘๋ซปัร๖N,”Pv|จJ<ฃT{ยDGา€ฎฤg…ิK๙ข ฏ๏๋€ฉ)รAB‘๋๏—ใ ฬU]Ÿ/โ๛'ฆ๐ร“Sธ?-0HE‡AŠˆอค•›qืŽ~XšŠ‰R_๑aฤiA‘"I์ศโส๎ฌฯ$5๔๓ถ†EวรLล†/ยุ…ฉŽค‰๖„MQPlากๆยB ถg14T]“ๅrฆ^_อฆศWXจน86Wฤฃcณ9>G—ฬ}ฯ EDDD)""4Wบ๗๊-๘นห๛aฉ ฮซ๘ณGAŽa๑ร:ฒx๛`:“๕ญa!„pEว(ปๆช\?ˆM˜๊LZhKะล˜mู;ถดฅ‘648~€C3(ฒ„ดก!khH่*4นฆผ @ั๖p2_ฦมฑYฆ›ฮซxfb฿ภ‰…rlฮƒQtคˆˆะ\A๊บ้2พฅšขเไB~๐๐า,Ÿธ™ฏ:๘ูํฝธm๓โ๑”๐ง?>KSQq}์๊jมญh„ฉ๚S๙๊3‹ฟพ•oฎ๊ ๆ‰ฆ S๋ำ ดX๕AํEวํPsU–ฑฉ%ซคž™ZXฺš๗r|BWdด% $tฆชภPeศ’„ Q๕ฆJ5<;ต€๏Ÿ˜ยOฆ๓Mคˆˆˆˆขร EDเ๖}ไ%ูfx-yำๅx๋ๆnhŠŒ๓%|ํเ‘ุฎ*ุ.~v{†6vASdŸ/โฯ~|I]]๚WุึžมฎฎlnM#m๊ะd้œ0 ๊๙˜ญฺจนั‡ฉžL9ณคJއั˜ฎา-iXชาุฒทpAื™/Bศฒ„Žค„ฆยTUXš E’ ยถ'0Su๐ยtŸ˜ฤ“ใ๓M{คˆˆˆˆขร ED`hx$'๎G•:L๖›wเึsฮพƒG_uๅJ3+ปฑญทl\U–qtถˆฏ{0HE‡AŠˆ่e P…|ฟ,แžีูฟu8Gf‹ุ๘11 RŽ/๐ฮห๚pc_Yยก™พ๒ศadM‚ํฆึ4ฎ^฿†ญ)dM}i––ิรTล๕ฑPsPv}จซT…๚ฒIdM€ผํโtพหR)]Co6CQP๕|™-.หqd  Mตฆืฎ+ไk.Žฮ๑ุุ,พ;: ว‘ž)"""ข่0HฝŠ(ยิ'†vใฆฮ_>~ บชฤ๒๙A€wl๏ร๕}P$เ๙ฉ<พ๚่ดX๚ุิ–ฦ๎ฎ ถg]ฺส๗b˜ชy๕แ็ืฟจmgฏG6‰L#Hอื\œ-Vb๙d =™4EAอ๓qxถ๐บWHฝTึฟฟฉสH้บz^L,ฺNๅห886‹‡Žฃ์๚‘œ)"""ข่0H]€กแz ธuฅึ์น7๔ืฮOฆ ๘›'วvห^†x็๖>\ ภณS ุw๐Z,ใขฟWล๓ฑ1—ย5=mุา–A‹ฅŸท•ฯjžภlี^ัSนิา–รนชƒ‰R5–๏MฮิัN@Sไ๚ ฉ™ไe>g"‘าUไ, Mก*ะ7Qr<œ-T๐ศ™YŒœ˜ฤlล^๋“AŠˆˆˆ(2 RDDa๏พCฒ,฿ SŸนํJ\ภ๓ำyํSฃฑj?wYฎZ฿ ภำ“ ๘oEฮิ_๗๗ซธ>zณ ิ฿‰MญiดX๚า–F7เxj~}ลิJ„ฉ  ˜ญุ˜,ืb๙พดZึฅ,hŠŒŠ็แศLqลV—๙"„ฅ)hOš็‡)I‚/”\ใลž8;‡‘“+ฌฮช3)"""ข่0Hฝ+ฆp๏Uธฆงpž\ภืŸ=UŽ๏ ฉปvlภ•ญ<51ฟzโุอz-ฯว†\ื๖ดcK[นฦV>Iช?ฑฏโ๚๕x>JŽทlฑe1Hฆห5L—ํXฮjKิƒ”*หจธŽฬW|ปฃ/BชŒŽค‰„ฆBo„)EDขโ๚/ึ๐๔ไช๎๋S2$lhI!mจ!0^จbฎj/๛์ฅีฐ.eก=a@‘%”GๆV/H-๒EYฺf#Lฉฐ4Š$A„!lO`ถ๊เ'ำ๕0๕ไ๘ฒ|)"""ข่0H-ฃๅS๙mืœทข่Ÿล7H9พภ/_ฝ—wf!Bเ‘ำ3๘ฦ๓งิี๛™%วรบ”…7m่ฤึถ ฺ: U$IpE€ฒใกๆีท๓•]ขถษ’„\ )C…BŒช˜ฏ9+พีm%tฅhKP$ ไ๘8:[„ชDsพ!K@kย@Rื`ฉ ,Mชศ‚ถ/0_spdถˆ๏Ÿภมฑูe๙น RDDDDัa""Zท๏เฃpฟ$#{Qฟ”% _|๛5็ญ(๚ๆแฑุžGธ๗๊-ุ‘B๋้ำ งai๊Š์’ใก+mแฦพ ถgัšะa( dฉ„ทช๋ก์๚จy%วป 0ฅH6œคNๅ+ศ๎ชฏ,zฃB=้Zd%ืรัูbS<อQ‚„ฌฉ!กฉ05 M…&K8~€๙šƒcsE๐ไ4~pr ม๘ร EDDDแ็>)"ข•14<’“๗ฃJ€^h˜Rd _|๛ตK+Š=3ƒGฮฦ๖ธBเWฎูŠม๖, ภONแ[GฮยT•U{ ‹aฺ๊žv\ึ™E[ย€S^#LU\5_ hฟz˜R% -)คt ~เฤBEƒฆฤ,H…@_6‰œฅCPt<›+5ีq„2F=LYš‚คฆ. ๗๗‚๙š‹ฃsE<~v฿=>3คˆˆˆˆขร EDดย.&LŠŒ/ผl๏ศB!~tzํฑปBเ}ืbs[~เแัI1‰้ฒš฿“AŠˆˆˆ(: RDDซlh๘ภ€*ไ๛_.Lฅ Ÿฟjlmฏฏ(๚ม‰)Œœ˜Œํฑz"ภฎ฿†-)ธBเกc๘แฉฉฅญWQ*9ฒฆŽ›7t6ถ๒™ฐTฒ,มo„ฉ๚S๙๒ถ ItEF.…„ฆย‡f ฐ}cท .‡ล •3u„ ถ‹“ ๅX g๗EKSะž4—ย”&หK๏[ู๕qถXล“ใsฤ™BๅฟƒQtคˆˆ"๒ra*k๊๘Waskž๐๐‰IเไTlั>xร6lศฅเoว#c3Pคๆ ‹+ฆฎ๋mรฮu-hOึWLษเ!jž…š‹’ใกโ๙ุั™ƒีRฯOเ ฑช3ฑ–รนA*Pจน8•/ว๊iพaจ2ฺ“&’š ]‘กซ  aˆŠ+0^ฌโ™ษy|otฃ๓ฅŸ๚ RDDDDัa""Šุร^‰ ทถ% |v๏Uุุุโ๖ใ๘ืำำฑ=6๘เ ั—Mย๖พyx OŽฯA’š/|”Cว }ํุฑ.‡ฮ”u^˜*ปfส6:’&ฒฆG<;™‡˜Zผ‚”„ุุ’B‹ฅC„@พๆเLพ9fO ๊aJSdด% $u†ชภTeศ’„ Q๕ฆห5<7•วร'&๑T~้฿2HE‡AŠˆจI์w`จ+“ธฎบuq‹ƒว&๐ศ™™ุ“C|่†m่อ$Q๓๙…3xvjกฉ_sษ๑ิUุื]-X—ฒฮส'Kาาฃ3๕ี^–ฯR-–„ศ.ฮชˆaZโ‹’t$M$uฆชยาd(’ถ็cถ๊เ…™ฤใs RDDDDb""j2ว็KCนิŽท~๛ศ8;;฿ƒ ธ ๋ำ ิ<๋…ำ๘ษt!/ฝไxฐ4o๊๏ภฎฎt&MXšบดญ-0WฑqถTยz|‹‹—ฉ๙š‹๑b’๛g1LีWLiฐT–ฆ@UdAGฬU-โ;วฦ๗|mืŒ๐ทั๊c""jRืื7ษNNmHZ<ศ๘เ ฑ>cกโ๚๘ฦ๓งpdถซc(9LMม}ธฎท=™ไFน ย๚Vพš ๆ๙(ุn,ยิ‹Aส€˜ฏ:˜(ี.‰ u๕'!cjHh ,M…ฅฉะe !ว0Wต๗๔f“#mCDDDมg5)"ขๆvว๏Mฺg{2V_ย”,บa;บาสฎ|๖$Žฟฬp้8(9ึฅ,ๆ›.Cช๑>, AจyUฯGพๆ"@๓}RนFšญุ˜ฎุ—์=ศ,MERS‘ะจฒŒแU–G๘[†ˆˆˆh๕1Hลฤb˜ฺิš๊ำ9ฏY‘d|่ฦmX—2Qr|รณ'prก๗ oป๘[wa}&?Qt<่ŠŒ„ฆ.=ญๆ ุพ@ู๕1[ฑ†€ช4ืาฃ 1ะ’Fฮาแ‰ณU3—pZ:๎0Dฺะ5uXชŠ0 ๗ไ,}„ฟ]ˆˆˆˆVƒQŒ ไฒZ๘;™ไGR†šj๖ืซส2~ใฦm่Hš(9๎้QŒชฑ=Eวร}ท๎BWสBี๓๑ƒ“Sธผ3Irf)oช,มร”฿”a*B ดฆ3 xB`บbcฎ๊ฌ™๛ศB$4Oœ๓หWoแo"""ขีว EDCCร#นžคr_ปi|ธ™ร”ฉส๘ภ๕๕ Ut<อ“ว1Qชล๖ผW\ฟ๗–K[ŽอยT่ŠŒึ„”ฎ"กi็?อจy>*ฎ™& Sa ดค3uธB`ฒTร‚ํฎฉ{จๆ |ๆม'๘”="""ขˆ0HลXณ‡)KS๑๋ืข-a oป๘ซ'ŽวzkXอ๘ท์\ฺ‚๘ิภิ€,Ihฑ๊ม,Mฉ*Pd Aย๖ุž@ู๕0[ฑDฆฮ RŽ˜(ีP`""""ขUฤ EDt >0ะe&จ3iผท™Ÿง ๏ฟnญ–Ž|อลวaก฿ญaฎ๐ฑ7๏@gชพ๑๘| Ž/`จสy_งHR}NQc€ถฅ)S!?hฬ˜๒0Sฑซฆฮ Rถ/0^ฌขไzk๊žฑ=O3HE†AŠˆ่าla*c่x฿u[ัb้Xจน๘‹วŽฦz%Ž๘ํ7๏Xš‰5:_†ใ ่๊ห™_ S ญพbสj<อB8~}๘๙โV>„ซฆฮ R5_เlฑŠ ƒญ")"ขKPณ„ฉVหภฏ\ณ9Kว|ีมื;‚ฒใว๖ผaˆ฿บyฺ“ŠŽ‡S eุพ€๖O=”% YCGBWaฉ‹aJBŽ/P[ๅ0๕า 5Vจ ๊๙k๊ฑ}O?ภ EDDD)"ขKุ}†ฺ’ๆ็ึฅฌ›ฃSํI๗^ฝYSรlลมื‰u๘|ไๆหั–0Pฐ=œษW`๛โ‚’ YS;gล”บฆ\ภ๖|Tผ๚S๙<ฑra*M-)dM5ฯว้|ถk๊p|O1HE๗ูšAŠˆ่าU˜๊L™ธ็๊-ศf*6พ๖่ิ๘†U–๐oบ ญ!ํc…j=HษŽร”ฅ)Hh*šฺ~^SŽ/Pq=ฬTx"X๖0„ภฆึฒ†Žช็ใdพ Ok๊žpŸzเq)"""ขˆ0Hญ!{๗ส%ฬ/ญO[;W#Lญฯ$๐๏ฏ„ดกaบlใฯใ eจ ~ใฦํKCฺฯ*pEE~}มH†„ดก!กฟฆTEF„pDืจx>ฆห๖ฒ†ฉ 6ทึWH•]'ส๐)""""Z= RDDkะ๛ผ7mhŸํษX}+ฆDbcK ๏ฝbRบŠษr ่‘XฏฤIh*>xร6ดX:๒ถ‡ำ๙2 „;‘ิSI]i<™O…ึSK+ฆผ๚Œ)ืใa*€อmidM %วว‰…‚5๖yภเ RDDDDQa""ZรริฆึTŸƒน/–lฯโ฿๎@RW1Qชแซ†ˆ๑฿ดกแื "g้(ุ.Nๅ+Ai™vิ…!OๅS`้0%KCภ ‚ฅง๒อVl8o LีWH-)ว็Kk๎ฺg""""Šƒแ=๐๛ปRึง 5ตœฮu9ผ{วXšŠ‰R_}๔HฌWโไLฟvVไLรษ…Vโhยศ˜,UAาะ–ยTžเŠF˜ช:ฐ=qQa* Hภฦ\ 9KGั๑0บƒ”'|’AŠˆˆˆ(2 RDDษ๕$•๛ฺMใรหฆjžภ5=m๘7—๗รRœ-V๑ีGว๚ต& ๊5[‘55l'V6ไ„าบ†„ฆ ฉซH่๔ล0ิท๒U=™Š}มa*Bศฒ„ นZ,}UŽฃy"ฤ'ฟƒQDคˆˆ่<หฆชž๚:๐ฮํ}0Uc… พ๚่‘e…sŸXด=ŒฎRศ C ฅซีR ’บ]‘†/ฮ˜บะ0ๅ!tEF_6ู˜…ๅโิBkํำ€/B|‚AŠˆˆˆ(2 RDD๔ฒรT›ฉ๕ >/ปnX‡;ท๕ยPœ.T๐•GA•ๅุž“๎ด…pีfคW9H- ‚iSCRSai*Rz}๘9P฿"้Šืร\ีEี๕_6Ly"„ฉส่ษ&—žxชPมZ๛<เ!>q€AŠˆˆˆ(* RDD๔ช†† t™‰?๊L๏ฝ˜0Ut<ถนwl]CQp2_ฦW= -ฦAช/›ฤ{ฏุ„ดกข`ืg/Eฑโk1LYชŠคฎ ฅkKกฯ ๊aช๊๚˜ฏ9(ป>ิs่Šบ"/mู›ฏน8/ฏน๋šAŠˆˆˆ(Z RDDtA.6Lๅmo์มอะ'J๘ฺมฃ็ล‘ธhIแ=ป7"ฅซ(8.F็ส‘nAAˆดก!ีx"_RW๋[๙๐โŠฉšW~^i„)วPe›าศ™:ๆซŽฯ—–VZญ"๑๛ RDDDD‘a""ข‹RSๆ—;“ึฏฆๆซyY๖l๊†ฆศ8>_ฤ_>~ RŒ‡HmnMใ๎]Hh๊าำ้šแpD"ฉซhKฐTฆ&/ญDsƒŽภ๖|LWmŠ,aฐ=‹ฌฉaฎ๊เ๐L ]]Sื1ƒQดคˆˆ่uูป๏ภP[าบ”u๓ห…ฉูŠw๏ภ[6ฎƒ*ห86Wฤ฿ำ+ แ!สއช็ฃ๊๙(9d้า S!€“AŠˆˆˆ(* RDDดข\|T๎fr!๛็Oล๚Xฎํiวืว6H@อ๐ƒื๗vภิˆ €„ะd’xAˆŠ๋กโ๚จyEวฝdริ๏1HE†AŠˆˆVœ+‚“๓ป'G?–2ิT\ใ๚vฑu=4EA1ฆAส๖„ธฒป –ช`กๆเ่\ ฝฺูtEฉ‡) ๊๙จx5ฯGั๖pฉu))"""ข่0Hัชษ๕$•๛ฺMใรq S7๕wเถอKAjtฎปyKถ/ CยฮฎXช‚๙šƒcsEช‚Vห@สะj @—ธAˆช็ฃๆ๚(ป>สฎwษ\ RDDDDัa""ขU74<’๋ตค/ด&ฬฆ -6ฏ๛ๆ ุณฉš"วv…”ใ hฒŒห:s0A๊๘\ a}š,MEgาDBWa( tE†,KK+ฆชฎJcฦT1HE‡AŠˆˆ"34|` หLQgาxoยิ[ึแึM]Peน๑”ฝR์ๆ+น~CUฐญ#CQ0WupฆP9/ฌ-?oOšH6ย”ฆศ%ภBิ<ฟ>cส(ุnlฏ?)"""ข่0HQไโฆ†6uแ–u็ฉ2bถcฎะTlmKCWฬีœษW^vฅ—/B่ชŒ๖„คฎมT:LีŸสฯ0ล EDDD)""jw ?xe‹กืu)๋ๆf Sทm๎ฦอ:กศŠŽ‡ัน2d9^็ุ!R†ŠM-)hŠ‚๙ชำ…๊ซ†5_„P IIM…ฅีgLษง๒ีผ๚๙*ž’ํ!@<>[0HE‡AŠˆˆšฮ}†ฺ’ๆ็š-Lพe=n๊๏h)ฃsลุ 5๗ƒCร†\ š"ืท์ๅหt/ SฆฆยPd(S5O ๆืท๓A“ฦ`""""Šƒ5ญf Soฺƒ๚; H@ั๑p|ฎ%fAJ!r–Žพlช,cฎjใtพrQวแ‹Š,กณ1cสT่ชฅฑ•ฯ๖ลy3ฆš5L1HE‡AŠˆˆšฟxเ]YS{2V_”a๊g{p]_d%ืร๑น2”˜mู ‚- =™TYฦlลฦ™Bๅu…ตล0ีž4jฬ˜2Tฒ$A4ยTีจy>๒Mฆคˆˆˆˆขร EDDฑqว๏Mฺgฃ S?ปญื๔ถCF}…ิ‰๙R์ถ์!ะž0ะถ ศf+N*P฿ภq๘"„,)IMƒฅ)0^ฒbชๆ T=๙š43ฆคˆˆˆˆขร EDDฑณฆ6ตฆ๚๔U\ข๔ฮํ}ธบง €ผํโ๔+<ฎ™…!ะ‘4ฑ.eพค๒จส?_„e4fLฝฆTY‚ิgLูพ@ู๕0[q†X–Ÿ๛z1HE‡AŠˆˆb๋฿ํ๗>7I~$eจฉU๙y—๗ใส๎V@พๆโLฑ)†็ญ3iข#eA‘€™Šำ๙*ดe Cพ!I๕0•า5ชK“กศ2D ๆจy~=LU ข0ล EDDD)""Šตกแ‘\ORนฏ4>ผาa๊] ˜ฏ:/UcyฮบSZ“&dณUง๒eฌฤJ3_„€t$Lค ฆชยT๋Oๅ ย5/€x*฿tล^๕0ล EDDD)""บ$ฌF˜z๗Ž ุีี‚ภlลฦdนหsี“N %a@jว้Bฺ n}๔Eˆ!:“’บ KSai๕แ็Aย๖ุ^}+฿Lล^ตญ| RDDDDัa""ขKสะ๐.3๑GIใฝห9๘\๐๎ุน.‡ภLูฦt%~A* พ\9S€ฦS๖–wห+๑E3วโS๙,Mฅ)ญ|๕แ็Žb˜ ‚• S RDDDDัa""ขKาr‡)Y’๐ ;7`วบDL•j˜ญฺฑ;/A ไ’ศš๚าJฏฑb๕ =e๏b-nๅkOผฆLUชิร”๋ ิฮ~.‚pEยƒQtคˆˆ่’ถ\aJ‘$ฝk—uf!‚ฅๆkN์ฮG„ุุšFฦะ" R็}ณ $4–ชภิ๊Oๅ B,…ฉŠ๋cฆb/{˜b""""Šƒญ {๗jKšŸ[—ฒn~=aJSdยฮl๏ศ@!ฮซศn์ฮƒBljฉภ\ลฦูbŠํ๓eHศZ:,Uฉว)MY~๎๚l_ ์๚˜ญฺ๐ล๒„))"""ข่0Hัš๒zร”ก*๘…0ุž„8Sจ ไxฑ;ล •55ˆฐy‚ิ"Y’1๊๘’Zžป•ฯ*ฎ‡้สS RDDDDัa""ข5้bร”ฅฉx๗Ž ฺุž8ตPFล๓cw็ฉ ฤ\ีiช ตH–$ค ษฦjฉ„ฆBUdAWิWL-nๅ๓D๐บยƒQtคˆˆhMปcƒ๗ฆ ํณ=ซ๏ียTRฏฉอmx"ภษ…jพˆ๑พ\/V!7Y:Wึะ‘ะ๋QสิThฒ„0ฤyajถjร๕/.L1HE‡AŠˆˆ/†ฉMญฉ>]‘๊ž64ตc6ตฆแ‰ว็‹pEปใ|1H้๐ƒ๓UใฅšธGB9Cฏฏ–าUX0„€'8B ์๘˜ซฺp.0L1HE‡AŠˆˆ่๏๙๛‡฿฿•ฒ8eจฉs๛ฌฉใฎhIรGๆŠA†žค<`กๆ`ขTƒ$ล็า†KS‘ิU$ฯ SฎเŠท๒ฝV˜b""""ŠƒัK ไz’ส}ํฆ๑แล0ีb้๘๙0Kม/L)~ว„ภฦ–ิRšซ:˜*ว+H-J้Rzcฦ”ฎAWd„a}ฦ”ใ T=ำๅWS RDDDDัa"""z‹a*ญชฟ1ุžIฟkG?6ไRp„ภ๓S๙ฆ~!ฮRณUำ;Žm †@ฺP‘ะ5$รฯuEF,…ฉŠ็cฎโ ๆ‰๓ยƒQtคˆˆˆ^ระ๐HnCZ๛่พ๕Šฯ๔e“ฐ}g&`จr์Ž% –rฆWฬTฬVํุฟGA"ณ8cJS‘าUจr๑‚Ž โy˜ฏบ(9. Ua""""Šƒั:™/๔e’๗พธ็ฉ‰9Xšปcxišฎุ˜ซ:—ฬ{!าฆKUll้ำaXSฎPu}L•k๘o๓เฏฝm„W6ั๊c"""บHeืxุ่ฤฺฦ/&๕xEฉ๐œ-{Ž_R๓5็’{‚ Dาะั5˜šŒิโŒ)ิท๒aˆƒcณ{nุ5ย+šˆˆˆh๕1HฝNCร๎์๚U๋ฎK˜:7HูB`บdcมv.ู๗H!Rบ๚โv>]…กิท๒9"ุcชสฏd"""ขีว EDD๔ํw`่ฮํ}_บฎท}gณ‡ฉ06ถฆ5tุพภTน†ผํ^๒๏Q=LihM่ฐT†*C•ๅ=Š,๐ &"""Z} RDDDห$.aj %ฌกม๖&ห5ึ@Zดธb 5๔=๋3‰^นDDDDซAŠˆˆh™ํw`่๖มo๊๏ุุŒajqห^อ˜(ีPt5๗ซxr|nฯงzๅฏX"""ขีว EDDดB๎ุเฝC›บพxห@gg3…ฉล U๕&JU”oอฝ7๓Uyไ้=ฝ๏ํ#ผR‰ˆˆˆVƒั [ Sทo้๎Td)ฺ?6ถค‘15T]๑Rewํฉ…š‹/|AŠˆˆˆ(ฒฯฅ RDDDซใณ฿}๚‹ทm๎-KSดศ๐ุุšFฦะPu}œ-UQq5๗^lŸ.ƒQdŸKคˆˆˆVฯะ๐H๎žฝ_lหE˜’ acK SCล๓qถPEี[{Aชh{๘wŸb""""ŠƒQข Sฒ$a WReืวูB5_ฌน๓_r<ง๏0HE…AŠˆˆ(BCร#น_ฺัื;r๏Xม็Š$aC.‰Œฉฃ์๘+V`ฏม Uv}|๖ก'คˆˆˆˆ"ย EDDิ†† ฝ}ใ]น=+ฆTYBถฑBส๑qบP+ึ^ชธ>AŠˆˆˆ(2 RDDDMdฅร”&ห่ห&‘15”\g๒k3Hี<ฯ<๘ƒQDคˆˆˆšะะ๐Ÿา๗Oื๕ถ๏\ฎ0†€ก*่ษZศ:Jއำ๙ ผ Xs็ื๖>อ EDDD)""ข&ถw฿ก;ท๗}i9ยT–ฆ`}:ฌฉกh{8S(ร ึgว๘ิ RDDDDQa"""ЁๅS"‘ะT๔dศŠŽ‡ำ ๘แฺ[!ๅ๚เวคˆˆˆˆ"ย EDD#{โwฝus๗Wo่์ผุ0ๅ!š‚พliฃพB๊Tพ ฑ? ธ"ภ|›AŠˆˆˆ(* RDDD1tว๏ฺิ๕ล‹ S~ยR๔็RH*Jއ ek๐ณ€'|’AŠˆˆˆ(2 RDDD1ถฆn฿าฉศาซ~ญ'BชŒMญiคteวว่BiM)_„๘ฤทc""""Šƒั%เ“=๙ๅ;ท๖ผ฿าํ•พฦ4Yฦ`{ MEล๓1:WB€5ค‚Ÿ8ภ EDDD)""ขKฤะ๐H๎žฝ_lห๕raส๑ศฐฃ3KSQ๓}-!\ƒAJ!~ŸAŠˆˆˆ(2 RDDD—˜W SŽ/HุีีKU`๛‡g k๒aˆ๛พล EDDD)""ขKิะ๐H๎๎ํ฿ุ•“ิUุž\ั SUP๓Ž0H๐J!"""Z} RDDD—ธกแwo฿ธส๎–=๓Uoฝคฯ ญมs„ภ}฿:ศ EDDD)""ข5bh๘ภภo^w๙o\ก(จz>ŽฮืไนCเใ RDDDD‘a"""Zcชž?ค+สฝ๕Tพผ&ฯƒQดคˆˆˆึจ#ณลก๕“ำ|cวUI]]sว{฿d""""Š ƒัทw฿ก;ท๗}้บ๖k)L1HE‡AŠˆˆˆw์๐กM]_ผe ณs-„))"""ข่0HัyึJ˜b""""Šƒฝฌล0u๛–๎NE–.นใc""""Šƒฝขกแ‘อฝูฯ฿นต็–ฆh—าฑ1HE‡AŠˆˆˆ^ำะ๐H๎žฝ_lหuฉ„))"""ข่0Hั[ S[Zำ๏‰๛|))"""ข่0HัE>0p๗๖๛wwๅ๖ฤ5L1HE‡AŠˆˆˆ^ท8‡))"""ข่0Hั64|`เฎมฏ_ตพํ๚ธ„))"""ข่0Hัฒูป๏ภะ๛พt]o๛ฮfS RDDDDัa"""ขe‡0ล EDDD)"""Z1{๗บ}ฐw›๚;66[˜b""""Šƒญธ;๖?x๏ะฆฎ/2ะูู,aŠAŠˆˆˆ(: RDDDดjริํ[บ;YŠ๔ต0HE‡AŠˆˆˆV๙sŸผyC็g,Mัขz RDDDDัa"""ขH ไ๎ู๛•มถฬ]Q„))"""ข่0HQคข S RDDDDัa"""ขฆ04<’๛ฅฝฝ#๗Žี|ฮ EDDD)"""j*Cร๎พq๎ฎž• S RDDDDัa"""ขฆดาaŠAŠˆˆˆ(: RDDDิิ†† –พบฎท}็r†))"""ข่0HQ,์w`่ฮํ}_Zฎ0ล EDDD)"""Š•ๅ S RDDDDัa"""ขXฺป๏ภะ[ท๔|–ฮฮืฆคˆˆˆˆขร EDDDฑvว๏ฺิ๕ล‹ S RDDDDัa"""ขKยb˜บ}Kwง"Kฏ๙๕ RDDDDัa"""ขKส'z๒หwnํyฟฅ)ฺซ}ƒQtคˆˆˆ่’34<’ปgw๏W2wฝR˜b""""Šƒ]ฒ^-L1HE‡AŠˆˆˆ.yCร#นปทwcwWnฯโเs)"""ข่0Hัš14|`เ๎ํ๗฿ิ฿พ‡AŠˆˆˆ(: RDD;vL 0๐ฅ …ฑ2† Fค ฅ.ฒp'!c€฿9๏็˜™yฏ๕ฉะ3คHRค )R†)C €”!@ส eH2คHRค )Rj%ุ๚^fhIENDฎB`‚sparse-0.18.0/docs/logo.svg000066400000000000000000000545651514474157100155360ustar00rootroot00000000000000 sparse-0.18.0/docs/migration-jl.md000066400000000000000000000036741514474157100167660ustar00rootroot00000000000000# Migration to the Finch Julia backend To switch to the Finch Julia backend, set the environment variable `SPARSE_BACKEND="Finch"`, then continue using. While this is largely compatible with the Array API, support for some functions may not be present, and API compatibility isn't strictly preserved with the default (Numba) backend. However, the new backend has a large performance benefit over the default backend. Below, you will find a table of common invocations, with their equivalents in the Finch Julia backend. The most common change is a standard API for construction of arrays. | Numba Backend
(`SPARSE_BACKEND="Numba"`) | Finch Julia Backend
(`SPARSE_BACKEND="Finch"`) | Notes | |---------------------------------------------|----------------------------------------------------|-------| | `sparse.COO.from_numpy(arr, fill_value=fv)`
`sparse.COO.from_scipy(arr)`
`sparse.COO(x)` | `sparse.asarray(x, format="coo", [fill_value=fv])` | Doesn't support pulling out individual arrays | | `sparse.GCXS.from_numpy(arr, fill_value=fv)`
`sparse.GCXS.from_scipy(arr)`
`sparse.GCXS(x)` | `sparse.asarray(x, format="csf", [fill_value=fv])` | Format might not be a 1:1 match | | `sparse.DOK.from_numpy(arr, fill_value=fv)`
`sparse.DOK.from_scipy(arr)`
`sparse.DOK(x)` | `sparse.asarray(x, format="dok", [fill_value=fv])` | Format might not be a 1:1 match | Most things work as expected, with the following exceptions, which aren't defined yet for Finch: * `sparse.broadcast_to` * `sparse.solve` * Statistical functions: `mean`, `std`, `var` * `sparse.isdtype` * `sparse.reshape` * Some elementwise functions * Manipulation functions: `concat`, `expand_dims`, `squeeze`, `flip`, `roll`, `stack` * `arg*` functions: `argmin`, `argmax` * Sorting functions: `sort`, `argsort` IEEE-754 compliance is hard to maintain with sparse arrays in general. This is now even more true of the Julia backend, which trades off performance for IEEE-754 compatibility. sparse-0.18.0/docs/operations.md000066400000000000000000000177321514474157100165550ustar00rootroot00000000000000# Operations on [`sparse.COO`][] and [`sparse.GCXS`][] arrays ## Operators [`sparse.COO`][] and [`sparse.GCXS`][] objects support a number of operations. They interact with scalars, [`sparse.COO`][] and [`sparse.GCXS`][] objects, [scipy.sparse.spmatrix][] objects, all following standard Python and Numpy conventions. For example, the following Numpy expression produces equivalent results for both Numpy arrays, COO arrays, or a mix of the two: ```python np.log(X.dot(beta.T) + 1) ``` However some operations are not supported, like operations that implicitly cause dense structures, or numpy functions that are not yet implemented for sparse arrays. ```python np.linalg.cholesky(x) # sparse cholesky not implemented ``` This page describes those valid operations, and their limitations. **[`sparse.elemwise`][]** This function allows you to apply any arbitrary broadcasting function to any number of arguments where the arguments can be [`sparse.SparseArray`][] objects or [`scipy.sparse.spmatrix`][] objects. For example, the following will add two arrays: ```python sparse.elemwise(np.add, x, y) ``` !!! warning Previously, [`sparse.elemwise`][] was a method of the [`sparse.COO`][] class. Now, it has been moved to the [sparse][] module. **Auto-Densification** Operations that would result in dense matrices, such as operations with [Numpy arrays][`numpy.ndarray`] raises a [ValueError][]. For example, the following will raise a [ValueError][] if `x` is a [`numpy.ndarray`][]: ```python x + y ``` However, all of the following are valid operations. ```python x + 0 x != y x + y x == 5 5 * x x / 7.3 x != 0 x == 0 ~x x + 5 ``` We also support operations with a nonzero fill value. These are operations that map zero values to nonzero values, such as `x + 1` or `~x`. In these cases, they will produce an output with a fill value of `1` or `True`, assuming the original array has a fill value of `0` or `False` respectively. If densification is needed, it must be explicit. In other words, you must call [`sparse.SparseArray.todense`][] on the [`sparse.SparseArray`][] object. If both operands are [`sparse.SparseArray`][], both must be densified. **Operations with NumPy arrays** In certain situations, operations with NumPy arrays are also supported. For example, the following will work if `x` is [`sparse.COO`][] and `y` is a NumPy array: ```python x * y ``` The following conditions must be met when performing element-wise operations with NumPy arrays: * The operation must produce a consistent fill-values. In other words, the resulting array must also be sparse. * Operating on the NumPy arrays must not increase the size when broadcasting the arrays. ## Operations with [`scipy.sparse.spmatrix`][] Certain operations with [`scipy.sparse.spmatrix`][] are also supported. For example, the following are all allowed if `y` is a [`scipy.sparse.spmatrix`][]: ```python x + y x - y x * y x > y x < y ``` In general, operating on a [`scipy.sparse.spmatrix`][] is the same as operating on [`sparse.COO`][] or [`sparse.GCXS`][], as long as it is to the right of the operator. !!! note Results are not guaranteed if `x` is a [scipy.sparse.spmatrix][]. For this reason, we recommend that all Scipy sparse matrices should be explicitly converted to [`sparse.COO`][] or [`sparse.GCXS`][] before any operations. ## Broadcasting All binary operators support [broadcasting](https://numpy.org/doc/stable/user/basics.broadcasting.html). This means that (under certain conditions) you can perform binary operations on arrays with unequal shape. Namely, when the shape is missing a dimension, or when a dimension is `1`. For example, performing a binary operation on two `COO` arrays with shapes `(4,)` and `(5, 1)` yields an object of shape `(5, 4)`. The same happens with arrays of shape `(1, 4)` and `(5, 1)`. However, `(4, 1)` and `(5, 1)` will raise a [`ValueError`][].If densification is needed, ## Element-wise Operations [`sparse.COO`][] and [`sparse.GCXS`][] arrays support a variety of element-wise operations. However, as with operators, operations that map zero to a nonzero value are not supported. To illustrate, the following are all possible, and will produce another [`sparse.SparseArray`][]: ```python np.abs(x) np.sin(x) np.sqrt(x) np.conj(x) np.expm1(x) np.log1p(x) np.exp(x) np.cos(x) np.log(x) ``` As above, in the last three cases, an array with a nonzero fill value will be produced. Notice that you can apply any unary or binary [`sparse.COO`][] arrays, and [`numpy.ndarray`][] objects and scalars and it will work so long as the result is not dense. When applying to [`numpy.ndarray`][] objects, we check that operating on the array with zero would always produce a zero. ## Reductions [`sparse.COO`][] and [`sparse.GCXS`][] objects support a number of reductions. However, not all important reductions are currently implemented (help welcome!). All of the following currently work: ```python x.sum(axis=1) np.max(x) np.min(x, axis=(0, 2)) x.prod() ``` [`sparse.SparseArray.reduce`][] This method can take an arbitrary [`numpy.ufunc`][] and performs a reduction using that method. For example, the following will perform a sum: ```python x.reduce(np.add, axis=1) ``` !!! note This library currently performs reductions by grouping together all coordinates along the supplied axes and reducing those. Then, if the number in a group is deficient, it reduces an extra time with zero. As a result, if reductions can change by adding multiple zeros to it, this method won't be accurate. However, it works in most cases. **Partial List of Supported Reductions** Although any binary [`numpy.ufunc`][] should work for reductions, when calling in the form `x.reduction()`, the following reductions are supported: * [`sparse.COO.sum`][] * [`sparse.COO.max`][] * [`sparse.COO.min`][] * [`sparse.COO.prod`][] ## Indexing [`sparse.COO`][] and [`sparse.GCXS`][] arrays can be [indexed](https://numpy.org/doc/stable/user/basics.indexing.html) just like regular [`numpy.ndarray`][] objects. They support integer, slice and boolean and array indexing (boolean and array indexing is supported only by dense NumPy arrays). However, currently, numpy advanced indexing is not properly supported. This means that all of the following work like in Numpy, except that they will produce [`sparse.SparseArray`][] arrays rather than [`numpy.ndarray`][] objects, and will produce scalars where expected. Assume that `z.shape` is `(5, 6, 7)` ```python z[0] z[1, 3] z[1, 4, 3] z[:3, :2, 3] z[::-1, 1, 3] z[-1] ``` All of the following will raise an `IndexError`, like in Numpy 1.13 and later. ```python z[6] z[3, 6] z[1, 4, 8] z[-6] ``` **Advanced Indexing** Advanced indexing (indexing arrays with other arrays) is supported, but only for indexing with a *single array*. Indexing a single array with multiple arrays is not supported at this time. As above, if `z.shape` is `(5, 6, 7)`, all of the following will work like NumPy: ```python z[[0, 1, 2]] z[1, [3]] z[1, 4, [3, 6]] z[:3, :2, [1, 5]] ``` **Package Configuration** By default, when performing something like `np.array(COO)`, we do not allow the array to be converted into a dense one and it raise a [`RuntimeError`][]. To prevent this, set the environment variable `SPARSE_AUTO_DENSIFY` to `1`. If it is desired to raise a warning if creating a sparse array that takes no less memory than an equivalent desne array, set the environment variable `SPARSE_WARN_ON_TOO_DENSE` to `1`. ## Other Operations [`sparse.COO`][] and [`sparse.GCXS`][] arrays support a number of other common operations. Among them are [`sparse.dot`][], [`sparse.tensordot`][] [`sparse.einsum`][], [`sparse.concatenate`][] and [`sparse.stack`][], [`sparse.COO.transpose`][] and [`sparse.COO.reshape`][]. You can view the full list on the [API reference page](../../api/). !!! note Some operations require zero fill-values (such as [`sparse.COO.nonzero`][]) and others (such as [`sparse.concatenate`][]) require that all inputs have consistent fill-values. For details, check the API reference. sparse-0.18.0/docs/quickstart.md000066400000000000000000000031351514474157100165540ustar00rootroot00000000000000# Getting Started ## Install If you haven't already, install the `sparse` library ```bash pip install sparse ``` ## Create To start, lets construct a sparse [`sparse.COO`][] array from a [`numpy.ndarray`][]: ```python import numpy as np import sparse x = np.random.random((100, 100, 100)) x[x < 0.9] = 0 # fill most of the array with zeros s = sparse.COO(x) # convert to sparse array ``` These store the same information and support many of the same operations, but the sparse version takes up less space in memory ```python >>> x.nbytes 8000000 >>> s.nbytes 1102706 >>> s ``` For more efficient ways to construct sparse arrays, see documentation on [Construct sparse arrays][construct-sparse-arrays]. ## Compute Many of the normal Numpy operations work on [`sparse.COO`][] objects just like on [`numpy.ndarray`][] objects. This includes arithmetic, [`numpy.ufunc`][] operations, or functions like tensordot and transpose. ```python >>> np.sin(s) + s.T * 1 ``` However, operations which map zero elements to nonzero will usually change the fill-value instead of raising an error. ```python >>> y = s + 5 ``` However, if you're sure you want to convert a sparse array to a dense one, you can use the ``todense`` method (which will result in a [`numpy.ndarray`][]): ```python y = s.todense() + 5 ``` For more operations see the [operations][operators] or the [API reference page](../../api/). sparse-0.18.0/docs/roadmap.md000066400000000000000000000077701514474157100160160ustar00rootroot00000000000000# Roadmap For a brochure version of this roadmap, see [this link](https://docs.wixstatic.com/ugd/095d2c_ac81d19db47047c79a55da7a6c31cf66.pdf). ## Background The aim of PyData/Sparse is to create sparse containers that implement the ndarray interface. Traditionally in the PyData ecosystem, sparse arrays have been provided by the `scipy.sparse` submodule. All containers there depend on and emulate the `numpy.matrix` interface. This means that they are limited to two dimensions and also donโ€™t work well in places where `numpy.ndarray` would work. PyData/Sparse is well on its way to replacing `scipy.sparse` as the de-facto sparse array implementation in the PyData ecosystem. ## Topics * More storage formats * Better performance/algorithms * Covering more of the NumPy API * SciPy Integration * Dask integration for high scalability * CuPy integration for GPU-acceleration * Maintenance and General Improvements ## More Storage Formats In the sparse domain, you have to make a choice of format when representing your array in memory, and different formats have different trade-offs. For example: * CSR/CSC are usually expected by external libraries, and have good space characteristics for most arrays * DOK allows in-place modification and writes * LIL has faster writes if written to in-order. * BSR allows block-writes and reads The most important formats are, of course, CSR and CSC, because they allow zero-copy interaction with a number of libraries including MKL, LAPACK and others. This will allow PyData/Sparse to quickly reach the functionality of `scipy.sparse`, accelerating the path to its replacement. ## Better Performance/Algorithms There are a few places in scipy.sparse where algorithms are sub-optimal, sometimes due to reliance on NumPy which doesnโ€™t have these algorithms. We intend to both improve the algorithms in NumPy, giving the broader community a chance to use them; as well as in PyData/Sparse, to reach optimal efficiency in the broadest use-cases. ## Covering More of the NumPy API Our eventual aim is to cover all areas of NumPy where algorithms exist that give sparse arrays an edge over dense arrays. Currently, PyData/Sparse supports reductions, element-wise functions and other common functions such as stacking, concatenating and tensor products. Common uses of sparse arrays include linear algebra and graph theoretic subroutines, so we plan on covering those first. ## SciPy Integration PyData/Sparse aims to build containers and elementary operations on them, such as element-wise operations, reductions and so on. We plan on modifying the current graph theoretic subroutines in `scipy.sparse.csgraph` to support PyData/Sparse arrays. The same applies for linear algebra and `scipy.sparse.linalg`. ## CuPy integration for GPU-acceleration CuPy is a project that implements a large portion of NumPyโ€™s ndarray interface on GPUs. We plan to integrate with CuPy so that itโ€™s possible to accelerate sparse arrays on GPUs. [](){#completed} # Completed Tasks ## Dask Integration for High Scalability Dask is a project that takes ndarray style containers and then allows them to scale across multiple cores or clusters. We plan on tighter integration and cooperation with the Dask team to ensure the highest amount of Dask functionality works with sparse arrays. Currently, integration with Dask is supported via array protocols. When more of the NumPy API (e.g. array creation functions) becomes available through array protocols, it will be automatically be supported by Dask. ## (Partial) SciPy Integration Support for `scipy.sparse.linalg` has been completed. We hope to add support for `scipy.sparse.csgraph` in the future. ## More Storage Formats GCXS, a compressed n-dimensional array format based on the GCRS/GCCS formats of [Shaikh and Hasan 2015](https://ieeexplore.ieee.org/document/7237032), has been added. In conjunction with this work, the CSR/CSC matrix formats have been are now a part of pydata/sparse. We plan to add better-performing algorithms for many of the operations currently supported. sparse-0.18.0/examples/000077500000000000000000000000001514474157100147245ustar00rootroot00000000000000sparse-0.18.0/examples/__init__.py000066400000000000000000000000001514474157100170230ustar00rootroot00000000000000sparse-0.18.0/examples/elemwise_example.py000066400000000000000000000040051514474157100206220ustar00rootroot00000000000000import importlib import operator import os import sparse from utils import benchmark import numpy as np import scipy.sparse as sps LEN = 10000 DENSITY = 0.001 ITERS = 3 rng = np.random.default_rng(0) if __name__ == "__main__": print("Elementwise Example:\n") for func_name in ["multiply", "add", "greater_equal"]: print(f"{func_name} benchmark:\n") s1_sps = sps.random(LEN, LEN, format="csr", density=DENSITY, random_state=rng) * 10 s1_sps.sum_duplicates() s2_sps = sps.random(LEN, LEN, format="csr", density=DENSITY, random_state=rng) * 10 s2_sps.sum_duplicates() # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) s1 = sparse.asarray(s1_sps.asformat("csc"), format="csc") s2 = sparse.asarray(s2_sps.asformat("csc"), format="csc") func = getattr(sparse, func_name) # Compile & Benchmark result_finch = benchmark(func, args=[s1, s2], info="Finch", iters=ITERS) # ======= Numba ======= os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) s1 = sparse.asarray(s1_sps) s2 = sparse.asarray(s2_sps) func = getattr(sparse, func_name) # Compile & Benchmark result_numba = benchmark(func, args=[s1, s2], info="Numba", iters=ITERS) # ======= SciPy ======= s1 = s1_sps s2 = s2_sps if func_name == "multiply": func, args = s1.multiply, [s2] elif func_name == "add": func, args = operator.add, [s1, s2] elif func_name == "greater_equal": func, args = operator.ge, [s1, s2] # Compile & Benchmark result_scipy = benchmark(func, args=args, info="SciPy", iters=ITERS) np.testing.assert_allclose(result_numba.todense(), result_scipy.toarray()) np.testing.assert_allclose(result_finch.todense(), result_numba.todense()) np.testing.assert_allclose(result_finch.todense(), result_scipy.toarray()) sparse-0.18.0/examples/hits_example.py000066400000000000000000000036731514474157100177710ustar00rootroot00000000000000import os from typing import Any import graphblas as gb import graphblas_algorithms as ga import numpy as np import scipy.sparse as sps from numpy.testing import assert_allclose os.environ["SPARSE_BACKEND"] = "Finch" import sparse # select namespace xp = sparse # np jnp Array = Any def converged(xprev: Array, x: Array, N: int, tol: float) -> bool: err = xp.sum(xp.abs(x - xprev)) return err < xp.asarray(N * tol) class Graph: def __init__(self, A: Array): assert A.ndim == 2 and A.shape[0] == A.shape[1] self.N = A.shape[0] self.A = A @sparse.compiled() def kernel(hprev: Array, A: Array, N: int, tol: float) -> tuple[Array, Array, Array]: a = hprev.mT @ A h = A @ a.mT h = h / xp.max(h) conv = converged(hprev, h, N, tol) return h, a, conv def hits_finch(G: Graph, max_iter: int = 100, tol: float = 1e-8, normalized: bool = True) -> tuple[Array, Array]: N = G.N if N == 0: return xp.asarray([]), xp.asarray([]) h = xp.full((N, 1), 1.0 / N) A = xp.asarray(G.A) for _ in range(max_iter): hprev = h a = hprev.mT @ A h = A @ a.mT h = h / xp.max(h) if converged(hprev, h, N, tol): break # alternatively these lines can be compiled # h, a, conv = kernel(h, A, N, tol) else: raise Exception("Didn't converge") if normalized: h = h / xp.sum(xp.abs(h)) a = a / xp.sum(xp.abs(a)) return h, a if __name__ == "__main__": coords = (np.array([0, 0, 1, 2, 2, 3]), np.array([1, 3, 0, 0, 1, 2])) data = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]) A = sps.coo_array((data, coords)) G = Graph(A) h_finch, a_finch = hits_finch(G) print(h_finch, a_finch) M = gb.io.from_scipy_sparse(A) G = ga.Graph(M) h_gb, a_gb = ga.hits(G) assert_allclose(h_finch.todense().ravel(), h_gb.to_dense()) assert_allclose(a_finch.todense().ravel(), a_gb.to_dense()) sparse-0.18.0/examples/matmul_example.py000066400000000000000000000031241514474157100203100ustar00rootroot00000000000000import importlib import os import sparse from utils import benchmark import numpy as np import scipy.sparse as sps LEN = 100000 DENSITY = 0.00001 ITERS = 3 rng = np.random.default_rng(0) if __name__ == "__main__": print("Matmul Example:\n") a_sps = sps.random(LEN, LEN - 10, format="csr", density=DENSITY, random_state=rng) * 10 a_sps.sum_duplicates() b_sps = sps.random(LEN - 10, LEN, format="csr", density=DENSITY, random_state=rng) * 10 b_sps.sum_duplicates() # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) a = sparse.asarray(a_sps) b = sparse.asarray(b_sps) @sparse.compiled() def sddmm_finch(a, b): return a @ b # Compile & Benchmark result_finch = benchmark(sddmm_finch, args=[a, b], info="Finch", iters=ITERS) # ======= Numba ======= os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) a = sparse.asarray(a_sps) b = sparse.asarray(b_sps) def sddmm_numba(a, b): return a @ b # Compile & Benchmark result_numba = benchmark(sddmm_numba, args=[a, b], info="Numba", iters=ITERS) # ======= SciPy ======= def sddmm_scipy(a, b): return a @ b a = a_sps b = b_sps # Compile & Benchmark result_scipy = benchmark(sddmm_scipy, args=[a, b], info="SciPy", iters=ITERS) # np.testing.assert_allclose(result_numba.todense(), result_scipy.toarray()) # np.testing.assert_allclose(result_finch.todense(), result_numba.todense()) # np.testing.assert_allclose(result_finch.todense(), result_scipy.toarray()) sparse-0.18.0/examples/mttkrp_example.py000066400000000000000000000027541514474157100203420ustar00rootroot00000000000000import importlib import os import sparse from utils import benchmark import numpy as np I_ = 1000 J_ = 25 K_ = 1000 L_ = 100 DENSITY = 0.0001 ITERS = 3 rng = np.random.default_rng(0) if __name__ == "__main__": print("MTTKRP Example:\n") os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) B_sps = sparse.random((I_, K_, L_), density=DENSITY, random_state=rng) * 10 D_sps = rng.random((L_, J_)) * 10 C_sps = rng.random((K_, J_)) * 10 # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) B = sparse.asarray(B_sps.todense(), format="csf") D = sparse.asarray(np.array(D_sps, order="F")) C = sparse.asarray(np.array(C_sps, order="F")) @sparse.compiled() def mttkrp_finch(B, D, C): return sparse.sum(B[:, :, :, None] * D[None, None, :, :] * C[None, :, None, :], axis=(1, 2)) # Compile & Benchmark result_finch = benchmark(mttkrp_finch, args=[B, D, C], info="Finch", iters=ITERS) # ======= Numba ======= os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) B = sparse.asarray(B_sps, format="gcxs") D = D_sps C = C_sps def mttkrp_numba(B, D, C): return sparse.sum(B[:, :, :, None] * D[None, None, :, :] * C[None, :, None, :], axis=(1, 2)) # Compile & Benchmark result_numba = benchmark(mttkrp_numba, args=[B, D, C], info="Numba", iters=ITERS) np.testing.assert_allclose(result_finch.todense(), result_numba.todense()) sparse-0.18.0/examples/sddmm_example.py000066400000000000000000000034611514474157100201210ustar00rootroot00000000000000import importlib import os import sparse from utils import benchmark import numpy as np import scipy.sparse as sps LEN = 10000 DENSITY = 0.00001 ITERS = 3 rng = np.random.default_rng(0) if __name__ == "__main__": print("SDDMM Example:\n") a_sps = rng.random((LEN, LEN - 10)) * 10 b_sps = rng.random((LEN - 10, LEN)) * 10 s_sps = sps.random(LEN, LEN, format="coo", density=DENSITY, random_state=rng) * 10 s_sps.sum_duplicates() # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) s = sparse.asarray(s_sps) a = sparse.asarray(np.array(a_sps, order="F")) b = sparse.asarray(np.array(b_sps, order="C")) @sparse.compiled() def sddmm_finch(s, a, b): return sparse.sum( s[:, :, None] * (a[:, None, :] * sparse.permute_dims(b, (1, 0))[None, :, :]), axis=-1, ) # Compile & Benchmark result_finch = benchmark(sddmm_finch, args=[s, a, b], info="Finch", iters=ITERS) # ======= Numba ======= os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) s = sparse.asarray(s_sps) a = a_sps b = b_sps def sddmm_numba(s, a, b): return s * (a @ b) # Compile & Benchmark result_numba = benchmark(sddmm_numba, args=[s, a, b], info="Numba", iters=ITERS) # ======= SciPy ======= def sddmm_scipy(s, a, b): return s.multiply(a @ b) s = s_sps.asformat("csr") a = a_sps b = b_sps # Compile & Benchmark result_scipy = benchmark(sddmm_scipy, args=[s, a, b], info="SciPy", iters=ITERS) np.testing.assert_allclose(result_numba.todense(), result_scipy.toarray()) np.testing.assert_allclose(result_finch.todense(), result_numba.todense()) np.testing.assert_allclose(result_finch.todense(), result_scipy.toarray()) sparse-0.18.0/examples/sparse_finch.ipynb000066400000000000000000000406741514474157100204460ustar00rootroot00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Finch backend for `sparse`\n", "\n", "
\n", " \"Open\n", " to download and run." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# %pip install 'sparse[finch]==0.17.0' scipy\n", "\n", "# let's make sure we're using Finch backend\n", "import os\n", "\n", "os.environ[\"SPARSE_BACKEND\"] = \"Finch\"\n", "CI_MODE = bool(int(os.getenv(\"CI_MODE\", default=\"0\")))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import importlib\n", "import time\n", "\n", "import sparse\n", "\n", "import matplotlib.pyplot as plt\n", "import networkx as nx\n", "\n", "import numpy as np\n", "import scipy.sparse as sps\n", "import scipy.sparse.linalg as splin" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tns = sparse.asarray(np.zeros((10, 10))) # offers a no-copy constructor for NumPy as scipy.sparse inputs\n", "\n", "s1 = sparse.random((100, 10), density=0.01) # creates random COO tensor\n", "s2 = sparse.random((100, 100, 10), density=0.01)\n", "s2 = sparse.asarray(s2, format=\"csf\") # can be used to rewrite tensor to a new format\n", "\n", "result = sparse.tensordot(s1, s2, axes=([0, 1], [0, 2]))\n", "\n", "total = sparse.sum(result * result)\n", "print(total)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example: least squares - closed form" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "y = sparse.random((100, 1), density=0.08)\n", "X = sparse.random((100, 5), density=0.08)\n", "X = sparse.asarray(X, format=\"csc\")\n", "X_lazy = sparse.lazy(X)\n", "\n", "X_X = sparse.compute(sparse.permute_dims(X_lazy, (1, 0)) @ X_lazy)\n", "\n", "X_X = sparse.asarray(X_X, format=\"csc\") # move back from dense to CSC format\n", "\n", "inverted = splin.inv(X_X) # dispatching to scipy.sparse.sparray\n", "\n", "b_hat = (inverted @ sparse.permute_dims(X, (1, 0))) @ y\n", "\n", "print(b_hat.todense())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Benchmark plots" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ITERS = 1\n", "rng = np.random.default_rng(0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.style.use(\"seaborn-v0_8\")\n", "plt.rcParams[\"figure.dpi\"] = 400\n", "plt.rcParams[\"figure.figsize\"] = [8, 4]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def benchmark(func, info, args) -> float:\n", " start = time.time()\n", " for _ in range(ITERS):\n", " func(*args)\n", " elapsed = time.time() - start\n", " return elapsed / ITERS" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## MTTKRP" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"MTTKRP Example:\\n\")\n", "\n", "os.environ[sparse._ENV_VAR_NAME] = \"Numba\"\n", "importlib.reload(sparse)\n", "\n", "configs = [\n", " {\"I_\": 100, \"J_\": 25, \"K_\": 100, \"L_\": 10, \"DENSITY\": 0.001},\n", " {\"I_\": 100, \"J_\": 25, \"K_\": 100, \"L_\": 100, \"DENSITY\": 0.001},\n", " {\"I_\": 1000, \"J_\": 25, \"K_\": 100, \"L_\": 100, \"DENSITY\": 0.001},\n", " {\"I_\": 1000, \"J_\": 25, \"K_\": 1000, \"L_\": 100, \"DENSITY\": 0.001},\n", " {\"I_\": 1000, \"J_\": 25, \"K_\": 1000, \"L_\": 1000, \"DENSITY\": 0.001},\n", "]\n", "nonzeros = [100_000, 1_000_000, 10_000_000, 100_000_000, 1_000_000_000]\n", "\n", "if CI_MODE:\n", " configs = configs[:1]\n", " nonzeros = nonzeros[:1]\n", "\n", "finch_times = []\n", "numba_times = []\n", "finch_galley_times = []\n", "\n", "for config in configs:\n", " B_shape = (config[\"I_\"], config[\"K_\"], config[\"L_\"])\n", " B_sps = sparse.random(B_shape, density=config[\"DENSITY\"], random_state=rng)\n", " D_sps = rng.random((config[\"L_\"], config[\"J_\"]))\n", " C_sps = rng.random((config[\"K_\"], config[\"J_\"]))\n", "\n", " # ======= Finch =======\n", " os.environ[sparse._ENV_VAR_NAME] = \"Finch\"\n", " importlib.reload(sparse)\n", "\n", " B = sparse.asarray(B_sps.todense(), format=\"csf\")\n", " D = sparse.asarray(np.array(D_sps, order=\"F\"))\n", " C = sparse.asarray(np.array(C_sps, order=\"F\"))\n", "\n", " @sparse.compiled(opt=sparse.DefaultScheduler())\n", " def mttkrp_finch(B, D, C):\n", " return sparse.sum(B[:, :, :, None] * D[None, None, :, :] * C[None, :, None, :], axis=(1, 2))\n", "\n", " # Compile\n", " result_finch = mttkrp_finch(B, D, C)\n", " # Benchmark\n", " time_finch = benchmark(mttkrp_finch, info=\"Finch\", args=[B, D, C])\n", "\n", " # ======= Finch Galley =======\n", " os.environ[sparse._ENV_VAR_NAME] = \"Finch\"\n", " importlib.reload(sparse)\n", "\n", " B = sparse.asarray(B_sps.todense(), format=\"csf\")\n", " D = sparse.asarray(np.array(D_sps, order=\"F\"))\n", " C = sparse.asarray(np.array(C_sps, order=\"F\"))\n", "\n", " @sparse.compiled(opt=sparse.GalleyScheduler(), tag=sum(B_shape))\n", " def mttkrp_finch_galley(B, D, C):\n", " return sparse.sum(B[:, :, :, None] * D[None, None, :, :] * C[None, :, None, :], axis=(1, 2))\n", "\n", " # Compile\n", " result_finch_galley = mttkrp_finch_galley(B, D, C)\n", " # Benchmark\n", " time_finch_galley = benchmark(mttkrp_finch_galley, info=\"Finch Galley\", args=[B, D, C])\n", "\n", " # ======= Numba =======\n", " os.environ[sparse._ENV_VAR_NAME] = \"Numba\"\n", " importlib.reload(sparse)\n", "\n", " B = sparse.asarray(B_sps, format=\"gcxs\")\n", " D = D_sps\n", " C = C_sps\n", "\n", " def mttkrp_numba(B, D, C):\n", " return sparse.sum(B[:, :, :, None] * D[None, None, :, :] * C[None, :, None, :], axis=(1, 2))\n", "\n", " # Compile\n", " result_numba = mttkrp_numba(B, D, C)\n", " # Benchmark\n", " time_numba = benchmark(mttkrp_numba, info=\"Numba\", args=[B, D, C])\n", "\n", " np.testing.assert_allclose(result_finch.todense(), result_numba.todense())\n", "\n", " finch_times.append(time_finch)\n", " numba_times.append(time_numba)\n", " finch_galley_times.append(time_finch_galley)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(nrows=1, ncols=1)\n", "\n", "ax.plot(nonzeros, finch_times, \"o-\", label=\"Finch\")\n", "ax.plot(nonzeros, numba_times, \"o-\", label=\"Numba\")\n", "ax.plot(nonzeros, finch_galley_times, \"o-\", label=\"Finch - Galley\")\n", "ax.grid(True)\n", "ax.set_xlabel(\"no. of elements\")\n", "ax.set_ylabel(\"time (sec)\")\n", "ax.set_title(\"MTTKRP\")\n", "ax.set_xscale(\"log\")\n", "ax.set_yscale(\"log\")\n", "ax.legend(loc=\"best\", numpoints=1)\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## SDDMM" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"SDDMM Example:\\n\")\n", "\n", "configs = [\n", " {\"LEN\": 5000, \"DENSITY\": 0.00001},\n", " {\"LEN\": 10000, \"DENSITY\": 0.00001},\n", " {\"LEN\": 15000, \"DENSITY\": 0.00001},\n", " {\"LEN\": 20000, \"DENSITY\": 0.00001},\n", " {\"LEN\": 25000, \"DENSITY\": 0.00001},\n", " {\"LEN\": 30000, \"DENSITY\": 0.00001},\n", "]\n", "size_n = [5000, 10000, 15000, 20000, 25000, 30000]\n", "\n", "if CI_MODE:\n", " configs = configs[:1]\n", " size_n = size_n[:1]\n", "\n", "finch_times = []\n", "numba_times = []\n", "scipy_times = []\n", "finch_galley_times = []\n", "\n", "for config in configs:\n", " LEN = config[\"LEN\"]\n", " DENSITY = config[\"DENSITY\"]\n", "\n", " a_sps = rng.random((LEN, LEN))\n", " b_sps = rng.random((LEN, LEN))\n", " s_sps = sps.random(LEN, LEN, format=\"coo\", density=DENSITY, random_state=rng)\n", " s_sps.sum_duplicates()\n", "\n", " # ======= Finch =======\n", " print(\"finch\")\n", " os.environ[sparse._ENV_VAR_NAME] = \"Finch\"\n", " importlib.reload(sparse)\n", "\n", " s = sparse.asarray(s_sps)\n", " a = sparse.asarray(a_sps)\n", " b = sparse.asarray(b_sps)\n", "\n", " @sparse.compiled(opt=sparse.DefaultScheduler())\n", " def sddmm_finch(s, a, b):\n", " return s * (a @ b)\n", "\n", " # Compile\n", " result_finch = sddmm_finch(s, a, b)\n", " # Benchmark\n", " time_finch = benchmark(sddmm_finch, info=\"Finch\", args=[s, a, b])\n", "\n", " # ======= Finch Galley =======\n", " print(\"finch galley\")\n", " os.environ[sparse._ENV_VAR_NAME] = \"Finch\"\n", " importlib.reload(sparse)\n", "\n", " s = sparse.asarray(s_sps)\n", " a = sparse.asarray(a_sps)\n", " b = sparse.asarray(b_sps)\n", "\n", " @sparse.compiled(opt=sparse.GalleyScheduler(), tag=LEN)\n", " def sddmm_finch_galley(s, a, b):\n", " return s * (a @ b)\n", "\n", " # Compile\n", " result_finch_galley = sddmm_finch_galley(s, a, b)\n", " # Benchmark\n", " time_finch_galley = benchmark(sddmm_finch_galley, info=\"Finch Galley\", args=[s, a, b])\n", "\n", " # ======= Numba =======\n", " print(\"numba\")\n", " os.environ[sparse._ENV_VAR_NAME] = \"Numba\"\n", " importlib.reload(sparse)\n", "\n", " s = sparse.asarray(s_sps)\n", " a = a_sps\n", " b = b_sps\n", "\n", " def sddmm_numba(s, a, b):\n", " return s * (a @ b)\n", "\n", " # Compile\n", " result_numba = sddmm_numba(s, a, b)\n", " # Benchmark\n", " time_numba = benchmark(sddmm_numba, info=\"Numba\", args=[s, a, b])\n", "\n", " # ======= SciPy =======\n", " print(\"scipy\")\n", "\n", " def sddmm_scipy(s, a, b):\n", " return s.multiply(a @ b)\n", "\n", " s = s_sps.asformat(\"csr\")\n", " a = a_sps\n", " b = b_sps\n", "\n", " result_scipy = sddmm_scipy(s, a, b)\n", " # Benchmark\n", " time_scipy = benchmark(sddmm_scipy, info=\"SciPy\", args=[s, a, b])\n", "\n", " finch_times.append(time_finch)\n", " numba_times.append(time_numba)\n", " scipy_times.append(time_scipy)\n", " finch_galley_times.append(time_finch_galley)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(nrows=1, ncols=1)\n", "\n", "ax.plot(size_n, finch_times, \"o-\", label=\"Finch\")\n", "ax.plot(size_n, numba_times, \"o-\", label=\"Numba\")\n", "ax.plot(size_n, scipy_times, \"o-\", label=\"SciPy\")\n", "ax.plot(size_n, finch_galley_times, \"o-\", label=\"Finch Galley\")\n", "\n", "ax.grid(True)\n", "ax.set_xlabel(\"size N\")\n", "ax.set_ylabel(\"time (sec)\")\n", "ax.set_title(\"SDDMM\")\n", "ax.legend(loc=\"best\", numpoints=1)\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Counting Triangles" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Counting Triangles Example:\\n\")\n", "\n", "configs = [\n", " {\"LEN\": 10000, \"DENSITY\": 0.001},\n", " {\"LEN\": 15000, \"DENSITY\": 0.001},\n", " {\"LEN\": 20000, \"DENSITY\": 0.001},\n", " {\"LEN\": 25000, \"DENSITY\": 0.001},\n", " {\"LEN\": 30000, \"DENSITY\": 0.001},\n", " {\"LEN\": 35000, \"DENSITY\": 0.001},\n", " {\"LEN\": 40000, \"DENSITY\": 0.001},\n", " {\"LEN\": 45000, \"DENSITY\": 0.001},\n", " {\"LEN\": 50000, \"DENSITY\": 0.001},\n", "]\n", "size_n = [10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000]\n", "\n", "if CI_MODE:\n", " configs = configs[:1]\n", " size_n = size_n[:1]\n", "\n", "finch_times = []\n", "finch_galley_times = []\n", "networkx_times = []\n", "scipy_times = []\n", "\n", "for config in configs:\n", " LEN = config[\"LEN\"]\n", " DENSITY = config[\"DENSITY\"]\n", "\n", " G = nx.gnp_random_graph(n=LEN, p=DENSITY)\n", " a_sps = nx.to_scipy_sparse_array(G)\n", "\n", " # ======= Finch =======\n", " print(\"finch\")\n", " os.environ[sparse._ENV_VAR_NAME] = \"Finch\"\n", " importlib.reload(sparse)\n", "\n", " a = sparse.asarray(a_sps)\n", "\n", " @sparse.compiled(opt=sparse.DefaultScheduler())\n", " def ct_finch(a):\n", " return sparse.sum(a @ a * a) / sparse.asarray(6)\n", "\n", " # Compile\n", " result_finch = ct_finch(a)\n", " # Benchmark\n", " time_finch = benchmark(ct_finch, info=\"Finch\", args=[a])\n", "\n", " # ======= Finch Galley =======\n", " print(\"finch galley\")\n", " os.environ[sparse._ENV_VAR_NAME] = \"Finch\"\n", " importlib.reload(sparse)\n", "\n", " a = sparse.asarray(a_sps)\n", "\n", " @sparse.compiled(opt=sparse.GalleyScheduler(), tag=LEN)\n", " def ct_finch_galley(a):\n", " return sparse.sum(a @ a * a) / sparse.asarray(6)\n", "\n", " # Compile\n", " result_finch_galley = ct_finch_galley(a)\n", " # Benchmark\n", " time_finch_galley = benchmark(ct_finch_galley, info=\"Finch Galley\", args=[a])\n", "\n", " # ======= SciPy =======\n", " print(\"scipy\")\n", "\n", " def ct_scipy(a):\n", " return (a @ a * a).sum() / 6\n", "\n", " a = a_sps\n", "\n", " # Benchmark\n", " time_scipy = benchmark(ct_scipy, info=\"SciPy\", args=[a])\n", "\n", " # ======= NetworkX =======\n", " print(\"networkx\")\n", "\n", " def ct_networkx(a):\n", " return sum(nx.triangles(a).values()) / 3\n", "\n", " a = G\n", "\n", " time_networkx = benchmark(ct_networkx, info=\"SciPy\", args=[a])\n", "\n", " finch_times.append(time_finch)\n", " finch_galley_times.append(time_finch_galley)\n", " networkx_times.append(time_networkx)\n", " scipy_times.append(time_scipy)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(nrows=1, ncols=1)\n", "\n", "ax.plot(size_n, finch_times, \"o-\", label=\"Finch\")\n", "ax.plot(size_n, networkx_times, \"o-\", label=\"NetworkX\")\n", "ax.plot(size_n, scipy_times, \"o-\", label=\"SciPy\")\n", "ax.plot(size_n, finch_galley_times, \"o-\", label=\"Finch Galley\")\n", "\n", "ax.grid(True)\n", "ax.set_xlabel(\"size N\")\n", "ax.set_ylabel(\"time (sec)\")\n", "ax.set_title(\"Counting Triangles\")\n", "ax.legend(loc=\"best\", numpoints=1)\n", "\n", "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "sparse-dev", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.14" } }, "nbformat": 4, "nbformat_minor": 2 } sparse-0.18.0/examples/spmv_add_example.py000066400000000000000000000032541514474157100206120ustar00rootroot00000000000000import importlib import os import sparse from utils import benchmark import numpy as np import scipy.sparse as sps LEN = 100000 DENSITY = 0.000001 ITERS = 3 rng = np.random.default_rng(0) if __name__ == "__main__": print("SpMv_add Example:\n") A_sps = sps.random(LEN - 10, LEN, format="csc", density=DENSITY, random_state=rng) * 10 x_sps = rng.random((LEN, 1)) * 10 y_sps = rng.random((LEN - 10, 1)) * 10 # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) A = sparse.asarray(A_sps) x = sparse.asarray(np.array(x_sps, order="C")) y = sparse.asarray(np.array(y_sps, order="C")) @sparse.compiled() def spmv_finch(A, x, y): return sparse.sum(A[:, None, :] * sparse.permute_dims(x, (1, 0))[None, :, :], axis=-1) + y # Compile & Benchmark result_finch = benchmark(spmv_finch, args=[A, x, y], info="Finch", iters=ITERS) # ======= Numba ======= os.environ[sparse._ENV_VAR_NAME] = "Numba" importlib.reload(sparse) A = sparse.asarray(A_sps, format="csc") x = x_sps y = y_sps def spmv_numba(A, x, y): return A @ x + y # Compile & Benchmark result_numba = benchmark(spmv_numba, args=[A, x, y], info="Numba", iters=ITERS) # ======= SciPy ======= def spmv_scipy(A, x, y): return A @ x + y A = A_sps x = x_sps y = y_sps # Compile & Benchmark result_scipy = benchmark(spmv_scipy, args=[A, x, y], info="SciPy", iters=ITERS) np.testing.assert_allclose(result_numba, result_scipy) np.testing.assert_allclose(result_finch.todense(), result_numba) np.testing.assert_allclose(result_finch.todense(), result_scipy) sparse-0.18.0/examples/triangles_example.py000066400000000000000000000024641514474157100210070ustar00rootroot00000000000000import importlib import os import sparse import networkx as nx from utils import benchmark import numpy as np ITERS = 3 if __name__ == "__main__": print("Counting Triangles Example:\n") G = nx.gnp_random_graph(n=200, p=0.2) # ======= Finch ======= os.environ[sparse._ENV_VAR_NAME] = "Finch" importlib.reload(sparse) a_sps = nx.to_scipy_sparse_array(G) a = sparse.asarray(a_sps) @sparse.compiled() def count_triangles_finch(a): return sparse.sum(a @ a * a) / sparse.asarray(6) # Compile & Benchmark result_finch = benchmark(count_triangles_finch, args=[a], info="Finch", iters=ITERS) # ======= SciPy ======= def count_triangles_scipy(a): return (a @ a * a).sum() / 6 a = nx.to_scipy_sparse_array(G) # Compile & Benchmark result_scipy = benchmark(count_triangles_scipy, args=[a], info="SciPy", iters=ITERS) # ======= NetworkX ======= def count_triangles_networkx(a): return sum(nx.triangles(a).values()) / 3 a = G # Compile & Benchmark result_networkx = benchmark(count_triangles_networkx, args=[a], info="NetworkX", iters=ITERS) np.testing.assert_equal(result_finch.todense(), result_scipy) np.testing.assert_equal(result_finch.todense(), result_networkx) assert result_networkx == result_scipy sparse-0.18.0/examples/utils.py000066400000000000000000000011011514474157100164270ustar00rootroot00000000000000import os import time from collections.abc import Callable, Iterable from typing import Any CI_MODE = bool(int(os.getenv("CI_MODE", default="0"))) def benchmark( func: Callable, args: Iterable[Any], info: str, iters: int, ) -> object: # Compile result = func(*args) if CI_MODE: print("CI mode - skipping benchmark") return result # Benchmark print(info) start = time.time() for _ in range(iters): func(*args) elapsed = time.time() - start print(f"Took {elapsed / iters} s.\n") return result sparse-0.18.0/mkdocs.yml000066400000000000000000000051441514474157100151150ustar00rootroot00000000000000site_name: sparse repo_url: https://github.com/pydata/sparse.git edit_uri: edit/main/docs/ #use_directory_urls: false theme: name: material palette: primary: custom accent: cyan font: false #avoid Google Fonts to adhere to data privacy regulations logo: assets/images/logo.png favicon: assets/images/logo.svg features: - navigation.tabs - navigation.tabs.sticky - navigation.tracking - navigation.instant - navigation.instant.progress - navigation.prune - navigation.footer - navigation.indexes - navigation.expand - navigation.top # adds a back-to-top button when user scrolls up - content.code.copy markdown_extensions: - tables - admonition # This line, pymdownx.details and pymdownx.superfences are used by warings - pymdownx.details - pymdownx.superfences - codehilite - toc: toc_depth: 3 - pymdownx.arithmatex: # To display math content with KaTex generic: true - attr_list # To be able to link to a header on another page, use grids - md_in_html # Used for grids extra_javascript: - js/katex.js - https://unpkg.com/katex@0/dist/katex.min.js - https://unpkg.com/katex@0/dist/contrib/auto-render.min.js extra_css: - https://unpkg.com/katex@0/dist/katex.min.css - css/mkdocstrings.css plugins: - search - section-index - autorefs - gen-files: scripts: - scripts/gen_ref_pages.py - literate-nav - mkdocstrings: handlers: python: inventories: - https://numpy.org/doc/stable/objects.inv - https://docs.python.org/3/objects.inv - https://docs.scipy.org/doc/scipy/objects.inv options: inherited_members: yes show_root_members_full_path: false show_if_no_docstring: true members_order: source docstring_style: numpy show_source: true filters: ["!^_"] group_by_category: true show_category_heading: true - mkdocs-jupyter: include_source: true execute: true ignore: ["__init__.py", "utils.py", "gen_logo.py"] nav: - Home: - index.md - Introduction: - introduction.md - Install: - install.md - Tutorials: - examples.md - examples/* - How to guides: - how-to-guides.md - quickstart.md - construct.md - operations.md - migration-jl.md - API: - api.md - api/* - Contributing: - contributing.md - roadmap.md - completed-tasks.md - changelog.md - conduct.md sparse-0.18.0/pixi.lock000066400000000000000000034125641514474157100147500ustar00rootroot00000000000000version: 6 environments: core: channels: - url: https://prefix.dev/conda-forge/ options: pypi-prerelease-mode: if-necessary-or-explicit packages: {} default: channels: - url: https://prefix.dev/conda-forge/ options: pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://prefix.dev/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py313hdd307be_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py313h5dce7c4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numpy-2.3.5-py313hf6604e3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/linux-64/python-3.13.11-hc97d973_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: . osx-64: - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py313h590e1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py313hd3f9b42_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numpy-2.3.5-py313hf1665ba_1.conda - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/osx-64/python-3.13.11-h17c18a5_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - conda: . osx-arm64: - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py313he297ed2_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py313ha873477_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-2.3.5-py313h16eae64_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - conda: . win-64: - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py313h5c49287_0.conda - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py313h2da9318_0.conda - conda: https://prefix.dev/conda-forge/win-64/numpy-2.3.5-py313hce7ae62_1.conda - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/win-64/python-3.13.11-h09917c8_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - conda: . doc: channels: - url: https://prefix.dev/conda-forge/ options: pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://prefix.dev/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-auth-0.9.3-hef928c7_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-cal-0.9.13-h2c9d079_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-common-0.12.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-compression-0.3.1-h8b1a151_9.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-event-stream-0.5.7-h28f887f_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-http-0.10.7-ha8fc4e3_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-io-0.23.3-hdaf4b65_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-mqtt-0.13.3-hc63082f_11.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-s3-0.11.3-h06ab39a_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-sdkutils-0.2.4-h8b1a151_4.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-checksums-0.2.7-h8b1a151_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-crt-cpp-0.35.4-h8824e59_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-sdk-cpp-1.11.606-h20b40b1_10.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-core-cpp-1.16.1-h3a458e0_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-identity-cpp-1.13.2-h3a5f585_1.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-blobs-cpp-12.16.0-h75daedc_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-common-cpp-12.12.0-h3d7a050_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.14.0-hd454692_0.conda - conda: https://prefix.dev/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/backports.zstd-1.3.0-py313h18e8e13_0.conda - conda: https://prefix.dev/conda-forge/noarch/backrefs-5.8-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/brotli-python-1.2.0-py313hf159716_1.conda - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://prefix.dev/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/noarch/certifi-2026.1.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/linux-64/contourpy-1.3.3-py313hc8edb43_4.conda - conda: https://prefix.dev/conda-forge/noarch/cpython-3.13.11-py313hd8ed1ab_101.conda - conda: https://prefix.dev/conda-forge/linux-64/cytoolz-1.1.0-py313h07c4f96_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/debugpy-1.8.20-py313h5d5ffb9_0.conda - conda: https://prefix.dev/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://prefix.dev/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda - conda: https://prefix.dev/conda-forge/noarch/griffe-1.15.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://prefix.dev/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/ipykernel-6.31.0-pyha191276_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython-9.9.0-pyh53cf698_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/jupytext-1.19.1-pyhbbac1ac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - conda: https://prefix.dev/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://prefix.dev/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-23.0.0-h2c50142_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-acero-23.0.0-h635bf11_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-compute-23.0.0-h8c2c5c3_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-dataset-23.0.0-h635bf11_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-substrait-23.0.0-h3f74fd7_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/libcurl-8.18.0-h4e3cde8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libev-4.33-hd590300_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libfreetype6-2.14.1-h73754d4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-2.39.0-hdb79228_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-storage-2.39.0-hdbdcf42_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgrpc-1.73.1-h3288cfb_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-1.21.0-hb9b0907_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-headers-1.21.0-ha770c72_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libparquet-23.0.0-h7376487_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libpng-1.6.54-h421ea60_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libprotobuf-6.31.1-h49aed37_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libre2-11-2025.11.05-h7b12aa8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libthrift-0.22.0-h454ac66_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxml2-16-2.15.1-hca6bf5a_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libxml2-2.15.1-he237659_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py313hdd307be_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/lz4-4.4.5-py313h28739b2_1.conda - conda: https://prefix.dev/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-3.10.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/markupsafe-3.0.3-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdit-py-plugins-0.5.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mergedeep-1.3.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-1.6.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-autorefs-1.4.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-gen-files-0.6.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-get-deps-0.2.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-jupyter-0.25.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-literate-nav-0.6.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-material-9.7.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-material-extensions-1.3.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-section-index-0.3.10-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocstrings-1.0.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocstrings-python-2.0.1-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/linux-64/msgpack-python-1.1.2-py313h7037e92_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-7.17.0-h14065e2_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-pandoc-7.17.0-hc3985f0_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://prefix.dev/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py313h5dce7c4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numpy-2.3.5-py313hf6604e3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/orc-2.2.2-h19cb568_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/paginate-0.5.7-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/pandas-3.0.0-py313hbfd7664_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pandoc-3.8.3-ha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/pillow-12.1.0-py313h80991f8_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda - conda: https://prefix.dev/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/linux-64/psutil-7.2.2-py313h54dd161_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://prefix.dev/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-23.0.0-py313h78bf25f_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-core-23.0.0-py313he109ebe_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pymdown-extensions-10.21.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/linux-64/python-3.13.11-hc97d973_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-gil-3.13.11-h4df99d1_101.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/noarch/pyyaml-env-tag-1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pyzmq-27.1.0-py312hfb55c3c_0.conda - conda: https://prefix.dev/conda-forge/linux-64/re2-2025.11.05-h5301d42_0.conda - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://prefix.dev/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/rpds-py-0.30.0-py313h843e2db_0.conda - conda: https://prefix.dev/conda-forge/linux-64/s2n-1.6.2-he8a4886_1.conda - conda: https://prefix.dev/conda-forge/linux-64/scikit-learn-1.8.0-np2py313h16d504d_1.conda - conda: https://prefix.dev/conda-forge/linux-64/scipy-1.17.0-py313h4b8bb8b_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/tornado-6.5.3-py313h07c4f96_0.conda - conda: https://prefix.dev/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/watchdog-6.0.0-py313h78bf25f_2.conda - conda: https://prefix.dev/conda-forge/noarch/wcwidth-0.5.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://prefix.dev/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/zlib-ng-2.3.2-hceb46e0_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: . osx-64: - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-auth-0.9.3-hdff831d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-cal-0.9.13-hea39f9f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-common-0.12.6-h8616949_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-compression-0.3.1-h901532c_9.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-event-stream-0.5.7-ha05da6a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-http-0.10.7-h924c446_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-io-0.23.3-hf559bb5_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-mqtt-0.13.3-ha72ff4e_11.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-s3-0.11.3-he30762a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-sdkutils-0.2.4-h901532c_4.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-checksums-0.2.7-h901532c_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-crt-cpp-0.35.4-h7484968_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-sdk-cpp-1.11.606-h386ebac_10.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-core-cpp-1.16.1-he2a98a9_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-identity-cpp-1.13.2-h0e8e1c8_1.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-blobs-cpp-12.16.0-ha4e89a6_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-common-cpp-12.12.0-h2a5eb39_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.14.0-h7f37a48_0.conda - conda: https://prefix.dev/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/backports.zstd-1.3.0-py313h591e92b_0.conda - conda: https://prefix.dev/conda-forge/noarch/backrefs-5.8-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/brotli-python-1.2.0-py313h8d69aa9_1.conda - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://prefix.dev/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/noarch/certifi-2026.1.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/osx-64/contourpy-1.3.3-py313h98b818e_4.conda - conda: https://prefix.dev/conda-forge/noarch/cpython-3.13.11-py313hd8ed1ab_101.conda - conda: https://prefix.dev/conda-forge/osx-64/cytoolz-1.1.0-py313hf050af9_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/debugpy-1.8.20-py313h8b5a893_0.conda - conda: https://prefix.dev/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda - conda: https://prefix.dev/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda - conda: https://prefix.dev/conda-forge/noarch/griffe-1.15.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/ipykernel-6.31.0-pyh5552912_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython-9.9.0-pyh53cf698_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/jupytext-1.19.1-pyhbbac1ac_0.conda - conda: https://prefix.dev/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda - conda: https://prefix.dev/conda-forge/osx-64/lcms2-2.18-h90db99b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/lerc-4.0.0-hcca01a6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libabseil-20250512.1-cxx17_hfc00f1c_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-23.0.0-h8071b21_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-acero-23.0.0-h9737151_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-compute-23.0.0-hc26cc94_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-dataset-23.0.0-h9737151_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-substrait-23.0.0-h7f2e36e_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-64/libcurl-8.18.0-h9348e2b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libev-4.33-h10d778d_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libfreetype-2.14.1-h694c41f_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libfreetype6-2.14.1-h6912278_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-2.39.0-hed66dea_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-storage-2.39.0-h8ac052b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgrpc-1.73.1-h451496d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libjpeg-turbo-3.1.2-h8616949_0.conda - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-1.21.0-h7d3f41d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-headers-1.21.0-h694c41f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libparquet-23.0.0-ha0d2768_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libpng-1.6.54-h07817ec_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libprotobuf-6.31.1-hcc66ac3_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libre2-11-2025.11.05-h554ac88_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libsodium-1.0.20-hfdf4475_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libthrift-0.22.0-h687e942_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libxml2-16-2.15.1-hd57b93d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libxml2-2.15.1-h745d5cb_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py313h590e1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-64/lz4-4.4.5-py313hab77a93_1.conda - conda: https://prefix.dev/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-3.10.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/markupsafe-3.0.3-py313h0f4d31d_0.conda - conda: https://prefix.dev/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdit-py-plugins-0.5.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mergedeep-1.3.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-1.6.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-autorefs-1.4.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-gen-files-0.6.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-get-deps-0.2.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-jupyter-0.25.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-literate-nav-0.6.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-material-9.7.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-material-extensions-1.3.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-section-index-0.3.10-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocstrings-1.0.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocstrings-python-2.0.1-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/osx-64/msgpack-python-1.1.2-py313h5eff275_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-7.17.0-h14065e2_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-pandoc-7.17.0-hc3985f0_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://prefix.dev/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py313hd3f9b42_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numpy-2.3.5-py313hf1665ba_1.conda - conda: https://prefix.dev/conda-forge/osx-64/openjpeg-2.5.4-h87e8dc5_0.conda - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://prefix.dev/conda-forge/osx-64/orc-2.2.2-h3073fbf_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/paginate-0.5.7-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/pandas-3.0.0-py313h4810d26_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pandoc-3.8.3-h694c41f_0.conda - conda: https://prefix.dev/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/pillow-12.1.0-py313h16bb925_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda - conda: https://prefix.dev/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/osx-64/psutil-7.2.2-py313h16366db_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://prefix.dev/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-23.0.0-py313habf4b1d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-core-23.0.0-py313h7c712a9_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pymdown-extensions-10.21.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/osx-64/python-3.13.11-h17c18a5_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-gil-3.13.11-h4df99d1_101.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyyaml-6.0.3-py313h0f4d31d_0.conda - conda: https://prefix.dev/conda-forge/noarch/pyyaml-env-tag-1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyzmq-27.1.0-py312hb7d603e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/re2-2025.11.05-h7df6414_0.conda - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://prefix.dev/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/rpds-py-0.30.0-py313hcc225dc_0.conda - conda: https://prefix.dev/conda-forge/osx-64/scikit-learn-1.8.0-np2py313he2891f2_1.conda - conda: https://prefix.dev/conda-forge/osx-64/scipy-1.17.0-py313h2bd7e7a_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/tornado-6.5.4-py313h16c19ce_0.conda - conda: https://prefix.dev/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/watchdog-6.0.0-py313hf050af9_2.conda - conda: https://prefix.dev/conda-forge/noarch/wcwidth-0.5.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxau-1.0.12-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxdmcp-1.1.5-h8616949_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://prefix.dev/conda-forge/osx-64/zeromq-4.3.5-h6c33b1e_9.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/zlib-ng-2.3.2-h8bce59a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - conda: . osx-arm64: - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-auth-0.9.3-h1ddaa69_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-cal-0.9.13-h6ee9776_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-common-0.12.6-hc919400_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-compression-0.3.1-h16f91aa_9.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-event-stream-0.5.7-h9ae9c55_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-http-0.10.7-h5928ca5_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-io-0.23.3-hbe03c90_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-mqtt-0.13.3-haf5c5c8_11.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-s3-0.11.3-h8da9771_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h16f91aa_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-checksums-0.2.7-h16f91aa_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-crt-cpp-0.35.4-h74951b9_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-sdk-cpp-1.11.606-h4e1b0f7_10.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-core-cpp-1.16.1-h88fedcc_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-identity-cpp-1.13.2-h853621b_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.16.0-h6507aac_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-common-cpp-12.12.0-ha416c23_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.14.0-hcfc4f22_0.conda - conda: https://prefix.dev/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/backports.zstd-1.3.0-py313h48bb75e_0.conda - conda: https://prefix.dev/conda-forge/noarch/backrefs-5.8-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-python-1.2.0-py313hde1f3bb_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://prefix.dev/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/noarch/certifi-2026.1.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/contourpy-1.3.3-py313h2af2deb_4.conda - conda: https://prefix.dev/conda-forge/noarch/cpython-3.13.11-py313hd8ed1ab_101.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cytoolz-1.1.0-py313h6535dbc_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/debugpy-1.8.20-py313h1188861_0.conda - conda: https://prefix.dev/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda - conda: https://prefix.dev/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda - conda: https://prefix.dev/conda-forge/noarch/griffe-1.15.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://prefix.dev/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/ipykernel-6.31.0-pyh5552912_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython-9.9.0-pyh53cf698_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/jupytext-1.19.1-pyhbbac1ac_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lcms2-2.18-hdfa7624_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lerc-4.0.0-hd64df32_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libabseil-20250512.1-cxx17_hd41c47c_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-23.0.0-h4365f54_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-acero-23.0.0-h6de58dd_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-compute-23.0.0-h45df96a_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-dataset-23.0.0-h6de58dd_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-substrait-23.0.0-hb5627e6_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-arm64/libcurl-8.18.0-he38603e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-2.39.0-head0a95_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-storage-2.39.0-hfa3a374_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgrpc-1.73.1-h3063b79_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libjpeg-turbo-3.1.2-hc919400_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-1.21.0-he15edb5_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.21.0-hce30654_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libparquet-23.0.0-hcc2992d_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libpng-1.6.54-h132b30e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libprotobuf-6.31.1-h98f38fd_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libre2-11-2025.11.05-h91c62da_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsodium-1.0.20-h99b78c6_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libthrift-0.22.0-h14a376c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-16-2.15.1-h5ef1a60_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-2.15.1-h8d039ee_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py313he297ed2_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-4.4.5-py313hd065f0a_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-3.10.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/markupsafe-3.0.3-py313h7d74516_0.conda - conda: https://prefix.dev/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdit-py-plugins-0.5.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mergedeep-1.3.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-1.6.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-autorefs-1.4.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-gen-files-0.6.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-get-deps-0.2.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-jupyter-0.25.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-literate-nav-0.6.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-material-9.7.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-material-extensions-1.3.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-section-index-0.3.10-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocstrings-1.0.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocstrings-python-2.0.1-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/msgpack-python-1.1.2-py313ha61f8ec_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-7.17.0-h14065e2_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-pandoc-7.17.0-hc3985f0_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://prefix.dev/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py313ha873477_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-2.3.5-py313h16eae64_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/orc-2.2.2-hac85105_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/paginate-0.5.7-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pandas-3.0.0-py313h6974306_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pandoc-3.8.3-hce30654_0.conda - conda: https://prefix.dev/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pillow-12.1.0-py313h45e5a15_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda - conda: https://prefix.dev/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/psutil-7.2.2-py313h6688731_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda - conda: https://prefix.dev/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-23.0.0-py313h39782a4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-core-23.0.0-py313hfb690af_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pymdown-extensions-10.21.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-gil-3.13.11-h4df99d1_101.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyyaml-6.0.3-py313h7d74516_0.conda - conda: https://prefix.dev/conda-forge/noarch/pyyaml-env-tag-1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyzmq-27.1.0-py312hd65ceae_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/re2-2025.11.05-h64b956e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://prefix.dev/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/rpds-py-0.30.0-py313h2c089d5_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py313h3b23316_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scipy-1.17.0-py313hc753a45_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tornado-6.5.4-py313h6535dbc_0.conda - conda: https://prefix.dev/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/watchdog-6.0.0-py313h6535dbc_2.conda - conda: https://prefix.dev/conda-forge/noarch/wcwidth-0.5.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-hc919400_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zeromq-4.3.5-h888dc83_9.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-ng-2.3.2-hed4e4f5_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - conda: . win-64: - conda: https://prefix.dev/conda-forge/win-64/_openmp_mutex-4.5-2_gnu.conda - conda: https://prefix.dev/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-auth-0.9.3-h2970c50_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-cal-0.9.13-h46f3b43_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-common-0.12.6-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-compression-0.3.1-hcb3a2da_9.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-event-stream-0.5.7-ha388e84_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-http-0.10.7-hc678f4a_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-io-0.23.3-h0d5b9f9_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-mqtt-0.13.3-hfa314fa_11.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-s3-0.11.3-ha659bf3_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-sdkutils-0.2.4-hcb3a2da_4.conda - conda: https://prefix.dev/conda-forge/win-64/aws-checksums-0.2.7-hcb3a2da_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-crt-cpp-0.35.4-hca034e6_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-sdk-cpp-1.11.606-hac16450_10.conda - conda: https://prefix.dev/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/backports.zstd-1.3.0-py313h2a31948_0.conda - conda: https://prefix.dev/conda-forge/noarch/backrefs-5.8-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/brotli-python-1.2.0-py313h3ebfc14_1.conda - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://prefix.dev/conda-forge/win-64/c-ares-1.34.6-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda - conda: https://prefix.dev/conda-forge/noarch/certifi-2026.1.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyha7b4d00_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/win-64/contourpy-1.3.3-py313h1a38498_4.conda - conda: https://prefix.dev/conda-forge/noarch/cpython-3.13.11-py313hd8ed1ab_101.conda - conda: https://prefix.dev/conda-forge/win-64/cytoolz-1.1.0-py313h5ea7bf4_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/debugpy-1.8.20-py313h927ade5_0.conda - conda: https://prefix.dev/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/griffe-1.15.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda - conda: https://prefix.dev/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/ipykernel-6.31.0-pyh6dadd2b_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython-9.9.0-pyhe2676ad_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/jupytext-1.19.1-pyhbbac1ac_0.conda - conda: https://prefix.dev/conda-forge/win-64/krb5-1.21.3-hdf4eb48_0.conda - conda: https://prefix.dev/conda-forge/win-64/lcms2-2.18-hf2c6c5f_0.conda - conda: https://prefix.dev/conda-forge/win-64/lerc-4.0.0-h6470a55_1.conda - conda: https://prefix.dev/conda-forge/win-64/libabseil-20250512.1-cxx17_habfad5f_0.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-23.0.0-hcf7e2ff_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-acero-23.0.0-h7d8d6a5_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-compute-23.0.0-h2db994a_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-dataset-23.0.0-h7d8d6a5_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-substrait-23.0.0-hf865cc0_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlicommon-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlidec-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlienc-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/libcurl-8.18.0-h43ecb02_0.conda - conda: https://prefix.dev/conda-forge/win-64/libdeflate-1.25-h51727cc_0.conda - conda: https://prefix.dev/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libfreetype-2.14.1-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/win-64/libfreetype6-2.14.1-hdbac1cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgcc-15.2.0-h8ee18e1_16.conda - conda: https://prefix.dev/conda-forge/win-64/libgomp-15.2.0-h8ee18e1_16.conda - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-2.39.0-h19ee442_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-storage-2.39.0-he04ea4c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgrpc-1.73.1-h317e13b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - conda: https://prefix.dev/conda-forge/win-64/libjpeg-turbo-3.1.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libparquet-23.0.0-h7051d1f_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libpng-1.6.54-h7351971_0.conda - conda: https://prefix.dev/conda-forge/win-64/libprotobuf-6.31.1-hdcda5b4_4.conda - conda: https://prefix.dev/conda-forge/win-64/libre2-11-2025.11.05-h0eb2380_0.conda - conda: https://prefix.dev/conda-forge/win-64/libsodium-1.0.20-hc70643c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda - conda: https://prefix.dev/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda - conda: https://prefix.dev/conda-forge/win-64/libthrift-0.22.0-h23985f6_1.conda - conda: https://prefix.dev/conda-forge/win-64/libtiff-4.7.1-h8f73337_1.conda - conda: https://prefix.dev/conda-forge/win-64/libutf8proc-2.11.3-hb980946_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwebp-base-1.6.0-h4d5522a_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - conda: https://prefix.dev/conda-forge/win-64/libxcb-1.17.0-h0e4246c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py313h5c49287_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/lz4-4.4.5-py313h4bbca4b_1.conda - conda: https://prefix.dev/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-3.10.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/markupsafe-3.0.3-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdit-py-plugins-0.5.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mergedeep-1.3.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-1.6.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-autorefs-1.4.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-gen-files-0.6.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-get-deps-0.2.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-jupyter-0.25.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-literate-nav-0.6.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-material-9.7.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-material-extensions-1.3.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocs-section-index-0.3.10-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocstrings-1.0.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mkdocstrings-python-2.0.1-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda - conda: https://prefix.dev/conda-forge/win-64/msgpack-python-1.1.2-py313hf069bd2_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-7.17.0-h14065e2_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbconvert-pandoc-7.17.0-hc3985f0_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py313h2da9318_0.conda - conda: https://prefix.dev/conda-forge/win-64/numpy-2.3.5-py313hce7ae62_1.conda - conda: https://prefix.dev/conda-forge/win-64/openjpeg-2.5.4-h24db6dd_0.conda - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://prefix.dev/conda-forge/win-64/orc-2.2.2-hbd3206f_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/paginate-0.5.7-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/pandas-3.0.0-py313h26f5e95_0.conda - conda: https://prefix.dev/conda-forge/win-64/pandoc-3.8.3-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/pillow-12.1.0-py313h38f99e1_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/win-64/psutil-7.2.2-py313h5fd188c_0.conda - conda: https://prefix.dev/conda-forge/win-64/pthread-stubs-0.4-h0e40799_1002.conda - conda: https://prefix.dev/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/pyarrow-23.0.0-py313hfa70ccb_0.conda - conda: https://prefix.dev/conda-forge/win-64/pyarrow-core-23.0.0-py313h5921983_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pymdown-extensions-10.21.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - conda: https://prefix.dev/conda-forge/win-64/python-3.13.11-h09917c8_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-gil-3.13.11-h4df99d1_101.conda - conda: https://prefix.dev/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/pywin32-311-py313h40c08fc_1.conda - conda: https://prefix.dev/conda-forge/win-64/pyyaml-6.0.3-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/noarch/pyyaml-env-tag-1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/pyzmq-27.1.0-py312hbb5da91_0.conda - conda: https://prefix.dev/conda-forge/win-64/re2-2025.11.05-ha104f34_0.conda - conda: https://prefix.dev/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/rpds-py-0.30.0-py313hfbe8231_0.conda - conda: https://prefix.dev/conda-forge/win-64/scikit-learn-1.8.0-np2py313h4ce4a18_1.conda - conda: https://prefix.dev/conda-forge/win-64/scipy-1.17.0-py313he51e9a2_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/win-64/snappy-1.2.2-h7fa0ca8_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tornado-6.5.4-py313h5ea7bf4_0.conda - conda: https://prefix.dev/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vs2015_runtime-14.44.35208-h38c0c73_34.conda - conda: https://prefix.dev/conda-forge/win-64/watchdog-6.0.0-py313hfa70ccb_2.conda - conda: https://prefix.dev/conda-forge/noarch/wcwidth-0.5.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://prefix.dev/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda - conda: https://prefix.dev/conda-forge/win-64/xorg-libxau-1.0.12-hba3369d_1.conda - conda: https://prefix.dev/conda-forge/win-64/xorg-libxdmcp-1.1.5-hba3369d_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://prefix.dev/conda-forge/win-64/zeromq-4.3.5-h5bddc39_9.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/zlib-ng-2.3.2-h0261ad2_1.conda - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - conda: . examples: channels: - url: https://prefix.dev/conda-forge/ indexes: - https://pypi.org/simple options: pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-auth-0.9.3-hef928c7_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-cal-0.9.13-h2c9d079_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-common-0.12.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-compression-0.3.1-h8b1a151_9.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-event-stream-0.5.7-h28f887f_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-http-0.10.7-ha8fc4e3_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-io-0.23.3-hdaf4b65_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-mqtt-0.13.3-hc63082f_11.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-s3-0.11.3-h06ab39a_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-sdkutils-0.2.4-h8b1a151_4.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-checksums-0.2.7-h8b1a151_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-crt-cpp-0.35.4-h8824e59_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-sdk-cpp-1.11.606-h20b40b1_10.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-core-cpp-1.16.1-h3a458e0_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-identity-cpp-1.13.2-h3a5f585_1.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-blobs-cpp-12.16.0-h75daedc_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-common-cpp-12.12.0-h3d7a050_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.14.0-hd454692_0.conda - conda: https://prefix.dev/conda-forge/linux-64/backports.zstd-1.3.0-py313h18e8e13_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/brotli-python-1.2.0-py313hf159716_1.conda - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://prefix.dev/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/contourpy-1.3.3-py313hc8edb43_4.conda - conda: https://prefix.dev/conda-forge/linux-64/cytoolz-1.1.0-py313h07c4f96_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/donfig-0.8.1.post1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://prefix.dev/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda - conda: https://prefix.dev/conda-forge/linux-64/graphblas-9.4.5-hb61eb52_0.conda - conda: https://prefix.dev/conda-forge/noarch/graphblas-algorithms-2023.10.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/juliaup-1.19.4-hdab8a38_0.conda - conda: https://prefix.dev/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - conda: https://prefix.dev/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://prefix.dev/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-23.0.0-h2c50142_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-acero-23.0.0-h635bf11_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-compute-23.0.0-h8c2c5c3_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-dataset-23.0.0-h635bf11_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-substrait-23.0.0-h3f74fd7_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/libcurl-8.18.0-h4e3cde8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libev-4.33-hd590300_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libfreetype6-2.14.1-h73754d4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-2.39.0-hdb79228_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-storage-2.39.0-hdbdcf42_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgrpc-1.73.1-h3288cfb_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-1.21.0-hb9b0907_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-headers-1.21.0-ha770c72_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libparquet-23.0.0-h7376487_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libpng-1.6.54-h421ea60_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libprotobuf-6.31.1-h49aed37_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libre2-11-2025.11.05-h7b12aa8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libthrift-0.22.0-h454ac66_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxml2-16-2.15.1-hca6bf5a_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libxml2-2.15.1-he237659_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/llvm-openmp-21.1.8-h4922eb0_0.conda - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py313hdd307be_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/lz4-4.4.5-py313h28739b2_1.conda - conda: https://prefix.dev/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://prefix.dev/conda-forge/linux-64/markupsafe-3.0.3-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/linux-64/msgpack-python-1.1.2-py313h7037e92_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.16.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://prefix.dev/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py313h5dce7c4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numpy-2.3.5-py313hf6604e3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/orc-2.2.2-h19cb568_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pandas-3.0.0-py313hbfd7664_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pillow-12.1.0-py313h80991f8_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-26.0-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda - conda: https://prefix.dev/conda-forge/linux-64/psutil-7.2.2-py313h54dd161_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-23.0.0-py313h78bf25f_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-core-23.0.0-py313he109ebe_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/linux-64/python-3.13.11-hc97d973_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-graphblas-2025.2.0-pyhff2d567_0.conda - conda: https://prefix.dev/conda-forge/linux-64/python-suitesparse-graphblas-9.4.5.0-py313h585d76f_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_1.conda - conda: https://prefix.dev/conda-forge/linux-64/re2-2025.11.05-h5301d42_0.conda - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://prefix.dev/conda-forge/linux-64/s2n-1.6.2-he8a4886_1.conda - conda: https://prefix.dev/conda-forge/linux-64/scikit-learn-1.8.0-np2py313h16d504d_1.conda - conda: https://prefix.dev/conda-forge/linux-64/scipy-1.17.0-py313h4b8bb8b_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/tornado-6.5.3-py313h07c4f96_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl osx-64: - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-auth-0.9.3-hdff831d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-cal-0.9.13-hea39f9f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-common-0.12.6-h8616949_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-compression-0.3.1-h901532c_9.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-event-stream-0.5.7-ha05da6a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-http-0.10.7-h924c446_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-io-0.23.3-hf559bb5_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-mqtt-0.13.3-ha72ff4e_11.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-s3-0.11.3-he30762a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-sdkutils-0.2.4-h901532c_4.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-checksums-0.2.7-h901532c_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-crt-cpp-0.35.4-h7484968_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-sdk-cpp-1.11.606-h386ebac_10.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-core-cpp-1.16.1-he2a98a9_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-identity-cpp-1.13.2-h0e8e1c8_1.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-blobs-cpp-12.16.0-ha4e89a6_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-common-cpp-12.12.0-h2a5eb39_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.14.0-h7f37a48_0.conda - conda: https://prefix.dev/conda-forge/osx-64/backports.zstd-1.3.0-py313h591e92b_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/brotli-python-1.2.0-py313h8d69aa9_1.conda - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://prefix.dev/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-64/cffi-2.0.0-py313hf57695f_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/contourpy-1.3.3-py313h98b818e_4.conda - conda: https://prefix.dev/conda-forge/osx-64/cytoolz-1.1.0-py313hf050af9_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/donfig-0.8.1.post1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda - conda: https://prefix.dev/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda - conda: https://prefix.dev/conda-forge/osx-64/graphblas-9.4.5-hb362918_0.conda - conda: https://prefix.dev/conda-forge/noarch/graphblas-algorithms-2023.10.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/juliaup-1.19.4-hb64060d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda - conda: https://prefix.dev/conda-forge/osx-64/lcms2-2.18-h90db99b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/lerc-4.0.0-hcca01a6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libabseil-20250512.1-cxx17_hfc00f1c_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-23.0.0-h8071b21_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-acero-23.0.0-h9737151_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-compute-23.0.0-hc26cc94_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-dataset-23.0.0-h9737151_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-substrait-23.0.0-h7f2e36e_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-64/libcurl-8.18.0-h9348e2b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libev-4.33-h10d778d_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libfreetype-2.14.1-h694c41f_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libfreetype6-2.14.1-h6912278_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-2.39.0-hed66dea_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-storage-2.39.0-h8ac052b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgrpc-1.73.1-h451496d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libjpeg-turbo-3.1.2-h8616949_0.conda - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-1.21.0-h7d3f41d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-headers-1.21.0-h694c41f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libparquet-23.0.0-ha0d2768_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libpng-1.6.54-h07817ec_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libprotobuf-6.31.1-hcc66ac3_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libre2-11-2025.11.05-h554ac88_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libthrift-0.22.0-h687e942_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libxml2-16-2.15.1-hd57b93d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libxml2-2.15.1-h745d5cb_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py313h590e1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-64/lz4-4.4.5-py313hab77a93_1.conda - conda: https://prefix.dev/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda - conda: https://prefix.dev/conda-forge/osx-64/markupsafe-3.0.3-py313h0f4d31d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/msgpack-python-1.1.2-py313h5eff275_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.16.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://prefix.dev/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py313hd3f9b42_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numpy-2.3.5-py313hf1665ba_1.conda - conda: https://prefix.dev/conda-forge/osx-64/openjpeg-2.5.4-h87e8dc5_0.conda - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://prefix.dev/conda-forge/osx-64/orc-2.2.2-h3073fbf_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pandas-3.0.0-py313h4810d26_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pillow-12.1.0-py313h16bb925_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-26.0-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda - conda: https://prefix.dev/conda-forge/osx-64/psutil-7.2.2-py313h16366db_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-23.0.0-py313habf4b1d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-core-23.0.0-py313h7c712a9_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/osx-64/python-3.13.11-h17c18a5_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-graphblas-2025.2.0-pyhff2d567_0.conda - conda: https://prefix.dev/conda-forge/osx-64/python-suitesparse-graphblas-9.4.5.0-py313hd5e51e8_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-64/pyyaml-6.0.3-py313h7c6a591_1.conda - conda: https://prefix.dev/conda-forge/osx-64/re2-2025.11.05-h7df6414_0.conda - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/scikit-learn-1.8.0-np2py313he2891f2_1.conda - conda: https://prefix.dev/conda-forge/osx-64/scipy-1.17.0-py313h2bd7e7a_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/tornado-6.5.4-py313h16c19ce_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxau-1.0.12-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxdmcp-1.1.5-h8616949_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/zlib-ng-2.3.3-h8bce59a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl osx-arm64: - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-auth-0.9.3-h1ddaa69_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-cal-0.9.13-h6ee9776_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-common-0.12.6-hc919400_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-compression-0.3.1-h16f91aa_9.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-event-stream-0.5.7-h9ae9c55_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-http-0.10.7-h5928ca5_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-io-0.23.3-hbe03c90_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-mqtt-0.13.3-haf5c5c8_11.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-s3-0.11.3-h8da9771_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h16f91aa_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-checksums-0.2.7-h16f91aa_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-crt-cpp-0.35.4-h74951b9_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-sdk-cpp-1.11.606-h4e1b0f7_10.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-core-cpp-1.16.1-h88fedcc_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-identity-cpp-1.13.2-h853621b_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.16.0-h6507aac_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-common-cpp-12.12.0-ha416c23_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.14.0-hcfc4f22_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/backports.zstd-1.3.0-py313h48bb75e_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-python-1.2.0-py313hde1f3bb_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://prefix.dev/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cffi-2.0.0-py313h224173a_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/contourpy-1.3.3-py313h2af2deb_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cytoolz-1.1.0-py313h6535dbc_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/donfig-0.8.1.post1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda - conda: https://prefix.dev/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/graphblas-9.4.5-h22bf013_0.conda - conda: https://prefix.dev/conda-forge/noarch/graphblas-algorithms-2023.10.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/juliaup-1.19.4-h748bcf4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lcms2-2.18-hdfa7624_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lerc-4.0.0-hd64df32_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libabseil-20250512.1-cxx17_hd41c47c_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-23.0.0-h4365f54_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-acero-23.0.0-h6de58dd_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-compute-23.0.0-h45df96a_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-dataset-23.0.0-h6de58dd_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-substrait-23.0.0-hb5627e6_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-arm64/libcurl-8.18.0-he38603e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-2.39.0-head0a95_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-storage-2.39.0-hfa3a374_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgrpc-1.73.1-h3063b79_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libjpeg-turbo-3.1.2-hc919400_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-1.21.0-he15edb5_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.21.0-hce30654_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libparquet-23.0.0-hcc2992d_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libpng-1.6.54-h132b30e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libprotobuf-6.31.1-h98f38fd_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libre2-11-2025.11.05-h91c62da_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libthrift-0.22.0-h14a376c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-16-2.15.1-h5ef1a60_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-2.15.1-h8d039ee_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py313he297ed2_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-4.4.5-py313hd065f0a_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/markupsafe-3.0.3-py313h7d74516_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/msgpack-python-1.1.2-py313ha61f8ec_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.16.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://prefix.dev/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py313ha873477_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-2.3.5-py313h16eae64_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/orc-2.2.2-hac85105_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pandas-3.0.0-py313h6974306_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pillow-12.1.0-py313h45e5a15_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-26.0-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/psutil-7.2.2-py313h6688731_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-23.0.0-py313h39782a4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-core-23.0.0-py313hfb690af_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-graphblas-2025.2.0-pyhff2d567_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-suitesparse-graphblas-9.4.5.0-py313h44f8b29_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyyaml-6.0.3-py313h65a2061_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/re2-2025.11.05-h64b956e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py313h3b23316_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scipy-1.17.0-py313hc753a45_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tornado-6.5.4-py313h6535dbc_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-hc919400_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl win-64: - conda: https://prefix.dev/conda-forge/win-64/_openmp_mutex-4.5-2_gnu.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-auth-0.9.3-h2970c50_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-cal-0.9.13-h46f3b43_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-common-0.12.6-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-compression-0.3.1-hcb3a2da_9.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-event-stream-0.5.7-ha388e84_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-http-0.10.7-hc678f4a_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-io-0.23.3-h0d5b9f9_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-mqtt-0.13.3-hfa314fa_11.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-s3-0.11.3-ha659bf3_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-sdkutils-0.2.4-hcb3a2da_4.conda - conda: https://prefix.dev/conda-forge/win-64/aws-checksums-0.2.7-hcb3a2da_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-crt-cpp-0.35.4-hca034e6_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-sdk-cpp-1.11.606-hac16450_10.conda - conda: https://prefix.dev/conda-forge/win-64/backports.zstd-1.3.0-py313h2a31948_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/brotli-python-1.2.0-py313h3ebfc14_1.conda - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://prefix.dev/conda-forge/win-64/c-ares-1.34.6-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda - conda: https://prefix.dev/conda-forge/win-64/cffi-2.0.0-py313h5ea7bf4_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyha7b4d00_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/contourpy-1.3.3-py313h1a38498_4.conda - conda: https://prefix.dev/conda-forge/win-64/cytoolz-1.1.0-py313h5ea7bf4_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/donfig-0.8.1.post1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/graphblas-9.4.5-h1163047_0.conda - conda: https://prefix.dev/conda-forge/noarch/graphblas-algorithms-2023.10.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/juliaup-1.19.4-h77a83cd_0.conda - conda: https://prefix.dev/conda-forge/win-64/krb5-1.21.3-hdf4eb48_0.conda - conda: https://prefix.dev/conda-forge/win-64/lcms2-2.18-hf2c6c5f_0.conda - conda: https://prefix.dev/conda-forge/win-64/lerc-4.0.0-h6470a55_1.conda - conda: https://prefix.dev/conda-forge/win-64/libabseil-20250512.1-cxx17_habfad5f_0.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-23.0.0-hcf7e2ff_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-acero-23.0.0-h7d8d6a5_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-compute-23.0.0-h2db994a_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-dataset-23.0.0-h7d8d6a5_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-substrait-23.0.0-hf865cc0_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlicommon-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlidec-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlienc-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/libcurl-8.18.0-h43ecb02_0.conda - conda: https://prefix.dev/conda-forge/win-64/libdeflate-1.25-h51727cc_0.conda - conda: https://prefix.dev/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libfreetype-2.14.1-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/win-64/libfreetype6-2.14.1-hdbac1cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgcc-15.2.0-h8ee18e1_16.conda - conda: https://prefix.dev/conda-forge/win-64/libgomp-15.2.0-h8ee18e1_16.conda - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-2.39.0-h19ee442_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-storage-2.39.0-he04ea4c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgrpc-1.73.1-h317e13b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - conda: https://prefix.dev/conda-forge/win-64/libjpeg-turbo-3.1.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libparquet-23.0.0-h7051d1f_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libpng-1.6.54-h7351971_0.conda - conda: https://prefix.dev/conda-forge/win-64/libprotobuf-6.31.1-hdcda5b4_4.conda - conda: https://prefix.dev/conda-forge/win-64/libre2-11-2025.11.05-h0eb2380_0.conda - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda - conda: https://prefix.dev/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda - conda: https://prefix.dev/conda-forge/win-64/libthrift-0.22.0-h23985f6_1.conda - conda: https://prefix.dev/conda-forge/win-64/libtiff-4.7.1-h8f73337_1.conda - conda: https://prefix.dev/conda-forge/win-64/libutf8proc-2.11.3-hb980946_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwebp-base-1.6.0-h4d5522a_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - conda: https://prefix.dev/conda-forge/win-64/libxcb-1.17.0-h0e4246c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py313h5c49287_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/lz4-4.4.5-py313h4bbca4b_1.conda - conda: https://prefix.dev/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda - conda: https://prefix.dev/conda-forge/win-64/markupsafe-3.0.3-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda - conda: https://prefix.dev/conda-forge/win-64/msgpack-python-1.1.2-py313hf069bd2_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.16.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py313h2da9318_0.conda - conda: https://prefix.dev/conda-forge/win-64/numpy-2.3.5-py313hce7ae62_1.conda - conda: https://prefix.dev/conda-forge/win-64/openjpeg-2.5.4-h24db6dd_0.conda - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://prefix.dev/conda-forge/win-64/orc-2.2.2-hbd3206f_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pandas-3.0.0-py313h26f5e95_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/pillow-12.1.0-py313h38f99e1_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-26.0-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/win-64/psutil-7.2.2-py313h5fd188c_0.conda - conda: https://prefix.dev/conda-forge/win-64/pthread-stubs-0.4-h0e40799_1002.conda - conda: https://prefix.dev/conda-forge/win-64/pyarrow-23.0.0-py313hfa70ccb_0.conda - conda: https://prefix.dev/conda-forge/win-64/pyarrow-core-23.0.0-py313h5921983_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - conda: https://prefix.dev/conda-forge/win-64/python-3.13.11-h09917c8_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-graphblas-2025.2.0-pyhff2d567_0.conda - conda: https://prefix.dev/conda-forge/win-64/python-suitesparse-graphblas-9.4.5.0-py313ha04d1f9_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/win-64/pyyaml-6.0.3-py313hd650c13_1.conda - conda: https://prefix.dev/conda-forge/win-64/re2-2025.11.05-ha104f34_0.conda - conda: https://prefix.dev/conda-forge/win-64/scikit-learn-1.8.0-np2py313h4ce4a18_1.conda - conda: https://prefix.dev/conda-forge/win-64/scipy-1.17.0-py313he51e9a2_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/win-64/snappy-1.2.2-h7fa0ca8_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tornado-6.5.4-py313h5ea7bf4_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vs2015_runtime-14.44.35208-h38c0c73_34.conda - conda: https://prefix.dev/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda - conda: https://prefix.dev/conda-forge/win-64/xorg-libxau-1.0.12-hba3369d_1.conda - conda: https://prefix.dev/conda-forge/win-64/xorg-libxdmcp-1.1.5-hba3369d_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/zlib-ng-2.3.3-h0261ad2_1.conda - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl finch: channels: - url: https://prefix.dev/conda-forge/ indexes: - https://pypi.org/simple options: pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://prefix.dev/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/coverage-7.13.2-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/juliaup-1.19.4-hdab8a38_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py313hdd307be_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py313h5dce7c4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numpy-2.3.5-py313hf6604e3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pytest-codspeed-4.2.0-py313h54dd161_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/python-3.13.11-hc97d973_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/scipy-1.17.0-py313h4b8bb8b_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl osx-64: - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-64/cffi-2.0.0-py313hf57695f_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/coverage-7.13.2-py313h7c6a591_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/juliaup-1.19.4-hb64060d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py313h590e1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py313hd3f9b42_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numpy-2.3.5-py313hf1665ba_1.conda - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pytest-codspeed-4.2.0-py313hcb05632_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/python-3.13.11-h17c18a5_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/scipy-1.17.0-py313h2bd7e7a_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl osx-arm64: - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cffi-2.0.0-py313h224173a_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/coverage-7.13.2-py313h65a2061_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/juliaup-1.19.4-h748bcf4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py313he297ed2_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py313ha873477_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-2.3.5-py313h16eae64_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pytest-codspeed-4.2.0-py313h9734d34_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scipy-1.17.0-py313hc753a45_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl win-64: - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda - conda: https://prefix.dev/conda-forge/win-64/cffi-2.0.0-py313h5ea7bf4_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/coverage-7.13.2-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/juliaup-1.19.4-h77a83cd_0.conda - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py313h5c49287_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py313h2da9318_0.conda - conda: https://prefix.dev/conda-forge/win-64/numpy-2.3.5-py313hce7ae62_1.conda - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pytest-codspeed-4.2.0-py313h5fd188c_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/python-3.13.11-h09917c8_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/scipy-1.17.0-py313he51e9a2_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl matrepr: channels: - url: https://prefix.dev/conda-forge/ options: pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://prefix.dev/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py313hdd307be_0.conda - conda: https://prefix.dev/conda-forge/noarch/matrepr-1.0.1-pyh4f8845f_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py313h5dce7c4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numpy-2.3.5-py313hf6604e3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/linux-64/python-3.13.11-hc97d973_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/tabulate-0.9.0-pyhcf101f3_3.conda - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: . osx-64: - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py313h590e1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/matrepr-1.0.1-pyh4f8845f_0.conda - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py313hd3f9b42_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numpy-2.3.5-py313hf1665ba_1.conda - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/osx-64/python-3.13.11-h17c18a5_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/tabulate-0.9.0-pyhcf101f3_3.conda - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - conda: . osx-arm64: - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py313he297ed2_0.conda - conda: https://prefix.dev/conda-forge/noarch/matrepr-1.0.1-pyh4f8845f_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py313ha873477_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-2.3.5-py313h16eae64_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/tabulate-0.9.0-pyhcf101f3_3.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - conda: . win-64: - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py313h5c49287_0.conda - conda: https://prefix.dev/conda-forge/noarch/matrepr-1.0.1-pyh4f8845f_0.conda - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py313h2da9318_0.conda - conda: https://prefix.dev/conda-forge/win-64/numpy-2.3.5-py313hce7ae62_1.conda - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/win-64/python-3.13.11-h09917c8_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/tabulate-0.9.0-pyhcf101f3_3.conda - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - conda: . mindeps: channels: - url: https://prefix.dev/conda-forge/ indexes: - https://pypi.org/simple options: pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://prefix.dev/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-auth-0.9.3-hef928c7_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-cal-0.9.13-h2c9d079_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-common-0.12.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-compression-0.3.1-h8b1a151_9.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-event-stream-0.5.7-h28f887f_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-http-0.10.7-ha8fc4e3_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-io-0.23.3-hdaf4b65_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-mqtt-0.13.3-hc63082f_11.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-s3-0.11.3-h06ab39a_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-sdkutils-0.2.4-h8b1a151_4.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-checksums-0.2.7-h8b1a151_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-crt-cpp-0.35.4-h8824e59_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-sdk-cpp-1.11.606-h20b40b1_10.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-core-cpp-1.16.1-h3a458e0_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-identity-cpp-1.13.2-h3a5f585_1.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-blobs-cpp-12.16.0-h75daedc_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-common-cpp-12.12.0-h3d7a050_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.14.0-hd454692_0.conda - conda: https://prefix.dev/conda-forge/linux-64/backports.zstd-1.3.0-py311h6b1f9c4_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/brotli-python-1.2.0-py311h66f275b_1.conda - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://prefix.dev/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/linux-64/cffi-2.0.0-py311h03d9500_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/contourpy-1.3.3-py311h724c32c_4.conda - conda: https://prefix.dev/conda-forge/linux-64/coverage-7.13.2-py311h3778330_0.conda - conda: https://prefix.dev/conda-forge/linux-64/cytoolz-1.1.0-py311h49ec1c0_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://prefix.dev/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/juliaup-1.19.4-hdab8a38_0.conda - conda: https://prefix.dev/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - conda: https://prefix.dev/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://prefix.dev/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-23.0.0-h2c50142_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-acero-23.0.0-h635bf11_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-compute-23.0.0-h8c2c5c3_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-dataset-23.0.0-h635bf11_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-substrait-23.0.0-h3f74fd7_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/libcurl-8.18.0-h4e3cde8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libev-4.33-hd590300_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libfreetype6-2.14.1-h73754d4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-2.39.0-hdb79228_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-storage-2.39.0-hdbdcf42_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgrpc-1.73.1-h3288cfb_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-1.21.0-hb9b0907_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-headers-1.21.0-ha770c72_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libparquet-23.0.0-h7376487_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libpng-1.6.54-h421ea60_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libprotobuf-6.31.1-h49aed37_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libre2-11-2025.11.05-h7b12aa8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libthrift-0.22.0-h454ac66_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libxml2-16-2.15.1-hca6bf5a_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libxml2-2.15.1-he237659_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py311h41a00d4_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/lz4-4.4.5-py311h1c460e0_1.conda - conda: https://prefix.dev/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/markupsafe-3.0.3-py311h3778330_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/msgpack-python-1.1.2-py311hdf67eae_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.16.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://prefix.dev/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py311h3c884d5_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - conda: https://prefix.dev/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/orc-2.2.2-h19cb568_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pandas-3.0.0-py311h8032f78_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pillow-12.1.0-py311hf88fc01_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh8b19718_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda - conda: https://prefix.dev/conda-forge/linux-64/psutil-7.2.2-py311haee01d2_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-23.0.0-py311h38be061_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-core-23.0.0-py311h342b5a4_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pytest-codspeed-4.2.0-py311haee01d2_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/python-3.11.14-hd63d673_3_cpython.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.11-8_cp311.conda - conda: https://prefix.dev/conda-forge/linux-64/pyyaml-6.0.3-py311h3778330_0.conda - conda: https://prefix.dev/conda-forge/linux-64/re2-2025.11.05-h5301d42_0.conda - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/s2n-1.6.2-he8a4886_1.conda - conda: https://prefix.dev/conda-forge/linux-64/scikit-learn-1.8.0-np2py311ha15b03d_1.conda - conda: https://prefix.dev/conda-forge/linux-64/scipy-1.17.0-py311hbe70eeb_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/tornado-6.5.3-py311h49ec1c0_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/zlib-ng-2.3.2-hceb46e0_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/c8/cd8cba0b633db2cf2fb9eaf0afe7b0552394bcf2c5b1e206b982ab37dd7d/finch_mlir-0.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl osx-64: - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-auth-0.9.3-hdff831d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-cal-0.9.13-hea39f9f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-common-0.12.6-h8616949_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-compression-0.3.1-h901532c_9.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-event-stream-0.5.7-ha05da6a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-http-0.10.7-h924c446_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-io-0.23.3-hf559bb5_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-mqtt-0.13.3-ha72ff4e_11.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-s3-0.11.3-he30762a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-sdkutils-0.2.4-h901532c_4.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-checksums-0.2.7-h901532c_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-crt-cpp-0.35.4-h7484968_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-sdk-cpp-1.11.606-h386ebac_10.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-core-cpp-1.16.1-he2a98a9_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-identity-cpp-1.13.2-h0e8e1c8_1.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-blobs-cpp-12.16.0-ha4e89a6_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-common-cpp-12.12.0-h2a5eb39_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.14.0-h7f37a48_0.conda - conda: https://prefix.dev/conda-forge/osx-64/backports.zstd-1.3.0-py311hdc67420_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/brotli-python-1.2.0-py311h7e844b6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://prefix.dev/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-64/cffi-2.0.0-py311h26bcf6e_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/contourpy-1.3.3-py311h9d13916_4.conda - conda: https://prefix.dev/conda-forge/osx-64/coverage-7.13.2-py311h53ebfaf_0.conda - conda: https://prefix.dev/conda-forge/osx-64/cytoolz-1.1.0-py311hf197a57_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda - conda: https://prefix.dev/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/juliaup-1.19.4-hb64060d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda - conda: https://prefix.dev/conda-forge/osx-64/lcms2-2.18-h90db99b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/lerc-4.0.0-hcca01a6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libabseil-20250512.1-cxx17_hfc00f1c_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-23.0.0-h8071b21_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-acero-23.0.0-h9737151_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-compute-23.0.0-hc26cc94_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-dataset-23.0.0-h9737151_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-substrait-23.0.0-h7f2e36e_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-64/libcurl-8.18.0-h9348e2b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libev-4.33-h10d778d_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libfreetype-2.14.1-h694c41f_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libfreetype6-2.14.1-h6912278_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-2.39.0-hed66dea_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-storage-2.39.0-h8ac052b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgrpc-1.73.1-h451496d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libjpeg-turbo-3.1.2-h8616949_0.conda - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-1.21.0-h7d3f41d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-headers-1.21.0-h694c41f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libparquet-23.0.0-ha0d2768_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libpng-1.6.54-h07817ec_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libprotobuf-6.31.1-hcc66ac3_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libre2-11-2025.11.05-h554ac88_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libthrift-0.22.0-h687e942_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libxml2-16-2.15.1-hd57b93d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libxml2-2.15.1-h745d5cb_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py311hb26b958_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-64/lz4-4.4.5-py311h14c9969_1.conda - conda: https://prefix.dev/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/markupsafe-3.0.3-py311he13f9b5_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/msgpack-python-1.1.2-py311haec20ae_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.16.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://prefix.dev/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py311hfe9595b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/openjpeg-2.5.4-h87e8dc5_0.conda - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://prefix.dev/conda-forge/osx-64/orc-2.2.2-h3073fbf_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pandas-3.0.0-py311hfbd1ee4_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pillow-12.1.0-py311h127dec8_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh8b19718_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda - conda: https://prefix.dev/conda-forge/osx-64/psutil-7.2.2-py311ha332486_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-23.0.0-py311h6eed73b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-core-23.0.0-py311hb7850dc_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pytest-codspeed-4.2.0-py311h62e9434_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/python-3.11.14-h74c2667_3_cpython.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.11-8_cp311.conda - conda: https://prefix.dev/conda-forge/osx-64/pyyaml-6.0.3-py311he13f9b5_0.conda - conda: https://prefix.dev/conda-forge/osx-64/re2-2025.11.05-h7df6414_0.conda - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/scikit-learn-1.8.0-np2py311heeb2b4f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/scipy-1.17.0-py311h553d447_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/tornado-6.5.4-py311ha2bb86f_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxau-1.0.12-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxdmcp-1.1.5-h8616949_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/zlib-ng-2.3.2-h8bce59a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/2c/29ab596b78a6e3601b499275a1048338804c0eda5a23324e154eb2463e5b/finch_mlir-0.0.2-cp311-cp311-macosx_11_0_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl osx-arm64: - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-auth-0.9.3-h1ddaa69_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-cal-0.9.13-h6ee9776_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-common-0.12.6-hc919400_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-compression-0.3.1-h16f91aa_9.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-event-stream-0.5.7-h9ae9c55_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-http-0.10.7-h5928ca5_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-io-0.23.3-hbe03c90_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-mqtt-0.13.3-haf5c5c8_11.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-s3-0.11.3-h8da9771_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h16f91aa_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-checksums-0.2.7-h16f91aa_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-crt-cpp-0.35.4-h74951b9_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-sdk-cpp-1.11.606-h4e1b0f7_10.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-core-cpp-1.16.1-h88fedcc_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-identity-cpp-1.13.2-h853621b_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.16.0-h6507aac_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-common-cpp-12.12.0-ha416c23_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.14.0-hcfc4f22_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/backports.zstd-1.3.0-py311hee243d0_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-python-1.2.0-py311hdc60ec4_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://prefix.dev/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cffi-2.0.0-py311hd10dc20_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/contourpy-1.3.3-py311h7d85929_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/coverage-7.13.2-py311hc290fe0_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cytoolz-1.1.0-py311h9408147_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda - conda: https://prefix.dev/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/juliaup-1.19.4-h748bcf4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lcms2-2.18-hdfa7624_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lerc-4.0.0-hd64df32_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libabseil-20250512.1-cxx17_hd41c47c_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-23.0.0-h4365f54_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-acero-23.0.0-h6de58dd_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-compute-23.0.0-h45df96a_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-dataset-23.0.0-h6de58dd_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-substrait-23.0.0-hb5627e6_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-arm64/libcurl-8.18.0-he38603e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-2.39.0-head0a95_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-storage-2.39.0-hfa3a374_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgrpc-1.73.1-h3063b79_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libjpeg-turbo-3.1.2-hc919400_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-1.21.0-he15edb5_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.21.0-hce30654_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libparquet-23.0.0-hcc2992d_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libpng-1.6.54-h132b30e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libprotobuf-6.31.1-h98f38fd_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libre2-11-2025.11.05-h91c62da_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libthrift-0.22.0-h14a376c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-16-2.15.1-h5ef1a60_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-2.15.1-h8d039ee_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py311h27de090_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-4.4.5-py311h3f5a5ee_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/markupsafe-3.0.3-py311ha9b3269_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/msgpack-python-1.1.2-py311h5a5e7c7_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.16.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://prefix.dev/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py311had9367a_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/orc-2.2.2-hac85105_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pandas-3.0.0-py311h4a068b9_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pillow-12.1.0-py311hd37aea2_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh8b19718_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/psutil-7.2.2-py311he363849_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-23.0.0-py311ha1ab1f8_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-core-23.0.0-py311h311f44d_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pytest-codspeed-4.2.0-py311h5bb9006_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.11.14-h18782d2_3_cpython.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.11-8_cp311.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyyaml-6.0.3-py311ha9b3269_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/re2-2025.11.05-h64b956e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py311hf1dd2ad_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scipy-1.17.0-py311he9931d0_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tornado-6.5.4-py311h9408147_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-hc919400_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-ng-2.3.2-hed4e4f5_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/e9/47681764301f53bcb3220ef1b77d328e09c8db33dbd048a7407d983d8618/finch_mlir-0.0.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl win-64: - conda: https://prefix.dev/conda-forge/win-64/_openmp_mutex-4.5-2_gnu.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-auth-0.9.3-h2970c50_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-cal-0.9.13-h46f3b43_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-common-0.12.6-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-compression-0.3.1-hcb3a2da_9.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-event-stream-0.5.7-ha388e84_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-http-0.10.7-hc678f4a_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-io-0.23.3-h0d5b9f9_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-mqtt-0.13.3-hfa314fa_11.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-s3-0.11.3-ha659bf3_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-sdkutils-0.2.4-hcb3a2da_4.conda - conda: https://prefix.dev/conda-forge/win-64/aws-checksums-0.2.7-hcb3a2da_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-crt-cpp-0.35.4-hca034e6_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-sdk-cpp-1.11.606-hac16450_10.conda - conda: https://prefix.dev/conda-forge/win-64/backports.zstd-1.3.0-py311h71c1bcc_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/brotli-python-1.2.0-py311hc5da9e4_1.conda - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://prefix.dev/conda-forge/win-64/c-ares-1.34.6-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda - conda: https://prefix.dev/conda-forge/win-64/cffi-2.0.0-py311h3485c13_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyha7b4d00_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/contourpy-1.3.3-py311h275cad7_4.conda - conda: https://prefix.dev/conda-forge/win-64/coverage-7.13.2-py311h3f79411_0.conda - conda: https://prefix.dev/conda-forge/win-64/cytoolz-1.1.0-py311h3485c13_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/juliaup-1.19.4-h77a83cd_0.conda - conda: https://prefix.dev/conda-forge/win-64/krb5-1.21.3-hdf4eb48_0.conda - conda: https://prefix.dev/conda-forge/win-64/lcms2-2.18-hf2c6c5f_0.conda - conda: https://prefix.dev/conda-forge/win-64/lerc-4.0.0-h6470a55_1.conda - conda: https://prefix.dev/conda-forge/win-64/libabseil-20250512.1-cxx17_habfad5f_0.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-23.0.0-hcf7e2ff_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-acero-23.0.0-h7d8d6a5_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-compute-23.0.0-h2db994a_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-dataset-23.0.0-h7d8d6a5_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-substrait-23.0.0-hf865cc0_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlicommon-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlidec-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlienc-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/libcurl-8.18.0-h43ecb02_0.conda - conda: https://prefix.dev/conda-forge/win-64/libdeflate-1.25-h51727cc_0.conda - conda: https://prefix.dev/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libfreetype-2.14.1-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/win-64/libfreetype6-2.14.1-hdbac1cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgcc-15.2.0-h8ee18e1_16.conda - conda: https://prefix.dev/conda-forge/win-64/libgomp-15.2.0-h8ee18e1_16.conda - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-2.39.0-h19ee442_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-storage-2.39.0-he04ea4c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgrpc-1.73.1-h317e13b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - conda: https://prefix.dev/conda-forge/win-64/libjpeg-turbo-3.1.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/libparquet-23.0.0-h7051d1f_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libpng-1.6.54-h7351971_0.conda - conda: https://prefix.dev/conda-forge/win-64/libprotobuf-6.31.1-hdcda5b4_4.conda - conda: https://prefix.dev/conda-forge/win-64/libre2-11-2025.11.05-h0eb2380_0.conda - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda - conda: https://prefix.dev/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda - conda: https://prefix.dev/conda-forge/win-64/libthrift-0.22.0-h23985f6_1.conda - conda: https://prefix.dev/conda-forge/win-64/libtiff-4.7.1-h8f73337_1.conda - conda: https://prefix.dev/conda-forge/win-64/libutf8proc-2.11.3-hb980946_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwebp-base-1.6.0-h4d5522a_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - conda: https://prefix.dev/conda-forge/win-64/libxcb-1.17.0-h0e4246c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py311h4f568be_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/lz4-4.4.5-py311ha034993_1.conda - conda: https://prefix.dev/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/markupsafe-3.0.3-py311h3f79411_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda - conda: https://prefix.dev/conda-forge/win-64/msgpack-python-1.1.2-py311h3fd045d_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.16.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py311h34437f8_0.conda - conda: https://prefix.dev/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - conda: https://prefix.dev/conda-forge/win-64/openjpeg-2.5.4-h24db6dd_0.conda - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://prefix.dev/conda-forge/win-64/orc-2.2.2-hbd3206f_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pandas-3.0.0-py311h0610301_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/pillow-12.1.0-py311h17b8079_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh8b19718_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/win-64/psutil-7.2.2-py311hf893f09_0.conda - conda: https://prefix.dev/conda-forge/win-64/pthread-stubs-0.4-h0e40799_1002.conda - conda: https://prefix.dev/conda-forge/win-64/pyarrow-23.0.0-py311h1ea47a8_0.conda - conda: https://prefix.dev/conda-forge/win-64/pyarrow-core-23.0.0-py311ha836b3b_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pytest-codspeed-4.2.0-py311hf893f09_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/python-3.11.14-h0159041_3_cpython.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.11-8_cp311.conda - conda: https://prefix.dev/conda-forge/win-64/pyyaml-6.0.3-py311h3f79411_0.conda - conda: https://prefix.dev/conda-forge/win-64/re2-2025.11.05-ha104f34_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/scikit-learn-1.8.0-np2py311hd01f973_1.conda - conda: https://prefix.dev/conda-forge/win-64/scipy-1.17.0-py311h9c22a71_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/win-64/snappy-1.2.2-h7fa0ca8_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tornado-6.5.4-py311h3485c13_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vs2015_runtime-14.44.35208-h38c0c73_34.conda - conda: https://prefix.dev/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda - conda: https://prefix.dev/conda-forge/win-64/xorg-libxau-1.0.12-hba3369d_1.conda - conda: https://prefix.dev/conda-forge/win-64/xorg-libxdmcp-1.1.5-hba3369d_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/zlib-ng-2.3.2-h0261ad2_1.conda - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/4f/3642d809f18857126239398d9fac520ace9e7b9e78958a75e88b021ae0cd/finch_mlir-0.0.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl mlir: channels: - url: https://prefix.dev/conda-forge/ indexes: - https://pypi.org/simple options: pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://prefix.dev/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/coverage-7.13.2-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py313hdd307be_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py313h5dce7c4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numpy-2.3.5-py313hf6604e3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pytest-codspeed-4.2.0-py313h54dd161_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/python-3.13.11-hc97d973_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/scipy-1.17.0-py313h4b8bb8b_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/59/ef/e62c0295ce64fdbaaef5496c15c59c24f2bf88a27c09c6d7f1933db5bdaf/finch_mlir-0.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl osx-64: - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-64/cffi-2.0.0-py313hf57695f_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/coverage-7.13.2-py313h7c6a591_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py313h590e1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py313hd3f9b42_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numpy-2.3.5-py313hf1665ba_1.conda - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pytest-codspeed-4.2.0-py313hcb05632_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/python-3.13.11-h17c18a5_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-64/pyyaml-6.0.3-py313h0f4d31d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/scipy-1.17.0-py313h2bd7e7a_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/63/53/1a8ef274d988c693e80b1225fdaa71a74443932c0761c22464cf4a1d69be/finch_mlir-0.0.2-cp313-cp313-macosx_11_0_x86_64.whl osx-arm64: - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cffi-2.0.0-py313h224173a_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/coverage-7.13.2-py313h65a2061_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py313he297ed2_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py313ha873477_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-2.3.5-py313h16eae64_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pytest-codspeed-4.2.0-py313h9734d34_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyyaml-6.0.3-py313h7d74516_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scipy-1.17.0-py313hc753a45_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/1e/c6/ce545d678439fd6a28fa020719d224c08ba50886849a10544402b118e6fb/finch_mlir-0.0.2-cp313-cp313-macosx_11_0_arm64.whl win-64: - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda - conda: https://prefix.dev/conda-forge/win-64/cffi-2.0.0-py313h5ea7bf4_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/coverage-7.13.2-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py313h5c49287_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py313h2da9318_0.conda - conda: https://prefix.dev/conda-forge/win-64/numpy-2.3.5-py313hce7ae62_1.conda - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pytest-codspeed-4.2.0-py313h5fd188c_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/python-3.13.11-h09917c8_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/win-64/pyyaml-6.0.3-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/scipy-1.17.0-py313he51e9a2_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/f8/c0/635d9c9e195b6ef6258aab8cae1edb1889e29f93e6a5ee85317f5e7117c6/finch_mlir-0.0.2-cp313-cp313-win_amd64.whl notebooks: channels: - url: https://prefix.dev/conda-forge/ indexes: - https://pypi.org/simple options: pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://prefix.dev/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/noarch/anyio-4.12.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py313h07c4f96_2.conda - conda: https://prefix.dev/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/async-lru-2.1.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-auth-0.9.3-hef928c7_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-cal-0.9.13-h2c9d079_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-common-0.12.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-compression-0.3.1-h8b1a151_9.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-event-stream-0.5.7-h28f887f_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-http-0.10.7-ha8fc4e3_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-io-0.23.3-hdaf4b65_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-mqtt-0.13.3-hc63082f_11.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-s3-0.11.3-h06ab39a_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-sdkutils-0.2.4-h8b1a151_4.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-checksums-0.2.7-h8b1a151_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-crt-cpp-0.35.4-h8824e59_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-sdk-cpp-1.11.606-h20b40b1_10.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-core-cpp-1.16.1-h3a458e0_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-identity-cpp-1.13.2-h3a5f585_1.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-blobs-cpp-12.16.0-h75daedc_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-common-cpp-12.12.0-h3d7a050_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.14.0-hd454692_0.conda - conda: https://prefix.dev/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/backports.zstd-1.3.0-py313h18e8e13_0.conda - conda: https://prefix.dev/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda - conda: https://prefix.dev/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/brotli-python-1.2.0-py313hf159716_1.conda - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://prefix.dev/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda - conda: https://prefix.dev/conda-forge/noarch/certifi-2026.1.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda - conda: https://prefix.dev/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/linux-64/contourpy-1.3.3-py313hc8edb43_4.conda - conda: https://prefix.dev/conda-forge/linux-64/coverage-7.13.3-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/noarch/cpython-3.13.11-py313hd8ed1ab_101.conda - conda: https://prefix.dev/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://prefix.dev/conda-forge/linux-64/cyrus-sasl-2.1.28-hd9c7081_0.conda - conda: https://prefix.dev/conda-forge/linux-64/cytoolz-1.1.0-py313h07c4f96_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/dbus-1.16.2-h24cb091_1.conda - conda: https://prefix.dev/conda-forge/linux-64/debugpy-1.8.20-py313h5d5ffb9_0.conda - conda: https://prefix.dev/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/double-conversion-3.4.0-hecca717_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda - conda: https://prefix.dev/conda-forge/linux-64/fontconfig-2.15.0-h7e30c49_1.conda - conda: https://prefix.dev/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - conda: https://prefix.dev/conda-forge/linux-64/fonttools-4.61.1-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/freetype-2.14.1-ha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://prefix.dev/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda - conda: https://prefix.dev/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://prefix.dev/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/harfbuzz-12.3.2-h6083320_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - conda: https://prefix.dev/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://prefix.dev/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipykernel-7.1.0-pyha191276_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython-9.9.0-pyh53cf698_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/json5-0.13.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/juliaup-1.19.4-hdab8a38_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_events-0.12.0-pyh29332c3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab-4.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/kiwisolver-1.4.9-py313hc8edb43_2.conda - conda: https://prefix.dev/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - conda: https://prefix.dev/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://prefix.dev/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-23.0.0-h2c50142_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-acero-23.0.0-h635bf11_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-compute-23.0.0-h8c2c5c3_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-dataset-23.0.0-h635bf11_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-substrait-23.0.0-h3f74fd7_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libclang-cpp21.1-21.1.8-default_h99862b1_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libclang13-21.1.8-default_h746c552_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/libcups-2.3.3-hb8b1518_5.conda - conda: https://prefix.dev/conda-forge/linux-64/libcurl-8.18.0-h4e3cde8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libdrm-2.4.125-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libev-4.33-hd590300_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libfreetype6-2.14.1-h73754d4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libglib-2.86.3-h6548e54_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-2.39.0-hdb79228_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-storage-2.39.0-hdbdcf42_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgrpc-1.73.1-h3288cfb_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libllvm21-21.1.8-hf7376ad_0.conda - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-1.21.0-hb9b0907_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-headers-1.21.0-ha770c72_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libparquet-23.0.0-h7376487_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libpng-1.6.54-h421ea60_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libpq-18.1-hb80d175_3.conda - conda: https://prefix.dev/conda-forge/linux-64/libprotobuf-6.31.1-h49aed37_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libre2-11-2025.11.05-h7b12aa8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libthrift-0.22.0-h454ac66_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libvulkan-loader-1.4.328.1-h5279c79_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libxkbcommon-1.13.1-hca5e8e5_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxml2-16-2.15.1-hca6bf5a_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libxml2-2.15.1-he237659_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py313hdd307be_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/lz4-4.4.5-py313h28739b2_1.conda - conda: https://prefix.dev/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/markupsafe-3.0.3-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/linux-64/matplotlib-3.10.8-py313h78bf25f_0.conda - conda: https://prefix.dev/conda-forge/linux-64/matplotlib-base-3.10.8-py313h683a580_0.conda - conda: https://prefix.dev/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/msgpack-python-1.1.2-py313h7037e92_1.conda - conda: https://prefix.dev/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbclient-0.6.8-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/nbmake-1.5.5-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://prefix.dev/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://prefix.dev/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py313h5dce7c4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numpy-2.3.5-py313hf6604e3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://prefix.dev/conda-forge/linux-64/openldap-2.6.10-he970967_0.conda - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/orc-2.2.2-h19cb568_0.conda - conda: https://prefix.dev/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pandas-3.0.0-py313hbfd7664_0.conda - conda: https://prefix.dev/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda - conda: https://prefix.dev/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/pillow-12.1.0-py313h80991f8_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda - conda: https://prefix.dev/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda - conda: https://prefix.dev/conda-forge/noarch/prometheus_client-0.24.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/linux-64/psutil-7.2.2-py313h54dd161_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://prefix.dev/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-23.0.0-py313h78bf25f_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-core-23.0.0-py313he109ebe_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pyside6-6.10.1-py313h85046ba_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pytest-codspeed-4.2.0-py313h54dd161_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/python-3.13.11-hc97d973_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-gil-3.13.11-h4df99d1_101.conda - conda: https://prefix.dev/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pyzmq-27.1.0-py312hfb55c3c_0.conda - conda: https://prefix.dev/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda - conda: https://prefix.dev/conda-forge/linux-64/qt6-main-6.10.1-hb82b983_4.conda - conda: https://prefix.dev/conda-forge/linux-64/re2-2025.11.05-h5301d42_0.conda - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://prefix.dev/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/rpds-py-0.30.0-py313h843e2db_0.conda - conda: https://prefix.dev/conda-forge/linux-64/s2n-1.6.2-he8a4886_1.conda - conda: https://prefix.dev/conda-forge/linux-64/scikit-learn-1.8.0-np2py313h16d504d_1.conda - conda: https://prefix.dev/conda-forge/linux-64/scipy-1.17.0-py313h4b8bb8b_1.conda - conda: https://prefix.dev/conda-forge/noarch/send2trash-2.1.0-pyha191276_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://prefix.dev/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/tornado-6.5.3-py313h07c4f96_0.conda - conda: https://prefix.dev/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/wayland-1.24.0-hd6090a7_1.conda - conda: https://prefix.dev/conda-forge/noarch/wcwidth-0.5.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://prefix.dev/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-cursor-0.1.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-image-0.4.0-hb711507_2.conda - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-keysyms-0.4.1-hb711507_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-renderutil-0.3.10-hb711507_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-wm-0.4.2-hb711507_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xkeyboard-config-2.46-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libx11-1.8.12-h4f16b4b_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxcomposite-0.4.6-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxcursor-1.2.3-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxdamage-1.1.6-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxxf86vm-1.1.7-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://prefix.dev/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/zlib-ng-2.3.2-hceb46e0_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/59/ef/e62c0295ce64fdbaaef5496c15c59c24f2bf88a27c09c6d7f1933db5bdaf/finch_mlir-0.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl osx-64: - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/anyio-4.12.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/argon2-cffi-bindings-25.1.0-py313hf050af9_2.conda - conda: https://prefix.dev/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/async-lru-2.1.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-auth-0.9.3-hdff831d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-cal-0.9.13-hea39f9f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-common-0.12.6-h8616949_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-compression-0.3.1-h901532c_9.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-event-stream-0.5.7-ha05da6a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-http-0.10.7-h924c446_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-io-0.23.3-hf559bb5_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-mqtt-0.13.3-ha72ff4e_11.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-s3-0.11.3-he30762a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-sdkutils-0.2.4-h901532c_4.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-checksums-0.2.7-h901532c_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-crt-cpp-0.35.4-h7484968_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-sdk-cpp-1.11.606-h386ebac_10.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-core-cpp-1.16.1-he2a98a9_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-identity-cpp-1.13.2-h0e8e1c8_1.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-blobs-cpp-12.16.0-ha4e89a6_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-common-cpp-12.12.0-h2a5eb39_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.14.0-h7f37a48_0.conda - conda: https://prefix.dev/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/backports.zstd-1.3.0-py313h591e92b_0.conda - conda: https://prefix.dev/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/brotli-1.2.0-hf139dec_1.conda - conda: https://prefix.dev/conda-forge/osx-64/brotli-bin-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/brotli-python-1.2.0-py313h8d69aa9_1.conda - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://prefix.dev/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/certifi-2026.1.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/cffi-2.0.0-py313hf57695f_1.conda - conda: https://prefix.dev/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/osx-64/contourpy-1.3.3-py313h98b818e_4.conda - conda: https://prefix.dev/conda-forge/osx-64/coverage-7.13.3-py313h7c6a591_0.conda - conda: https://prefix.dev/conda-forge/noarch/cpython-3.13.11-py313hd8ed1ab_101.conda - conda: https://prefix.dev/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://prefix.dev/conda-forge/osx-64/cytoolz-1.1.0-py313hf050af9_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/debugpy-1.8.20-py313h8b5a893_0.conda - conda: https://prefix.dev/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/fonttools-4.61.1-py313h0f4d31d_0.conda - conda: https://prefix.dev/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/freetype-2.14.1-h694c41f_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda - conda: https://prefix.dev/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda - conda: https://prefix.dev/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - conda: https://prefix.dev/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipykernel-7.1.0-pyh5552912_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython-9.9.0-pyh53cf698_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/json5-0.13.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/juliaup-1.19.4-hb64060d_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_events-0.12.0-pyh29332c3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab-4.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/kiwisolver-1.4.9-py313ha1c5e85_2.conda - conda: https://prefix.dev/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda - conda: https://prefix.dev/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/lcms2-2.18-h90db99b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/lerc-4.0.0-hcca01a6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libabseil-20250512.1-cxx17_hfc00f1c_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-23.0.0-h8071b21_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-acero-23.0.0-h9737151_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-compute-23.0.0-hc26cc94_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-dataset-23.0.0-h9737151_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-substrait-23.0.0-h7f2e36e_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-64/libcurl-8.18.0-h9348e2b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libev-4.33-h10d778d_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libfreetype-2.14.1-h694c41f_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libfreetype6-2.14.1-h6912278_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-2.39.0-hed66dea_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-storage-2.39.0-h8ac052b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgrpc-1.73.1-h451496d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libjpeg-turbo-3.1.2-h8616949_0.conda - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-1.21.0-h7d3f41d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-headers-1.21.0-h694c41f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libparquet-23.0.0-ha0d2768_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libpng-1.6.54-h07817ec_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libprotobuf-6.31.1-hcc66ac3_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libre2-11-2025.11.05-h554ac88_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libsodium-1.0.20-hfdf4475_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libthrift-0.22.0-h687e942_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libxml2-16-2.15.1-hd57b93d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libxml2-2.15.1-h745d5cb_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py313h590e1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-64/lz4-4.4.5-py313hab77a93_1.conda - conda: https://prefix.dev/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/markupsafe-3.0.3-py313h0f4d31d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/matplotlib-3.10.8-py313habf4b1d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/matplotlib-base-3.10.8-py313h4ad75b8_0.conda - conda: https://prefix.dev/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/msgpack-python-1.1.2-py313h5eff275_1.conda - conda: https://prefix.dev/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbclient-0.6.8-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/nbmake-1.5.5-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://prefix.dev/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda - conda: https://prefix.dev/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py313hd3f9b42_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numpy-2.3.5-py313hf1665ba_1.conda - conda: https://prefix.dev/conda-forge/osx-64/openjpeg-2.5.4-h87e8dc5_0.conda - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://prefix.dev/conda-forge/osx-64/orc-2.2.2-h3073fbf_0.conda - conda: https://prefix.dev/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pandas-3.0.0-py313h4810d26_0.conda - conda: https://prefix.dev/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/pillow-12.1.0-py313h16bb925_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda - conda: https://prefix.dev/conda-forge/noarch/prometheus_client-0.24.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/osx-64/psutil-7.2.2-py313h16366db_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://prefix.dev/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-23.0.0-py313habf4b1d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-core-23.0.0-py313h7c712a9_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyobjc-core-12.1-py313h07bcf3a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyobjc-framework-cocoa-12.1-py313hf669bc3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pytest-codspeed-4.2.0-py313hcb05632_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/python-3.13.11-h17c18a5_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-gil-3.13.11-h4df99d1_101.conda - conda: https://prefix.dev/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyyaml-6.0.3-py313h0f4d31d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyzmq-27.1.0-py312hb7d603e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/qhull-2020.2-h3c5361c_5.conda - conda: https://prefix.dev/conda-forge/osx-64/re2-2025.11.05-h7df6414_0.conda - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://prefix.dev/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/rpds-py-0.30.0-py313hcc225dc_0.conda - conda: https://prefix.dev/conda-forge/osx-64/scikit-learn-1.8.0-np2py313he2891f2_1.conda - conda: https://prefix.dev/conda-forge/osx-64/scipy-1.17.0-py313h2bd7e7a_1.conda - conda: https://prefix.dev/conda-forge/noarch/send2trash-2.1.0-pyh5552912_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda - conda: https://prefix.dev/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/tornado-6.5.4-py313h16c19ce_0.conda - conda: https://prefix.dev/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/wcwidth-0.5.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://prefix.dev/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxau-1.0.12-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxdmcp-1.1.5-h8616949_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://prefix.dev/conda-forge/osx-64/zeromq-4.3.5-h6c33b1e_9.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/zlib-ng-2.3.2-h8bce59a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/53/1a8ef274d988c693e80b1225fdaa71a74443932c0761c22464cf4a1d69be/finch_mlir-0.0.2-cp313-cp313-macosx_11_0_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl osx-arm64: - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/anyio-4.12.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py313h6535dbc_2.conda - conda: https://prefix.dev/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/async-lru-2.1.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-auth-0.9.3-h1ddaa69_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-cal-0.9.13-h6ee9776_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-common-0.12.6-hc919400_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-compression-0.3.1-h16f91aa_9.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-event-stream-0.5.7-h9ae9c55_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-http-0.10.7-h5928ca5_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-io-0.23.3-hbe03c90_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-mqtt-0.13.3-haf5c5c8_11.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-s3-0.11.3-h8da9771_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h16f91aa_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-checksums-0.2.7-h16f91aa_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-crt-cpp-0.35.4-h74951b9_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-sdk-cpp-1.11.606-h4e1b0f7_10.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-core-cpp-1.16.1-h88fedcc_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-identity-cpp-1.13.2-h853621b_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.16.0-h6507aac_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-common-cpp-12.12.0-ha416c23_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.14.0-hcfc4f22_0.conda - conda: https://prefix.dev/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/backports.zstd-1.3.0-py313h48bb75e_0.conda - conda: https://prefix.dev/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-python-1.2.0-py313hde1f3bb_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://prefix.dev/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/certifi-2026.1.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cffi-2.0.0-py313h224173a_1.conda - conda: https://prefix.dev/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/contourpy-1.3.3-py313h2af2deb_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/coverage-7.13.3-py313h65a2061_0.conda - conda: https://prefix.dev/conda-forge/noarch/cpython-3.13.11-py313hd8ed1ab_101.conda - conda: https://prefix.dev/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cytoolz-1.1.0-py313h6535dbc_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/debugpy-1.8.20-py313h1188861_0.conda - conda: https://prefix.dev/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/fonttools-4.61.1-py313h7d74516_0.conda - conda: https://prefix.dev/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/freetype-2.14.1-hce30654_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda - conda: https://prefix.dev/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda - conda: https://prefix.dev/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - conda: https://prefix.dev/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://prefix.dev/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipykernel-7.1.0-pyh5552912_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython-9.9.0-pyh53cf698_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/json5-0.13.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/juliaup-1.19.4-h748bcf4_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_events-0.12.0-pyh29332c3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab-4.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/kiwisolver-1.4.9-py313h7add70c_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - conda: https://prefix.dev/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lcms2-2.18-hdfa7624_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lerc-4.0.0-hd64df32_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libabseil-20250512.1-cxx17_hd41c47c_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-23.0.0-h4365f54_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-acero-23.0.0-h6de58dd_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-compute-23.0.0-h45df96a_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-dataset-23.0.0-h6de58dd_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-substrait-23.0.0-hb5627e6_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-arm64/libcurl-8.18.0-he38603e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-2.39.0-head0a95_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-storage-2.39.0-hfa3a374_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgrpc-1.73.1-h3063b79_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libjpeg-turbo-3.1.2-hc919400_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-1.21.0-he15edb5_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.21.0-hce30654_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libparquet-23.0.0-hcc2992d_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libpng-1.6.54-h132b30e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libprotobuf-6.31.1-h98f38fd_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libre2-11-2025.11.05-h91c62da_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsodium-1.0.20-h99b78c6_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libthrift-0.22.0-h14a376c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-16-2.15.1-h5ef1a60_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-2.15.1-h8d039ee_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py313he297ed2_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-4.4.5-py313hd065f0a_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/markupsafe-3.0.3-py313h7d74516_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/matplotlib-3.10.8-py313h39782a4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/matplotlib-base-3.10.8-py313h58042b9_0.conda - conda: https://prefix.dev/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/msgpack-python-1.1.2-py313ha61f8ec_1.conda - conda: https://prefix.dev/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbclient-0.6.8-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/nbmake-1.5.5-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://prefix.dev/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://prefix.dev/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py313ha873477_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-2.3.5-py313h16eae64_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/orc-2.2.2-hac85105_0.conda - conda: https://prefix.dev/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pandas-3.0.0-py313h6974306_0.conda - conda: https://prefix.dev/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pillow-12.1.0-py313h45e5a15_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda - conda: https://prefix.dev/conda-forge/noarch/prometheus_client-0.24.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/psutil-7.2.2-py313h6688731_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda - conda: https://prefix.dev/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-23.0.0-py313h39782a4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-core-23.0.0-py313hfb690af_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyobjc-core-12.1-py313h40b429f_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py313hcc5defa_0.conda - conda: https://prefix.dev/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pytest-codspeed-4.2.0-py313h9734d34_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-gil-3.13.11-h4df99d1_101.conda - conda: https://prefix.dev/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyyaml-6.0.3-py313h7d74516_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyzmq-27.1.0-py312hd65ceae_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/qhull-2020.2-h420ef59_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/re2-2025.11.05-h64b956e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://prefix.dev/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/rpds-py-0.30.0-py313h2c089d5_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py313h3b23316_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scipy-1.17.0-py313hc753a45_1.conda - conda: https://prefix.dev/conda-forge/noarch/send2trash-2.1.0-pyh5552912_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda - conda: https://prefix.dev/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tornado-6.5.4-py313h6535dbc_0.conda - conda: https://prefix.dev/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/wcwidth-0.5.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://prefix.dev/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-hc919400_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zeromq-4.3.5-h888dc83_9.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-ng-2.3.2-hed4e4f5_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/c6/ce545d678439fd6a28fa020719d224c08ba50886849a10544402b118e6fb/finch_mlir-0.0.2-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl win-64: - conda: https://prefix.dev/conda-forge/win-64/_openmp_mutex-4.5-2_gnu.conda - conda: https://prefix.dev/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/anyio-4.12.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py313h5ea7bf4_2.conda - conda: https://prefix.dev/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/async-lru-2.1.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-auth-0.9.3-h2970c50_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-cal-0.9.13-h46f3b43_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-common-0.12.6-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-compression-0.3.1-hcb3a2da_9.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-event-stream-0.5.7-ha388e84_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-http-0.10.7-hc678f4a_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-io-0.23.3-h0d5b9f9_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-mqtt-0.13.3-hfa314fa_11.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-s3-0.11.3-ha659bf3_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-sdkutils-0.2.4-hcb3a2da_4.conda - conda: https://prefix.dev/conda-forge/win-64/aws-checksums-0.2.7-hcb3a2da_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-crt-cpp-0.35.4-hca034e6_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-sdk-cpp-1.11.606-hac16450_10.conda - conda: https://prefix.dev/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/backports.zstd-1.3.0-py313h2a31948_0.conda - conda: https://prefix.dev/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/brotli-1.2.0-h2d644bc_1.conda - conda: https://prefix.dev/conda-forge/win-64/brotli-bin-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/brotli-python-1.2.0-py313h3ebfc14_1.conda - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://prefix.dev/conda-forge/win-64/c-ares-1.34.6-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda - conda: https://prefix.dev/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/cairo-1.18.4-h477c42c_1.conda - conda: https://prefix.dev/conda-forge/noarch/certifi-2026.1.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/cffi-2.0.0-py313h5ea7bf4_1.conda - conda: https://prefix.dev/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyha7b4d00_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/win-64/contourpy-1.3.3-py313h1a38498_4.conda - conda: https://prefix.dev/conda-forge/win-64/coverage-7.13.3-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/noarch/cpython-3.13.11-py313hd8ed1ab_101.conda - conda: https://prefix.dev/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://prefix.dev/conda-forge/win-64/cytoolz-1.1.0-py313h5ea7bf4_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/debugpy-1.8.20-py313h927ade5_0.conda - conda: https://prefix.dev/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/double-conversion-3.4.0-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda - conda: https://prefix.dev/conda-forge/win-64/fontconfig-2.15.0-h765892d_1.conda - conda: https://prefix.dev/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - conda: https://prefix.dev/conda-forge/win-64/fonttools-4.61.1-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/freetype-2.14.1-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/graphite2-1.3.14-hac47afa_2.conda - conda: https://prefix.dev/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/harfbuzz-12.3.2-h5a1b470_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - conda: https://prefix.dev/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda - conda: https://prefix.dev/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipykernel-7.1.0-pyh6dadd2b_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython-9.9.0-pyhe2676ad_0.conda - conda: https://prefix.dev/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/json5-0.13.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/juliaup-1.19.4-h77a83cd_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_events-0.12.0-pyh29332c3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab-4.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/kiwisolver-1.4.9-py313h1a38498_2.conda - conda: https://prefix.dev/conda-forge/win-64/krb5-1.21.3-hdf4eb48_0.conda - conda: https://prefix.dev/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/lcms2-2.18-hf2c6c5f_0.conda - conda: https://prefix.dev/conda-forge/win-64/lerc-4.0.0-h6470a55_1.conda - conda: https://prefix.dev/conda-forge/win-64/libabseil-20250512.1-cxx17_habfad5f_0.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-23.0.0-hcf7e2ff_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-acero-23.0.0-h7d8d6a5_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-compute-23.0.0-h2db994a_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-dataset-23.0.0-h7d8d6a5_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-substrait-23.0.0-hf865cc0_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlicommon-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlidec-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlienc-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libclang13-21.1.8-default_ha2db4b5_2.conda - conda: https://prefix.dev/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/libcurl-8.18.0-h43ecb02_0.conda - conda: https://prefix.dev/conda-forge/win-64/libdeflate-1.25-h51727cc_0.conda - conda: https://prefix.dev/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libfreetype-2.14.1-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/win-64/libfreetype6-2.14.1-hdbac1cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgcc-15.2.0-h8ee18e1_16.conda - conda: https://prefix.dev/conda-forge/win-64/libglib-2.86.3-h0c9aed9_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgomp-15.2.0-h8ee18e1_16.conda - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-2.39.0-h19ee442_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-storage-2.39.0-he04ea4c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgrpc-1.73.1-h317e13b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - conda: https://prefix.dev/conda-forge/win-64/libintl-0.22.5-h5728263_3.conda - conda: https://prefix.dev/conda-forge/win-64/libjpeg-turbo-3.1.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libparquet-23.0.0-h7051d1f_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libpng-1.6.54-h7351971_0.conda - conda: https://prefix.dev/conda-forge/win-64/libprotobuf-6.31.1-hdcda5b4_4.conda - conda: https://prefix.dev/conda-forge/win-64/libre2-11-2025.11.05-h0eb2380_0.conda - conda: https://prefix.dev/conda-forge/win-64/libsodium-1.0.20-hc70643c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda - conda: https://prefix.dev/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda - conda: https://prefix.dev/conda-forge/win-64/libthrift-0.22.0-h23985f6_1.conda - conda: https://prefix.dev/conda-forge/win-64/libtiff-4.7.1-h8f73337_1.conda - conda: https://prefix.dev/conda-forge/win-64/libutf8proc-2.11.3-hb980946_0.conda - conda: https://prefix.dev/conda-forge/win-64/libvulkan-loader-1.4.328.1-h477610d_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwebp-base-1.6.0-h4d5522a_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - conda: https://prefix.dev/conda-forge/win-64/libxcb-1.17.0-h0e4246c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxslt-1.1.43-h0fbe4c1_1.conda - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py313h5c49287_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/lz4-4.4.5-py313h4bbca4b_1.conda - conda: https://prefix.dev/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/markupsafe-3.0.3-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/win-64/matplotlib-3.10.8-py313hfa70ccb_0.conda - conda: https://prefix.dev/conda-forge/win-64/matplotlib-base-3.10.8-py313he1ded55_0.conda - conda: https://prefix.dev/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda - conda: https://prefix.dev/conda-forge/win-64/msgpack-python-1.1.2-py313hf069bd2_1.conda - conda: https://prefix.dev/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbclient-0.6.8-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/nbmake-1.5.5-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py313h2da9318_0.conda - conda: https://prefix.dev/conda-forge/win-64/numpy-2.3.5-py313hce7ae62_1.conda - conda: https://prefix.dev/conda-forge/win-64/openjpeg-2.5.4-h24db6dd_0.conda - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://prefix.dev/conda-forge/win-64/orc-2.2.2-hbd3206f_0.conda - conda: https://prefix.dev/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pandas-3.0.0-py313h26f5e95_0.conda - conda: https://prefix.dev/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/pcre2-10.47-hd2b5f0e_0.conda - conda: https://prefix.dev/conda-forge/win-64/pillow-12.1.0-py313h38f99e1_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/win-64/pixman-0.46.4-h5112557_1.conda - conda: https://prefix.dev/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/prometheus_client-0.24.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/win-64/psutil-7.2.2-py313h5fd188c_0.conda - conda: https://prefix.dev/conda-forge/win-64/pthread-stubs-0.4-h0e40799_1002.conda - conda: https://prefix.dev/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/pyarrow-23.0.0-py313hfa70ccb_0.conda - conda: https://prefix.dev/conda-forge/win-64/pyarrow-core-23.0.0-py313h5921983_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pyside6-6.10.1-py313h475ba69_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pytest-codspeed-4.2.0-py313h5fd188c_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/python-3.13.11-h09917c8_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-gil-3.13.11-h4df99d1_101.conda - conda: https://prefix.dev/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/pywin32-311-py313h40c08fc_1.conda - conda: https://prefix.dev/conda-forge/win-64/pywinpty-2.0.15-py313h5813708_1.conda - conda: https://prefix.dev/conda-forge/win-64/pyyaml-6.0.3-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/win-64/pyzmq-27.1.0-py312hbb5da91_0.conda - conda: https://prefix.dev/conda-forge/win-64/qhull-2020.2-hc790b64_5.conda - conda: https://prefix.dev/conda-forge/win-64/qt6-main-6.10.1-h68b6638_4.conda - conda: https://prefix.dev/conda-forge/win-64/re2-2025.11.05-ha104f34_0.conda - conda: https://prefix.dev/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/rpds-py-0.30.0-py313hfbe8231_0.conda - conda: https://prefix.dev/conda-forge/win-64/scikit-learn-1.8.0-np2py313h4ce4a18_1.conda - conda: https://prefix.dev/conda-forge/win-64/scipy-1.17.0-py313he51e9a2_1.conda - conda: https://prefix.dev/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/win-64/snappy-1.2.2-h7fa0ca8_1.conda - conda: https://prefix.dev/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tornado-6.5.4-py313h5ea7bf4_0.conda - conda: https://prefix.dev/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vs2015_runtime-14.44.35208-h38c0c73_34.conda - conda: https://prefix.dev/conda-forge/noarch/wcwidth-0.5.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://prefix.dev/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda - conda: https://prefix.dev/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/xorg-libxau-1.0.12-hba3369d_1.conda - conda: https://prefix.dev/conda-forge/win-64/xorg-libxdmcp-1.1.5-hba3369d_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://prefix.dev/conda-forge/win-64/zeromq-4.3.5-h5bddc39_9.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/zlib-ng-2.3.2-h0261ad2_1.conda - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f8/c0/635d9c9e195b6ef6258aab8cae1edb1889e29f93e6a5ee85317f5e7117c6/finch_mlir-0.0.2-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl test: channels: - url: https://prefix.dev/conda-forge/ options: pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://prefix.dev/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-auth-0.9.3-hef928c7_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-cal-0.9.13-h2c9d079_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-common-0.12.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-compression-0.3.1-h8b1a151_9.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-event-stream-0.5.7-h28f887f_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-http-0.10.7-ha8fc4e3_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-io-0.23.3-hdaf4b65_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-mqtt-0.13.3-hc63082f_11.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-s3-0.11.3-h06ab39a_1.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-c-sdkutils-0.2.4-h8b1a151_4.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-checksums-0.2.7-h8b1a151_5.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-crt-cpp-0.35.4-h8824e59_0.conda - conda: https://prefix.dev/conda-forge/linux-64/aws-sdk-cpp-1.11.606-h20b40b1_10.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-core-cpp-1.16.1-h3a458e0_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-identity-cpp-1.13.2-h3a5f585_1.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-blobs-cpp-12.16.0-h75daedc_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-common-cpp-12.12.0-h3d7a050_0.conda - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.14.0-hd454692_0.conda - conda: https://prefix.dev/conda-forge/linux-64/backports.zstd-1.3.0-py313h18e8e13_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/brotli-python-1.2.0-py313hf159716_1.conda - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://prefix.dev/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/contourpy-1.3.3-py313hc8edb43_4.conda - conda: https://prefix.dev/conda-forge/linux-64/coverage-7.13.2-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/linux-64/cytoolz-1.1.0-py313h07c4f96_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://prefix.dev/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - conda: https://prefix.dev/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://prefix.dev/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-23.0.0-h2c50142_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-acero-23.0.0-h635bf11_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-compute-23.0.0-h8c2c5c3_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-dataset-23.0.0-h635bf11_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libarrow-substrait-23.0.0-h3f74fd7_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/libcurl-8.18.0-h4e3cde8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libev-4.33-hd590300_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libfreetype6-2.14.1-h73754d4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-2.39.0-hdb79228_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-storage-2.39.0-hdbdcf42_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgrpc-1.73.1-h3288cfb_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://prefix.dev/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-1.21.0-hb9b0907_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-headers-1.21.0-ha770c72_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libparquet-23.0.0-h7376487_1_cpu.conda - conda: https://prefix.dev/conda-forge/linux-64/libpng-1.6.54-h421ea60_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libprotobuf-6.31.1-h49aed37_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libre2-11-2025.11.05-h7b12aa8_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libthrift-0.22.0-h454ac66_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libxml2-16-2.15.1-hca6bf5a_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libxml2-2.15.1-he237659_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py313hdd307be_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/lz4-4.4.5-py313h28739b2_1.conda - conda: https://prefix.dev/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/markupsafe-3.0.3-pyh7db6752_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/msgpack-python-1.1.2-py313h7037e92_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://prefix.dev/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py313h5dce7c4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numpy-2.3.5-py313hf6604e3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/orc-2.2.2-h19cb568_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pandas-3.0.0-py313hbfd7664_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pillow-12.1.0-py313h80991f8_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda - conda: https://prefix.dev/conda-forge/linux-64/psutil-7.2.2-py313h54dd161_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-23.0.0-py313h78bf25f_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-core-23.0.0-py313he109ebe_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pytest-codspeed-4.2.0-py313h54dd161_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/python-3.13.11-hc97d973_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pyyaml-6.0.3-pyh7db6752_0.conda - conda: https://prefix.dev/conda-forge/linux-64/re2-2025.11.05-h5301d42_0.conda - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/s2n-1.6.2-he8a4886_1.conda - conda: https://prefix.dev/conda-forge/linux-64/scikit-learn-1.8.0-np2py313h16d504d_1.conda - conda: https://prefix.dev/conda-forge/linux-64/scipy-1.17.0-py313h4b8bb8b_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/tornado-6.5.3-py313h07c4f96_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/zlib-ng-2.3.2-hceb46e0_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: . osx-64: - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-auth-0.9.3-hdff831d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-cal-0.9.13-hea39f9f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-common-0.12.6-h8616949_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-compression-0.3.1-h901532c_9.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-event-stream-0.5.7-ha05da6a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-http-0.10.7-h924c446_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-io-0.23.3-hf559bb5_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-mqtt-0.13.3-ha72ff4e_11.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-s3-0.11.3-he30762a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-c-sdkutils-0.2.4-h901532c_4.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-checksums-0.2.7-h901532c_5.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-crt-cpp-0.35.4-h7484968_0.conda - conda: https://prefix.dev/conda-forge/osx-64/aws-sdk-cpp-1.11.606-h386ebac_10.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-core-cpp-1.16.1-he2a98a9_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-identity-cpp-1.13.2-h0e8e1c8_1.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-blobs-cpp-12.16.0-ha4e89a6_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-common-cpp-12.12.0-h2a5eb39_0.conda - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.14.0-h7f37a48_0.conda - conda: https://prefix.dev/conda-forge/osx-64/backports.zstd-1.3.0-py313h591e92b_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/brotli-python-1.2.0-py313h8d69aa9_1.conda - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://prefix.dev/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-64/cffi-2.0.0-py313hf57695f_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/contourpy-1.3.3-py313h98b818e_4.conda - conda: https://prefix.dev/conda-forge/osx-64/coverage-7.13.2-py313h7c6a591_0.conda - conda: https://prefix.dev/conda-forge/osx-64/cytoolz-1.1.0-py313hf050af9_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda - conda: https://prefix.dev/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda - conda: https://prefix.dev/conda-forge/osx-64/lcms2-2.18-h90db99b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/lerc-4.0.0-hcca01a6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libabseil-20250512.1-cxx17_hfc00f1c_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-23.0.0-h8071b21_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-acero-23.0.0-h9737151_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-compute-23.0.0-hc26cc94_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-dataset-23.0.0-h9737151_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libarrow-substrait-23.0.0-h7f2e36e_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-64/libcurl-8.18.0-h9348e2b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libev-4.33-h10d778d_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libfreetype-2.14.1-h694c41f_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libfreetype6-2.14.1-h6912278_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-2.39.0-hed66dea_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-storage-2.39.0-h8ac052b_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgrpc-1.73.1-h451496d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libjpeg-turbo-3.1.2-h8616949_0.conda - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-1.21.0-h7d3f41d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-headers-1.21.0-h694c41f_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libparquet-23.0.0-ha0d2768_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-64/libpng-1.6.54-h07817ec_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libprotobuf-6.31.1-hcc66ac3_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libre2-11-2025.11.05-h554ac88_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libthrift-0.22.0-h687e942_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libxml2-16-2.15.1-hd57b93d_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libxml2-2.15.1-h745d5cb_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py313h590e1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-64/lz4-4.4.5-py313hab77a93_1.conda - conda: https://prefix.dev/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/markupsafe-3.0.3-pyh7db6752_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/msgpack-python-1.1.2-py313h5eff275_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://prefix.dev/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py313hd3f9b42_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numpy-2.3.5-py313hf1665ba_1.conda - conda: https://prefix.dev/conda-forge/osx-64/openjpeg-2.5.4-h87e8dc5_0.conda - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://prefix.dev/conda-forge/osx-64/orc-2.2.2-h3073fbf_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pandas-3.0.0-py313h4810d26_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pillow-12.1.0-py313h16bb925_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda - conda: https://prefix.dev/conda-forge/osx-64/psutil-7.2.2-py313h16366db_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-23.0.0-py313habf4b1d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-core-23.0.0-py313h7c712a9_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pytest-codspeed-4.2.0-py313hcb05632_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/python-3.13.11-h17c18a5_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pyyaml-6.0.3-pyh7db6752_0.conda - conda: https://prefix.dev/conda-forge/osx-64/re2-2025.11.05-h7df6414_0.conda - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/scikit-learn-1.8.0-np2py313he2891f2_1.conda - conda: https://prefix.dev/conda-forge/osx-64/scipy-1.17.0-py313h2bd7e7a_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/tornado-6.5.4-py313h16c19ce_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxau-1.0.12-h8616949_1.conda - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxdmcp-1.1.5-h8616949_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/zlib-ng-2.3.2-h8bce59a_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - conda: . osx-arm64: - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-auth-0.9.3-h1ddaa69_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-cal-0.9.13-h6ee9776_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-common-0.12.6-hc919400_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-compression-0.3.1-h16f91aa_9.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-event-stream-0.5.7-h9ae9c55_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-http-0.10.7-h5928ca5_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-io-0.23.3-hbe03c90_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-mqtt-0.13.3-haf5c5c8_11.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-s3-0.11.3-h8da9771_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h16f91aa_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-checksums-0.2.7-h16f91aa_5.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-crt-cpp-0.35.4-h74951b9_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/aws-sdk-cpp-1.11.606-h4e1b0f7_10.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-core-cpp-1.16.1-h88fedcc_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-identity-cpp-1.13.2-h853621b_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.16.0-h6507aac_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-common-cpp-12.12.0-ha416c23_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.14.0-hcfc4f22_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/backports.zstd-1.3.0-py313h48bb75e_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-python-1.2.0-py313hde1f3bb_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://prefix.dev/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cffi-2.0.0-py313h224173a_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/contourpy-1.3.3-py313h2af2deb_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/coverage-7.13.2-py313h65a2061_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cytoolz-1.1.0-py313h6535dbc_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda - conda: https://prefix.dev/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lcms2-2.18-hdfa7624_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lerc-4.0.0-hd64df32_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libabseil-20250512.1-cxx17_hd41c47c_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-23.0.0-h4365f54_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-acero-23.0.0-h6de58dd_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-compute-23.0.0-h45df96a_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-dataset-23.0.0-h6de58dd_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-substrait-23.0.0-hb5627e6_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-arm64/libcurl-8.18.0-he38603e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-2.39.0-head0a95_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-storage-2.39.0-hfa3a374_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgrpc-1.73.1-h3063b79_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libjpeg-turbo-3.1.2-hc919400_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-1.21.0-he15edb5_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.21.0-hce30654_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libparquet-23.0.0-hcc2992d_1_cpu.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libpng-1.6.54-h132b30e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libprotobuf-6.31.1-h98f38fd_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libre2-11-2025.11.05-h91c62da_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libthrift-0.22.0-h14a376c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-16-2.15.1-h5ef1a60_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-2.15.1-h8d039ee_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py313he297ed2_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-4.4.5-py313hd065f0a_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/markupsafe-3.0.3-pyh7db6752_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/msgpack-python-1.1.2-py313ha61f8ec_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://prefix.dev/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py313ha873477_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-2.3.5-py313h16eae64_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/orc-2.2.2-hac85105_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pandas-3.0.0-py313h6974306_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pillow-12.1.0-py313h45e5a15_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/psutil-7.2.2-py313h6688731_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-23.0.0-py313h39782a4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-core-23.0.0-py313hfb690af_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pytest-codspeed-4.2.0-py313h9734d34_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pyyaml-6.0.3-pyh7db6752_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/re2-2025.11.05-h64b956e_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py313h3b23316_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scipy-1.17.0-py313hc753a45_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tornado-6.5.4-py313h6535dbc_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-hc919400_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-ng-2.3.2-hed4e4f5_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - conda: . win-64: - conda: https://prefix.dev/conda-forge/win-64/_openmp_mutex-4.5-2_gnu.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-auth-0.9.3-h2970c50_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-cal-0.9.13-h46f3b43_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-common-0.12.6-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-compression-0.3.1-hcb3a2da_9.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-event-stream-0.5.7-ha388e84_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-http-0.10.7-hc678f4a_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-io-0.23.3-h0d5b9f9_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-mqtt-0.13.3-hfa314fa_11.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-s3-0.11.3-ha659bf3_1.conda - conda: https://prefix.dev/conda-forge/win-64/aws-c-sdkutils-0.2.4-hcb3a2da_4.conda - conda: https://prefix.dev/conda-forge/win-64/aws-checksums-0.2.7-hcb3a2da_5.conda - conda: https://prefix.dev/conda-forge/win-64/aws-crt-cpp-0.35.4-hca034e6_0.conda - conda: https://prefix.dev/conda-forge/win-64/aws-sdk-cpp-1.11.606-hac16450_10.conda - conda: https://prefix.dev/conda-forge/win-64/backports.zstd-1.3.0-py313h2a31948_0.conda - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/brotli-python-1.2.0-py313h3ebfc14_1.conda - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://prefix.dev/conda-forge/win-64/c-ares-1.34.6-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda - conda: https://prefix.dev/conda-forge/win-64/cffi-2.0.0-py313h5ea7bf4_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyha7b4d00_1.conda - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/contourpy-1.3.3-py313h1a38498_4.conda - conda: https://prefix.dev/conda-forge/win-64/coverage-7.13.2-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/win-64/cytoolz-1.1.0-py313h5ea7bf4_1.conda - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/krb5-1.21.3-hdf4eb48_0.conda - conda: https://prefix.dev/conda-forge/win-64/lcms2-2.18-hf2c6c5f_0.conda - conda: https://prefix.dev/conda-forge/win-64/lerc-4.0.0-h6470a55_1.conda - conda: https://prefix.dev/conda-forge/win-64/libabseil-20250512.1-cxx17_habfad5f_0.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-23.0.0-hcf7e2ff_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-acero-23.0.0-h7d8d6a5_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-compute-23.0.0-h2db994a_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-dataset-23.0.0-h7d8d6a5_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libarrow-substrait-23.0.0-hf865cc0_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlicommon-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlidec-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libbrotlienc-1.2.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/libcurl-8.18.0-h43ecb02_0.conda - conda: https://prefix.dev/conda-forge/win-64/libdeflate-1.25-h51727cc_0.conda - conda: https://prefix.dev/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libfreetype-2.14.1-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/win-64/libfreetype6-2.14.1-hdbac1cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgcc-15.2.0-h8ee18e1_16.conda - conda: https://prefix.dev/conda-forge/win-64/libgomp-15.2.0-h8ee18e1_16.conda - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-2.39.0-h19ee442_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-storage-2.39.0-he04ea4c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libgrpc-1.73.1-h317e13b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - conda: https://prefix.dev/conda-forge/win-64/libjpeg-turbo-3.1.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libparquet-23.0.0-h7051d1f_1_cpu.conda - conda: https://prefix.dev/conda-forge/win-64/libpng-1.6.54-h7351971_0.conda - conda: https://prefix.dev/conda-forge/win-64/libprotobuf-6.31.1-hdcda5b4_4.conda - conda: https://prefix.dev/conda-forge/win-64/libre2-11-2025.11.05-h0eb2380_0.conda - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda - conda: https://prefix.dev/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda - conda: https://prefix.dev/conda-forge/win-64/libthrift-0.22.0-h23985f6_1.conda - conda: https://prefix.dev/conda-forge/win-64/libtiff-4.7.1-h8f73337_1.conda - conda: https://prefix.dev/conda-forge/win-64/libutf8proc-2.11.3-hb980946_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwebp-base-1.6.0-h4d5522a_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - conda: https://prefix.dev/conda-forge/win-64/libxcb-1.17.0-h0e4246c_0.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py313h5c49287_0.conda - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/win-64/lz4-4.4.5-py313h4bbca4b_1.conda - conda: https://prefix.dev/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/markupsafe-3.0.3-pyh7db6752_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda - conda: https://prefix.dev/conda-forge/win-64/msgpack-python-1.1.2-py313hf069bd2_1.conda - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py313h2da9318_0.conda - conda: https://prefix.dev/conda-forge/win-64/numpy-2.3.5-py313hce7ae62_1.conda - conda: https://prefix.dev/conda-forge/win-64/openjpeg-2.5.4-h24db6dd_0.conda - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://prefix.dev/conda-forge/win-64/orc-2.2.2-hbd3206f_0.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pandas-3.0.0-py313h26f5e95_0.conda - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/pillow-12.1.0-py313h38f99e1_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/win-64/psutil-7.2.2-py313h5fd188c_0.conda - conda: https://prefix.dev/conda-forge/win-64/pthread-stubs-0.4-h0e40799_1002.conda - conda: https://prefix.dev/conda-forge/win-64/pyarrow-23.0.0-py313hfa70ccb_0.conda - conda: https://prefix.dev/conda-forge/win-64/pyarrow-core-23.0.0-py313h5921983_0_cpu.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pytest-codspeed-4.2.0-py313h5fd188c_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/python-3.13.11-h09917c8_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://prefix.dev/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/pyyaml-6.0.3-pyh7db6752_0.conda - conda: https://prefix.dev/conda-forge/win-64/re2-2025.11.05-ha104f34_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/scikit-learn-1.8.0-np2py313h4ce4a18_1.conda - conda: https://prefix.dev/conda-forge/win-64/scipy-1.17.0-py313he51e9a2_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/win-64/snappy-1.2.2-h7fa0ca8_1.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tornado-6.5.4-py313h5ea7bf4_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vs2015_runtime-14.44.35208-h38c0c73_34.conda - conda: https://prefix.dev/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda - conda: https://prefix.dev/conda-forge/win-64/xorg-libxau-1.0.12-hba3369d_1.conda - conda: https://prefix.dev/conda-forge/win-64/xorg-libxdmcp-1.1.5-hba3369d_1.conda - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/zlib-ng-2.3.2-h0261ad2_1.conda - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - conda: . xp-tests: channels: - url: https://prefix.dev/conda-forge/ indexes: - https://pypi.org/simple options: pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://prefix.dev/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/coverage-7.13.3-py313h3dea7bd_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hypothesis-6.151.5-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/juliaup-1.19.4-hdab8a38_0.conda - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py313hdd307be_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://prefix.dev/conda-forge/linux-64/ndindex-1.10.1-py313h7033f15_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py313h5dce7c4_0.conda - conda: https://prefix.dev/conda-forge/linux-64/numpy-2.3.5-py313hf6604e3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-26.0-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/pytest-codspeed-4.2.0-py313h54dd161_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-json-report-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/pytest-metadata-3.1.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/linux-64/python-3.13.11-hc97d973_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/linux-64/scipy-1.17.0-py313h4b8bb8b_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl osx-64: - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-64/cffi-2.0.0-py313hf57695f_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/coverage-7.13.3-py313h7c6a591_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hypothesis-6.151.5-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/juliaup-1.19.4-hb64060d_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h4fb565c_2.conda - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py313h590e1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://prefix.dev/conda-forge/osx-64/ndindex-1.10.1-py313hc4a83b5_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py313hd3f9b42_0.conda - conda: https://prefix.dev/conda-forge/osx-64/numpy-2.3.5-py313hf1665ba_1.conda - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-26.0-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/pytest-codspeed-4.2.0-py313hcb05632_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-json-report-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/pytest-metadata-3.1.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-64/python-3.13.11-h17c18a5_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-64/scipy-1.17.0-py313h2bd7e7a_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl osx-arm64: - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/cffi-2.0.0-py313h224173a_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/coverage-7.13.3-py313h65a2061_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hypothesis-6.151.5-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/juliaup-1.19.4-h748bcf4_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-h55c6f16_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py313he297ed2_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://prefix.dev/conda-forge/noarch/ndindex-1.8-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py313ha873477_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-2.3.5-py313h16eae64_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-26.0-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/pytest-codspeed-4.2.0-py313h9734d34_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-json-report-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/pytest-metadata-3.1.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/osx-arm64/scipy-1.17.0-py313hc753a45_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl win-64: - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda - conda: https://prefix.dev/conda-forge/win-64/cffi-2.0.0-py313h5ea7bf4_1.conda - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyha7b4d00_1.conda - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/coverage-7.13.3-py313hd650c13_0.conda - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/hypothesis-6.151.5-pyha770c72_0.conda - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/juliaup-1.19.4-h77a83cd_0.conda - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda - conda: https://prefix.dev/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py313h5c49287_0.conda - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda - conda: https://prefix.dev/conda-forge/win-64/ndindex-1.10.1-py313hfe59770_0.conda - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py313h2da9318_0.conda - conda: https://prefix.dev/conda-forge/win-64/numpy-2.3.5-py313hce7ae62_1.conda - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/pip-26.0-pyh145f28c_0.conda - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/pytest-codspeed-4.2.0-py313h5fd188c_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-json-report-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://prefix.dev/conda-forge/noarch/pytest-metadata-3.1.1-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/win-64/python-3.13.11-h09917c8_101_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.2-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/win-64/scipy-1.17.0-py313he51e9a2_1.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - conda: . - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl packages: - conda: https://prefix.dev/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 md5: d7c89558ba9fa0495403155b64376d81 license: None purls: [] size: 2562 timestamp: 1578324546067 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 build_number: 16 sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 md5: 73aaf86a425cc6e73fcf236a5a46396d depends: - _libgcc_mutex 0.1 conda_forge - libgomp >=7.5.0 constrains: - openmp_impl 9999 license: BSD-3-Clause license_family: BSD purls: [] size: 23621 timestamp: 1650670423406 - conda: https://prefix.dev/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda build_number: 7 sha256: c0cddb66070dd6355311f7667ce2acccf70d1013edaa6e97f22859502fefdb22 md5: 887b70e1d607fba7957aa02f9ee0d939 depends: - llvm-openmp >=9.0.1 license: BSD-3-Clause license_family: BSD purls: [] size: 8244 timestamp: 1764092331208 - conda: https://prefix.dev/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda build_number: 7 sha256: 30006902a9274de8abdad5a9f02ef7c8bb3d69a503486af0c1faee30b023e5b7 md5: eaac87c21aff3ed21ad9656697bb8326 depends: - llvm-openmp >=9.0.1 license: BSD-3-Clause license_family: BSD purls: [] size: 8328 timestamp: 1764092562779 - conda: https://prefix.dev/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda build_number: 7 sha256: 7acaa2e0782cad032bdaf756b536874346ac1375745fb250e9bdd6a48a7ab3cd md5: a44032f282e7d2acdeb1c240308052dd depends: - llvm-openmp >=9.0.1 license: BSD-3-Clause license_family: BSD purls: [] size: 8325 timestamp: 1764092507920 - conda: https://prefix.dev/conda-forge/win-64/_openmp_mutex-4.5-2_gnu.conda build_number: 8 sha256: 1a62cd1f215fe0902e7004089693a78347a30ad687781dfda2289cab000e652d md5: 37e16618af5c4851a3f3d66dd0e11141 depends: - libgomp >=7.5.0 - libwinpthread >=12.0.0.r2.ggc561118da constrains: - openmp_impl 9999 - msys2-conda-epoch <0.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 49468 timestamp: 1718213032772 - conda: https://prefix.dev/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 md5: aaa2a381ccc56eac91d63b6c1240312f depends: - cpython - python-gil license: MIT license_family: MIT purls: [] size: 8191 timestamp: 1744137672556 - conda: https://prefix.dev/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda sha256: d88aa7ae766cf584e180996e92fef2aa7d8e0a0a5ab1d4d49c32390c1b5fff31 md5: dcdc58c15961dbf17a0621312b01f5cb depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: LGPL-2.1-or-later license_family: GPL purls: [] size: 584660 timestamp: 1768327524772 - conda: https://prefix.dev/conda-forge/noarch/anyio-4.12.1-pyhcf101f3_0.conda sha256: eb0c4e2b24f1fbefaf96ce6c992c6bd64340bc3c06add4d7415ab69222b201da md5: 11a2b8c732d215d977998ccd69a9d5e8 depends: - exceptiongroup >=1.0.2 - idna >=2.8 - python >=3.10 - typing_extensions >=4.5 - python constrains: - trio >=0.32.0 - uvloop >=0.21 license: MIT license_family: MIT purls: - pkg:pypi/anyio?source=compressed-mapping size: 145175 timestamp: 1767719033569 - conda: https://prefix.dev/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda sha256: 8f032b140ea4159806e4969a68b4a3c0a7cab1ad936eb958a2b5ffe5335e19bf md5: 54898d0f524c9dee622d44bbb081a8ab depends: - python >=3.9 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/appnope?source=hash-mapping size: 10076 timestamp: 1733332433806 - conda: https://prefix.dev/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda sha256: bea62005badcb98b1ae1796ec5d70ea0fc9539e7d59708ac4e7d41e2f4bb0bad md5: 8ac12aff0860280ee0cff7fa2cf63f3b depends: - argon2-cffi-bindings - python >=3.9 - typing-extensions constrains: - argon2_cffi ==999 license: MIT license_family: MIT purls: - pkg:pypi/argon2-cffi?source=hash-mapping size: 18715 timestamp: 1749017288144 - conda: https://prefix.dev/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py313h07c4f96_2.conda sha256: ad188ccc06a06c633dc124b09e9e06fb9df4c32ffc38acc96ecc86e506062090 md5: 27bbec9f2f3a15d32b60ec5734f5b41c depends: - __glibc >=2.17,<3.0.a0 - cffi >=1.0.1 - libgcc >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping size: 35943 timestamp: 1762509452935 - conda: https://prefix.dev/conda-forge/osx-64/argon2-cffi-bindings-25.1.0-py313hf050af9_2.conda sha256: e2644e87c26512e38c63ace8fc19120a472c0983718a8aa264862c25294d0632 md5: 1fedb53ffc72b7d1162daa934ad7996b depends: - __osx >=10.13 - cffi >=1.0.1 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping size: 33301 timestamp: 1762509795647 - conda: https://prefix.dev/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py313h6535dbc_2.conda sha256: 05ea6fa7109235cfb4fc24526bae1fe82d88bbb5e697ab3945c313f5f041af5b md5: e23e087109b2096db4cf9a3985bab329 depends: - __osx >=11.0 - cffi >=1.0.1 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping size: 33947 timestamp: 1762510144907 - conda: https://prefix.dev/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py313h5ea7bf4_2.conda sha256: 3f8a1affdfeb2be5289d709e365fc6e386d734773895215cf8cbc5100fa6af9a md5: eabb4b677b54874d7d6ab775fdaa3d27 depends: - cffi >=1.0.1 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping size: 38779 timestamp: 1762509796090 - conda: https://prefix.dev/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda sha256: 792da8131b1b53ff667bd6fc617ea9087b570305ccb9913deb36b8e12b3b5141 md5: 85c4f19f377424eafc4ed7911b291642 depends: - python >=3.10 - python-dateutil >=2.7.0 - python-tzdata - python license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/arrow?source=hash-mapping size: 113854 timestamp: 1760831179410 - conda: https://prefix.dev/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda sha256: ee4da0f3fe9d59439798ee399ef3e482791e48784873d546e706d0935f9ff010 md5: 9673a61a297b00016442e022d689faa6 depends: - python >=3.10 constrains: - astroid >=2,<5 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/asttokens?source=hash-mapping size: 28797 timestamp: 1763410017955 - conda: https://prefix.dev/conda-forge/noarch/async-lru-2.1.0-pyhcf101f3_0.conda sha256: fb09cb9bfe4da1586d0ad3bf80bb65e70acfd5fe0f76df384250a1c0587d6acc md5: 04d2e5fba67e5a1ecec8e25d6c769004 depends: - python >=3.10 - typing_extensions >=4.0.0 - python license: MIT license_family: MIT purls: - pkg:pypi/async-lru?source=hash-mapping size: 19458 timestamp: 1768752884184 - conda: https://prefix.dev/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda sha256: c13d5e42d187b1d0255f591b7ce91201d4ed8a5370f0d986707a802c20c9d32f md5: 537296d57ea995666c68c821b00e360b depends: - python >=3.10 - python license: MIT license_family: MIT purls: - pkg:pypi/attrs?source=hash-mapping size: 64759 timestamp: 1764875182184 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-auth-0.9.3-hef928c7_0.conda sha256: d9c5babed03371448bb0dc91a1573c80d278d1222a3b0accef079ed112e584f9 md5: bdd464b33f6540ed70845b946c11a7b8 depends: - libgcc >=14 - __glibc >=2.17,<3.0.a0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 133443 timestamp: 1764765235190 - conda: https://prefix.dev/conda-forge/osx-64/aws-c-auth-0.9.3-hdff831d_0.conda sha256: aaadae39675911059bf0caa072c9d0cab622278365f6c3ceb6a63a2e9e57df03 md5: a04fb222805ce5697065036ae1676436 depends: - __osx >=10.13 - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 119662 timestamp: 1764765258455 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-auth-0.9.3-h1ddaa69_0.conda sha256: 491576e1ef8640e0cc345705c2028aebb98e015d51471395fe595f60a3b33884 md5: f0cc47ecd2058f2dd65fde1a5f6528ec depends: - __osx >=11.0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 114473 timestamp: 1764765266429 - conda: https://prefix.dev/conda-forge/win-64/aws-c-auth-0.9.3-h2970c50_0.conda sha256: 1ca3be8873335aff46da2d613c0e9e0c27b9878e402548e3cf31cd378a2f9342 md5: 6f42aac88a3b880dd3a4e0fe61f418bc depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 125616 timestamp: 1764765271198 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-cal-0.9.13-h2c9d079_1.conda sha256: f21d648349a318f4ae457ea5403d542ba6c0e0343b8642038523dd612b2a5064 md5: 3c3d02681058c3d206b562b2e3bc337f depends: - __glibc >=2.17,<3.0.a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - libgcc >=14 - openssl >=3.5.4,<4.0a0 license: Apache-2.0 license_family: Apache purls: [] size: 56230 timestamp: 1764593147526 - conda: https://prefix.dev/conda-forge/osx-64/aws-c-cal-0.9.13-hea39f9f_1.conda sha256: c085b749572ca7c137dfbf8a2a4fd505657f8f7f8a7b374d5f41bf4eb2dd9214 md5: cbf7be9e03e8b5e38ec60b6dbdf3a649 depends: - __osx >=10.13 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: Apache purls: [] size: 45262 timestamp: 1764593359925 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-cal-0.9.13-h6ee9776_1.conda sha256: 13c42cb54619df0a1c3e5e5b0f7c8e575460b689084024fd23abeb443aac391b md5: 8baab664c541d6f059e83423d9fc5e30 depends: - __osx >=11.0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: Apache purls: [] size: 45233 timestamp: 1764593742187 - conda: https://prefix.dev/conda-forge/win-64/aws-c-cal-0.9.13-h46f3b43_1.conda sha256: 5f61082caea9fbdd6ba02702935e9dea9997459a7e6c06fd47f21b81aac882fb md5: 7cc4953d504d4e8f3d6f4facb8549465 depends: - aws-c-common >=0.12.6,<0.12.7.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: Apache purls: [] size: 53613 timestamp: 1764593604081 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-common-0.12.6-hb03c661_0.conda sha256: 926a5b9de0a586e88669d81de717c8dd3218c51ce55658e8a16af7e7fe87c833 md5: e36ad70a7e0b48f091ed6902f04c23b8 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: Apache-2.0 license_family: Apache purls: [] size: 239605 timestamp: 1763585595898 - conda: https://prefix.dev/conda-forge/osx-64/aws-c-common-0.12.6-h8616949_0.conda sha256: 66fb2710898bb3e25cb4af52ee88a0559dcde5e56e6bd09b31b98a346a89b2e3 md5: c7f2d588a6d50d170b343f3ae0b72e62 depends: - __osx >=10.13 license: Apache-2.0 license_family: Apache purls: [] size: 230785 timestamp: 1763585852531 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-common-0.12.6-hc919400_0.conda sha256: cd3817c82470826167b1d8008485676862640cff65750c34062e6c20aeac419b md5: b759f02a7fa946ea9fd9fb035422c848 depends: - __osx >=11.0 license: Apache-2.0 license_family: Apache purls: [] size: 224116 timestamp: 1763585987935 - conda: https://prefix.dev/conda-forge/win-64/aws-c-common-0.12.6-hfd05255_0.conda sha256: 0627691c34eb3d9fcd18c71346d9f16f83e8e58f9983e792138a2cccf387d18a md5: b1465f33b05b9af02ad0887c01837831 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: Apache purls: [] size: 236441 timestamp: 1763586152571 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-compression-0.3.1-h8b1a151_9.conda sha256: 96edccb326b8c653c8eb95a356e01d4aba159da1a97999577b7dd74461b040b4 md5: f7ec84186dfe7a9e3a9f9e5a4d023e75 depends: - libgcc >=14 - __glibc >=2.17,<3.0.a0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 22272 timestamp: 1764593718823 - conda: https://prefix.dev/conda-forge/osx-64/aws-c-compression-0.3.1-h901532c_9.conda sha256: b99ddb6654ca12b9f530ca4cbe4d2063335d4ac43f9d97092c4076ccaf9b89e7 md5: abb79371a321d47da8f7ddca128533de depends: - __osx >=10.13 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 21423 timestamp: 1764593738902 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-compression-0.3.1-h16f91aa_9.conda sha256: 988f2251c5ddb91a93a3893e52eccb4fdd8b755af80bbc2bf739aabc25c5cfdf md5: 8dc111381c4c73deb8b9a529b3abee4a depends: - __osx >=11.0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 21372 timestamp: 1764593773975 - conda: https://prefix.dev/conda-forge/win-64/aws-c-compression-0.3.1-hcb3a2da_9.conda sha256: ff1046d67709960859adfa5793391a2d233bb432ec7429069fcfab5b643827df md5: 0888dbe9e883582d138ec6221f5482d6 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 23136 timestamp: 1764593733263 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-event-stream-0.5.7-h28f887f_1.conda sha256: a5b151db1c8373b6ca2dacea65bc8bda02791a43685eebfa4ea987bb1a758ca9 md5: 7b8e3f846353b75db163ad93248e5f9d depends: - libgcc >=14 - libstdcxx >=14 - __glibc >=2.17,<3.0.a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-checksums >=0.2.7,<0.2.8.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 58806 timestamp: 1764675439822 - conda: https://prefix.dev/conda-forge/osx-64/aws-c-event-stream-0.5.7-ha05da6a_1.conda sha256: 56f7aebd59d5527830ef7cf6e91f63ee4c5cf510af56529276affe8e2dc9eb24 md5: e0d71662f35b21fb993484238b4861d9 depends: - __osx >=10.13 - libcxx >=19 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-checksums >=0.2.7,<0.2.8.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 52911 timestamp: 1764675471218 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-event-stream-0.5.7-h9ae9c55_1.conda sha256: c336b71a356d9b39fa6e9769d475dea6fd0cfe25ad81dcecac3102ef30f8b753 md5: 53c59e7f68bbd3754de6c8dcd4c27f86 depends: - libcxx >=19 - __osx >=11.0 - aws-checksums >=0.2.7,<0.2.8.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 52221 timestamp: 1764675514267 - conda: https://prefix.dev/conda-forge/win-64/aws-c-event-stream-0.5.7-ha388e84_1.conda sha256: 5fbbfd835831dace087064d08c38eb279b7db3231fbd0db32fad86fe9273c10c md5: 34e3b065b76c8a144c92e224cc3f5672 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-checksums >=0.2.7,<0.2.8.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 57054 timestamp: 1764675494741 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-http-0.10.7-ha8fc4e3_5.conda sha256: 5527224d6e0813e37426557d38cb04fed3753d6b1e544026cfbe2654f5e556be md5: 3028f20dacafc00b22b88b324c8956cc depends: - libgcc >=14 - __glibc >=2.17,<3.0.a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-compression >=0.3.1,<0.3.2.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 224580 timestamp: 1764675497060 - conda: https://prefix.dev/conda-forge/osx-64/aws-c-http-0.10.7-h924c446_5.conda sha256: 53ee041db79f6cbff62179b2f693e50e484d163b9a843a3dbbb80dbc36220c7e md5: acff093ebb711857fb78fae3b656631c depends: - __osx >=10.13 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-compression >=0.3.1,<0.3.2.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 192149 timestamp: 1764675489248 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-http-0.10.7-h5928ca5_5.conda sha256: 29e180b61155279a2e64011b95957fbe38385113c60467b8d34fce47bc29c728 md5: f12bd6066c693efba2e5886e2c70d7ba depends: - __osx >=11.0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-compression >=0.3.1,<0.3.2.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 171020 timestamp: 1764675515369 - conda: https://prefix.dev/conda-forge/win-64/aws-c-http-0.10.7-hc678f4a_5.conda sha256: 4f41b922ce01c983f98898208d49af5f3d6b0d8f3e8dcb44bd13d8183287b19a md5: 3427460b0654d317e72a0ba959bb3a23 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-compression >=0.3.1,<0.3.2.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 206709 timestamp: 1764675527860 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-io-0.23.3-hdaf4b65_5.conda sha256: 07d7f2a4493ada676084c3f4313da1fab586cf0a7302572c5d8dde6606113bf4 md5: 132e8f8f40f0ffc0bbde12bb4e8dd1a1 depends: - libgcc >=14 - __glibc >=2.17,<3.0.a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - s2n >=1.6.2,<1.6.3.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 181361 timestamp: 1765168239856 - conda: https://prefix.dev/conda-forge/osx-64/aws-c-io-0.23.3-hf559bb5_5.conda sha256: 734496fb5a33a4d13ff0a27c5bc4a0f4e7fe9ed15ec099722d5be82b456b9502 md5: d9cc056da3a1ee0a2da750d10a5496f3 depends: - __osx >=10.15 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 182572 timestamp: 1765168277462 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-io-0.23.3-hbe03c90_5.conda sha256: bf1c7cf7997d28922283e6612e5ea6a9409fcfc2749cd4acfafd1bf6e0c57c08 md5: c249aa1a151e319d7acd05a2e1f165d2 depends: - __osx >=11.0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 176451 timestamp: 1765168273313 - conda: https://prefix.dev/conda-forge/win-64/aws-c-io-0.23.3-h0d5b9f9_5.conda sha256: 2d726ffd67fb387dbebf63c9b9965b476b9d670f683e71c3dca1feb6365ddc7c md5: 400792109e426730ac9047fd6c9537ef depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 182053 timestamp: 1765168273517 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-mqtt-0.13.3-hc63082f_11.conda sha256: fb102b0346a1f5c4f3bb680ec863c529b0333fa4119d78768c3e8a5d1cc2c812 md5: 6a653aefdc5d83a4f959869d1759e6e3 depends: - libgcc >=14 - __glibc >=2.17,<3.0.a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 216454 timestamp: 1764681745427 - conda: https://prefix.dev/conda-forge/osx-64/aws-c-mqtt-0.13.3-ha72ff4e_11.conda sha256: c05215c85f90a0caba1202f4c852d6e3a2ad93b4a25f286435a8e855db4237ae md5: 96f22c912f1cf3493d9113b9fd04c912 depends: - __osx >=10.13 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 188230 timestamp: 1764681760102 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-mqtt-0.13.3-haf5c5c8_11.conda sha256: 880996ae8c792eb15fcbca0a452d8b3508dba16ed7384bdb73fb7ed6c075c125 md5: 3fcd02361ce1427ae5968fcd532a85b4 depends: - __osx >=11.0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-http >=0.10.7,<0.10.8.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 150454 timestamp: 1764681796127 - conda: https://prefix.dev/conda-forge/win-64/aws-c-mqtt-0.13.3-hfa314fa_11.conda sha256: 9b241397ef436dcf67e8e6cde15ff9c0d03ea942ad11e27c77caecce0d51b5be md5: 6c043365f1d3f89c0b68238c6f5b8cce depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-http >=0.10.7,<0.10.8.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 206357 timestamp: 1764681793150 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-s3-0.11.3-h06ab39a_1.conda sha256: 8de2292329dce2fd512413d83988584d616582442a07990f67670f9bc793a98b md5: 3689a4290319587e3b54a4f9e68f70c8 depends: - libgcc >=14 - __glibc >=2.17,<3.0.a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - openssl >=3.5.4,<4.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-auth >=0.9.3,<0.9.4.0a0 - aws-checksums >=0.2.7,<0.2.8.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 151382 timestamp: 1765174166541 - conda: https://prefix.dev/conda-forge/osx-64/aws-c-s3-0.11.3-he30762a_1.conda sha256: 9c989a5f0b35ff5cee91b74bcba0d540ce5684450dc072ba0bb5299783cdf9cd md5: 33c653401dc7b016b0011cb4d16de458 depends: - __osx >=10.13 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-auth >=0.9.3,<0.9.4.0a0 - aws-checksums >=0.2.7,<0.2.8.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 133827 timestamp: 1765174162875 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-s3-0.11.3-h8da9771_1.conda sha256: 31f432d1a0f7dacbe80b476c3236c22a71f4018e840ae6974e843d38d5763335 md5: 06417cb45f131cf503d3483446cedbc3 depends: - __osx >=11.0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-checksums >=0.2.7,<0.2.8.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-auth >=0.9.3,<0.9.4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 129384 timestamp: 1765174183548 - conda: https://prefix.dev/conda-forge/win-64/aws-c-s3-0.11.3-ha659bf3_1.conda sha256: cda138c03683e85f29eafc680b043a40f304ac8759138dc141a42878eb17a90f md5: dcfc08ccd8e332411c454e38110ea915 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-auth >=0.9.3,<0.9.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-checksums >=0.2.7,<0.2.8.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 141805 timestamp: 1765174184168 - conda: https://prefix.dev/conda-forge/linux-64/aws-c-sdkutils-0.2.4-h8b1a151_4.conda sha256: 9d62c5029f6f8219368a8665f0a549da572dc777f52413b7d75609cacdbc02cc md5: c7e3e08b7b1b285524ab9d74162ce40b depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 59383 timestamp: 1764610113765 - conda: https://prefix.dev/conda-forge/osx-64/aws-c-sdkutils-0.2.4-h901532c_4.conda sha256: 468629dbf52fee6dcabda1fcb0c0f2f29941b9001dcc75a57ebfbe38d0bde713 md5: b384fb05730f549a55cdb13c484861eb depends: - __osx >=10.13 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 55664 timestamp: 1764610141049 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-c-sdkutils-0.2.4-h16f91aa_4.conda sha256: 8a4ee03ea6e14d5a498657e5fe96875a133b4263b910c5b60176db1a1a0aaa27 md5: 658a8236f3f1ebecaaa937b5ccd5d730 depends: - __osx >=11.0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 53430 timestamp: 1764755714246 - conda: https://prefix.dev/conda-forge/win-64/aws-c-sdkutils-0.2.4-hcb3a2da_4.conda sha256: c86c30edba7457e04d905c959328142603b62d7d1888aed893b2e21cca9c302c md5: 3c97faee5be6fd0069410cf2bca71c85 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 56509 timestamp: 1764610148907 - conda: https://prefix.dev/conda-forge/linux-64/aws-checksums-0.2.7-h8b1a151_5.conda sha256: a8693d2e06903a09e98fe724ed5ec32e7cd1b25c405d754f0ab7efb299046f19 md5: 68da5b56dde41e172b7b24f071c4b392 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 76915 timestamp: 1764593731486 - conda: https://prefix.dev/conda-forge/osx-64/aws-checksums-0.2.7-h901532c_5.conda sha256: 0f67c453829592277f90d520f7855e260cf0565a3dc59fe90c55293996b7fbe9 md5: cccf553ce36da9ae739206b69c1a4d28 depends: - __osx >=10.13 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 75646 timestamp: 1764593751665 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-checksums-0.2.7-h16f91aa_5.conda sha256: c630ece8c0fe99cdf03774bb0b048cfd72daec0458dbc825be5de0106431087e md5: ee9ebfd7b6fdf61dd632e4fea6287c47 depends: - __osx >=11.0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 74377 timestamp: 1764593734393 - conda: https://prefix.dev/conda-forge/win-64/aws-checksums-0.2.7-hcb3a2da_5.conda sha256: ca5e0719b7ca257462a4aa7d3b99fde756afaf579ee1472cac91c04c7bf3a725 md5: 38f1501fc55f833a4567c83581a2d2ed depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 93142 timestamp: 1764593765744 - conda: https://prefix.dev/conda-forge/linux-64/aws-crt-cpp-0.35.4-h8824e59_0.conda sha256: 524fc8aa2645e5701308b865bf5c523257feabc6dfa7000cb8207ccfbb1452a1 md5: 113b9d9913280474c0868b0e290c0326 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - aws-c-event-stream >=0.5.7,<0.5.8.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-auth >=0.9.3,<0.9.4.0a0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-mqtt >=0.13.3,<0.13.4.0a0 - aws-c-s3 >=0.11.3,<0.11.4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 408804 timestamp: 1765200263609 - conda: https://prefix.dev/conda-forge/osx-64/aws-crt-cpp-0.35.4-h7484968_0.conda sha256: d3ab94c9245f667c78940d6838529401795ce0df02ad561d190c38819a312cd9 md5: 31db311b3005b16ff340796e424a6b3c depends: - libcxx >=19 - __osx >=10.13 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-mqtt >=0.13.3,<0.13.4.0a0 - aws-c-s3 >=0.11.3,<0.11.4.0a0 - aws-c-auth >=0.9.3,<0.9.4.0a0 - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-event-stream >=0.5.7,<0.5.8.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 343812 timestamp: 1765200322696 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-crt-cpp-0.35.4-h74951b9_0.conda sha256: 465527f414c2399ab70503d9d4e891658e7698439ba7f22d723f2ca8c03bb3e8 md5: 87351fb3a08425237b701c582773be1a depends: - __osx >=11.0 - libcxx >=19 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 - aws-c-s3 >=0.11.3,<0.11.4.0a0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-auth >=0.9.3,<0.9.4.0a0 - aws-c-mqtt >=0.13.3,<0.13.4.0a0 - aws-c-event-stream >=0.5.7,<0.5.8.0a0 - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 266862 timestamp: 1765200345049 - conda: https://prefix.dev/conda-forge/win-64/aws-crt-cpp-0.35.4-hca034e6_0.conda sha256: 7b4aef9e1823207a5f91e8b5b95853bdfafcfea306cd62b99fd53c38aa5c3da0 md5: ce1a20b5c406727e32222ac91e5848c4 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-c-mqtt >=0.13.3,<0.13.4.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-sdkutils >=0.2.4,<0.2.5.0a0 - aws-c-event-stream >=0.5.7,<0.5.8.0a0 - aws-c-http >=0.10.7,<0.10.8.0a0 - aws-c-cal >=0.9.13,<0.9.14.0a0 - aws-c-auth >=0.9.3,<0.9.4.0a0 - aws-c-s3 >=0.11.3,<0.11.4.0a0 - aws-c-io >=0.23.3,<0.23.4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 302247 timestamp: 1765200336894 - conda: https://prefix.dev/conda-forge/linux-64/aws-sdk-cpp-1.11.606-h20b40b1_10.conda sha256: e0d81b7dd6d054d457a1c54d17733d430d96dc5ca9b2ca69a72eb41c3fc8c9bf md5: 937d1d4c233adc6eeb2ac3d6e9a73e53 depends: - libstdcxx >=14 - libgcc >=14 - __glibc >=2.17,<3.0.a0 - libcurl >=8.17.0,<9.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-crt-cpp >=0.35.4,<0.35.5.0a0 - libzlib >=1.3.1,<2.0a0 - aws-c-event-stream >=0.5.7,<0.5.8.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 3472674 timestamp: 1765257107074 - conda: https://prefix.dev/conda-forge/osx-64/aws-sdk-cpp-1.11.606-h386ebac_10.conda sha256: 3b7ee2bc2bbd41e1fca87b1c1896b2186644f20912bf89756fd39020f8461e13 md5: 768c6b78e331a2938af208e062fd6702 depends: - libcxx >=19 - __osx >=10.13 - libcurl >=8.17.0,<9.0a0 - aws-crt-cpp >=0.35.4,<0.35.5.0a0 - libzlib >=1.3.1,<2.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-c-event-stream >=0.5.7,<0.5.8.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 3313002 timestamp: 1765257111791 - conda: https://prefix.dev/conda-forge/osx-arm64/aws-sdk-cpp-1.11.606-h4e1b0f7_10.conda sha256: 87660413df6c49984a897544c8ace8461cd4ed69301ede5a793d00530985f702 md5: a392fe9e9a3c6e0b65161533aca39be9 depends: - __osx >=11.0 - libcxx >=19 - aws-c-event-stream >=0.5.7,<0.5.8.0a0 - libzlib >=1.3.1,<2.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - aws-crt-cpp >=0.35.4,<0.35.5.0a0 - libcurl >=8.17.0,<9.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 3121951 timestamp: 1765257130593 - conda: https://prefix.dev/conda-forge/win-64/aws-sdk-cpp-1.11.606-hac16450_10.conda sha256: 8a12c4f6774ecb3641048b74133ff5e6c2b560469fe5ac1d7515631b84e63059 md5: d9b942bede589d0ad1e8e360e970efd0 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - aws-crt-cpp >=0.35.4,<0.35.5.0a0 - aws-c-common >=0.12.6,<0.12.7.0a0 - libzlib >=1.3.1,<2.0a0 - aws-c-event-stream >=0.5.7,<0.5.8.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 3438133 timestamp: 1765257127502 - conda: https://prefix.dev/conda-forge/linux-64/azure-core-cpp-1.16.1-h3a458e0_0.conda sha256: cba633571e7368953520a4f66dc74c3942cc12f735e0afa8d3d5fc3edf35c866 md5: 1d4e0d37da5f3c22ecd44033f673feba depends: - __glibc >=2.17,<3.0.a0 - libcurl >=8.14.1,<9.0a0 - libgcc >=14 - libstdcxx >=14 - openssl >=3.5.4,<4.0a0 license: MIT license_family: MIT purls: [] size: 348231 timestamp: 1760926677260 - conda: https://prefix.dev/conda-forge/osx-64/azure-core-cpp-1.16.1-he2a98a9_0.conda sha256: 923a0f9fab0c922e17f8bb27c8210d8978111390ff4e0cf6c1adff3c1a4d13bc md5: 9f39c22aad61e76bfb73bb7d4114efac depends: - __osx >=10.13 - libcurl >=8.14.1,<9.0a0 - libcxx >=19 - openssl >=3.5.4,<4.0a0 license: MIT license_family: MIT purls: [] size: 297681 timestamp: 1760927174036 - conda: https://prefix.dev/conda-forge/osx-arm64/azure-core-cpp-1.16.1-h88fedcc_0.conda sha256: d995413e4daf19ee3120f3ab9f0c9e330771787f33cbd4a33d8e5445f52022e3 md5: fbe485a39b05090c0b5f8bb4febcd343 depends: - __osx >=11.0 - libcurl >=8.14.1,<9.0a0 - libcxx >=19 - openssl >=3.5.4,<4.0a0 license: MIT license_family: MIT purls: [] size: 289984 timestamp: 1760927117177 - conda: https://prefix.dev/conda-forge/linux-64/azure-identity-cpp-1.13.2-h3a5f585_1.conda sha256: fc1df5ea2595f4f16d0da9f7713ce5fed20cb1bfc7fb098eda7925c7d23f0c45 md5: 4e921d9c85e6559c60215497978b3cdb depends: - __glibc >=2.17,<3.0.a0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - libgcc >=14 - libstdcxx >=14 - openssl >=3.5.4,<4.0a0 license: MIT license_family: MIT purls: [] size: 249684 timestamp: 1761066654684 - conda: https://prefix.dev/conda-forge/osx-64/azure-identity-cpp-1.13.2-h0e8e1c8_1.conda sha256: 555e9c9262b996f8c688598760b4cddf4d16ae1cb2f0fd0a31cb76c2fdc7d628 md5: 32eb613f88ae1530ca78481bdce41cdd depends: - __osx >=10.13 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - libcxx >=19 - openssl >=3.5.4,<4.0a0 license: MIT license_family: MIT purls: [] size: 174582 timestamp: 1761067038720 - conda: https://prefix.dev/conda-forge/osx-arm64/azure-identity-cpp-1.13.2-h853621b_1.conda sha256: a4ed52062025035d9c1b3d8c70af39496fc5153cc741420139a770bc1312cfd6 md5: fac63edc393d7035ab23fbccdeda34f4 depends: - __osx >=11.0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - libcxx >=19 - openssl >=3.5.4,<4.0a0 license: MIT license_family: MIT purls: [] size: 167268 timestamp: 1761066827371 - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-blobs-cpp-12.16.0-h75daedc_0.conda sha256: c155301bd9287480939b505b101db188b17564353366f1314080c7d8084077df md5: e88f8e816ae46c12cbe912c8f4d9d3bc depends: - __glibc >=2.17,<3.0.a0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - azure-storage-common-cpp >=12.12.0,<12.12.1.0a0 - libgcc >=14 - libstdcxx >=14 license: MIT license_family: MIT purls: [] size: 580063 timestamp: 1768483495056 - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-blobs-cpp-12.16.0-ha4e89a6_0.conda sha256: 446abd2fad0aa6b74207733534efc5e3ac4624bee981f40495cd4b8ae02d65ed md5: 5f76a3745c0eb7021845161c9a1bfee3 depends: - __osx >=10.13 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - azure-storage-common-cpp >=12.12.0,<12.12.1.0a0 - libcxx >=19 license: MIT license_family: MIT purls: [] size: 434189 timestamp: 1768483686754 - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-blobs-cpp-12.16.0-h6507aac_0.conda sha256: fbf0d01d29dae190346f294ade76d7fda9b869e12176cb368b10c3fa2588e568 md5: ebcb072935c1595c39e2c62f0d3e50cc depends: - __osx >=11.0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - azure-storage-common-cpp >=12.12.0,<12.12.1.0a0 - libcxx >=19 license: MIT license_family: MIT purls: [] size: 426388 timestamp: 1768483945648 - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-common-cpp-12.12.0-h3d7a050_0.conda sha256: b1f91b15e46d9c33129374a5cbca302070311711838ae135bb3f6767af95f707 md5: e6f12de3a9b016cea81a87db04d85ff3 depends: - __glibc >=2.17,<3.0.a0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - libgcc >=14 - libstdcxx >=14 - libxml2 - libxml2-16 >=2.14.6 - openssl >=3.5.4,<4.0a0 license: MIT license_family: MIT purls: [] size: 149750 timestamp: 1768406691043 - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-common-cpp-12.12.0-h2a5eb39_0.conda sha256: b0ca0c4896fcc94ed1756a41c38fac2a95d28748ca89a90f99f6ceb8b4db0c26 md5: 53d1b2dc90315c3b8e4ecc86966ab7bd depends: - __osx >=10.13 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - libcxx >=19 - libxml2 - libxml2-16 >=2.14.6 - openssl >=3.5.4,<4.0a0 license: MIT license_family: MIT purls: [] size: 126024 timestamp: 1768407197686 - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-common-cpp-12.12.0-ha416c23_0.conda sha256: e20bb2e6abf1d6823cd89db7a8ad91084560ba1a4d144f5dc6baa25711a30a3f md5: 327799f2eb655ddf596b3e0ba2658979 depends: - __osx >=11.0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - libcxx >=19 - libxml2 - libxml2-16 >=2.14.6 - openssl >=3.5.4,<4.0a0 license: MIT license_family: MIT purls: [] size: 121803 timestamp: 1768406901262 - conda: https://prefix.dev/conda-forge/linux-64/azure-storage-files-datalake-cpp-12.14.0-hd454692_0.conda sha256: e9a64773488382997f28944612525f9cb7d8a3f8cbb0be2f0a07dc0881311925 md5: 55986e49b7aafe9aa09d7f4c70a56a18 depends: - __glibc >=2.17,<3.0.a0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - azure-storage-blobs-cpp >=12.16.0,<12.16.1.0a0 - azure-storage-common-cpp >=12.12.0,<12.12.1.0a0 - libgcc >=14 - libstdcxx >=14 license: MIT license_family: MIT purls: [] size: 302378 timestamp: 1768501952777 - conda: https://prefix.dev/conda-forge/osx-64/azure-storage-files-datalake-cpp-12.14.0-h7f37a48_0.conda sha256: f3aabb7c5023828aba930b82046b81b87a794b0c5c8a1db82043e88b3f5ca136 md5: 30ca75c03ba3166f44852b33f07f077c depends: - __osx >=10.13 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - azure-storage-blobs-cpp >=12.16.0,<12.16.1.0a0 - azure-storage-common-cpp >=12.12.0,<12.12.1.0a0 - libcxx >=19 license: MIT license_family: MIT purls: [] size: 204696 timestamp: 1768502627687 - conda: https://prefix.dev/conda-forge/osx-arm64/azure-storage-files-datalake-cpp-12.14.0-hcfc4f22_0.conda sha256: f8d1ec719f3e3047d0f5be4be6973e5b4218c00b83b0707c327384304bcc2a72 md5: a49804e4c4ad182a8de7b251d77f3b0c depends: - __osx >=11.0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - azure-storage-blobs-cpp >=12.16.0,<12.16.1.0a0 - azure-storage-common-cpp >=12.12.0,<12.12.1.0a0 - libcxx >=19 license: MIT license_family: MIT purls: [] size: 197881 timestamp: 1768502314584 - conda: https://prefix.dev/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda sha256: 1c656a35800b7f57f7371605bc6507c8d3ad60fbaaec65876fce7f73df1fc8ac md5: 0a01c169f0ab0f91b26e77a3301fbfe4 depends: - python >=3.9 - pytz >=2015.7 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/babel?source=hash-mapping size: 6938256 timestamp: 1738490268466 - conda: https://prefix.dev/conda-forge/linux-64/backports.zstd-1.3.0-py311h6b1f9c4_0.conda sha256: 246e50ec7fc222875c6ecfa3feab77f5661dc43e26397bc01d9e0310e3cd48a0 md5: adda5ef2a74c9bdb338ff8a51192898a depends: - python - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python_abi 3.11.* *_cp311 - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - pkg:pypi/backports-zstd?source=hash-mapping size: 244920 timestamp: 1767044984647 - conda: https://prefix.dev/conda-forge/linux-64/backports.zstd-1.3.0-py313h18e8e13_0.conda sha256: 9552afbec37c4d8d0e83a5c4c6b3c7f4b8785f935094ce3881e0a249045909ce md5: d9e90792551a527200637e23a915dd79 depends: - python - libgcc >=14 - __glibc >=2.17,<3.0.a0 - python_abi 3.13.* *_cp313 - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - pkg:pypi/backports-zstd?source=hash-mapping size: 240943 timestamp: 1767044981366 - conda: https://prefix.dev/conda-forge/osx-64/backports.zstd-1.3.0-py311hdc67420_0.conda sha256: 7230ab90abf6bb3c3ee13e4d4bd22d9f1c3c08f1462c07909a8fbabd19dae92f md5: 81100ad214bd892d904a81cacfb5b988 depends: - python - __osx >=10.13 - zstd >=1.5.7,<1.6.0a0 - python_abi 3.11.* *_cp311 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - pkg:pypi/backports-zstd?source=hash-mapping size: 243615 timestamp: 1767044978242 - conda: https://prefix.dev/conda-forge/osx-64/backports.zstd-1.3.0-py313h591e92b_0.conda sha256: 4133ba0e5ab6a0955b57a49ad4014148df6e4b79bef4309a1cdd407afd853444 md5: c602f30b6c45567cd5cfb074631beb5d depends: - python - __osx >=10.13 - python_abi 3.13.* *_cp313 - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - pkg:pypi/backports-zstd?source=hash-mapping size: 241212 timestamp: 1767044991370 - conda: https://prefix.dev/conda-forge/osx-arm64/backports.zstd-1.3.0-py311hee243d0_0.conda sha256: 57bace9e1431c53952af4cc98ee276cd47604ab98686d837b457246aa2a6dd45 md5: 6838fc10cc74fe2feb818e2add03d328 depends: - python - __osx >=11.0 - python 3.11.* *_cpython - zstd >=1.5.7,<1.6.0a0 - python_abi 3.11.* *_cp311 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - pkg:pypi/backports-zstd?source=hash-mapping size: 246748 timestamp: 1767045020742 - conda: https://prefix.dev/conda-forge/osx-arm64/backports.zstd-1.3.0-py313h48bb75e_0.conda sha256: f3047ca3b41bb444b4b5a71a6eee182623192c77019746dd4685fd260becb249 md5: 54008c5cc8928e5cb5a0f9206b829451 depends: - python - python 3.13.* *_cp313 - __osx >=11.0 - zstd >=1.5.7,<1.6.0a0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - pkg:pypi/backports-zstd?source=hash-mapping size: 244371 timestamp: 1767045003420 - conda: https://prefix.dev/conda-forge/win-64/backports.zstd-1.3.0-py311h71c1bcc_0.conda sha256: 5a30429e009b93c6dffe539cf0e3d220ef8d36ea42d36ca5c26b603cb3319c71 md5: 49eb28c4f92e8a7440e3da6d8e8b5e58 depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - zstd >=1.5.7,<1.6.0a0 - python_abi 3.11.* *_cp311 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - pkg:pypi/backports-zstd?source=hash-mapping size: 243289 timestamp: 1767045012846 - conda: https://prefix.dev/conda-forge/win-64/backports.zstd-1.3.0-py313h2a31948_0.conda sha256: 1e76ed9bcf07ef1df9c964d73e9cda08a0380845d09c8da1678a1687dc087c34 md5: cdcdfe68c5bc9af9e908e35ebffc9fe1 depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.13.* *_cp313 - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - pkg:pypi/backports-zstd?source=hash-mapping size: 240406 timestamp: 1767045016907 - conda: https://prefix.dev/conda-forge/noarch/backrefs-5.8-pyhd8ed1ab_0.conda sha256: 3a0af23d357a07154645c41d035a4efbd15b7a642db397fa9ea0193fd58ae282 md5: b16e2595d3a9042aa9d570375978835f depends: - python >=3.9 license: MIT license_family: MIT size: 143810 timestamp: 1740887689966 - conda: https://prefix.dev/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda sha256: bf1e71c3c0a5b024e44ff928225a0874fc3c3356ec1a0b6fe719108e6d1288f6 md5: 5267bef8efea4127aacd1f4e1f149b6e depends: - python >=3.10 - soupsieve >=1.2 - typing-extensions license: MIT license_family: MIT purls: - pkg:pypi/beautifulsoup4?source=hash-mapping size: 90399 timestamp: 1764520638652 - conda: https://prefix.dev/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda sha256: e03ba1a2b93fe0383c57920a9dc6b4e0c2c7972a3f214d531ed3c21dc8f8c717 md5: b1a27250d70881943cca0dd6b4ba0956 depends: - python >=3.10 - webencodings - python constrains: - tinycss >=1.1.0,<1.5 license: Apache-2.0 AND MIT purls: - pkg:pypi/bleach?source=hash-mapping size: 141952 timestamp: 1763589981635 - conda: https://prefix.dev/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda sha256: f85f6b2c7938d8c20c80ce5b7e6349fafbb49294641b5648273c5f892b150768 md5: 08a03378bc5293c6f97637323802f480 depends: - bleach ==6.3.0 pyhcf101f3_0 - tinycss2 license: Apache-2.0 AND MIT purls: [] size: 4386 timestamp: 1763589981639 - conda: https://prefix.dev/conda-forge/noarch/bokeh-3.8.2-pyhd8ed1ab_0.conda sha256: 5e1aaaa2d193c1d4acea261b8cf822ee84cb59b4cf8c26ad40ca172584ab2a85 md5: 0b830ba4947de6d60dd9d96827a1cacb depends: - contourpy >=1.2 - jinja2 >=2.9 - narwhals >=1.13 - numpy >=1.16 - packaging >=16.8 - pandas >=1.2 - pillow >=7.1.0 - python >=3.10 - pyyaml >=3.10 - tornado >=6.2 - xyzservices >=2021.09.1 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/bokeh?source=hash-mapping size: 4713032 timestamp: 1769414672158 - conda: https://prefix.dev/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda sha256: e511644d691f05eb12ebe1e971fd6dc3ae55a4df5c253b4e1788b789bdf2dfa6 md5: 8ccf913aaba749a5496c17629d859ed1 depends: - __glibc >=2.17,<3.0.a0 - brotli-bin 1.2.0 hb03c661_1 - libbrotlidec 1.2.0 hb03c661_1 - libbrotlienc 1.2.0 hb03c661_1 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 20103 timestamp: 1764017231353 - conda: https://prefix.dev/conda-forge/osx-64/brotli-1.2.0-hf139dec_1.conda sha256: c838c71ded28ada251589f6462fc0f7c09132396799eea2701277566a1a863bf md5: 149d8ee7d6541a02a6117d8814fd9413 depends: - __osx >=10.13 - brotli-bin 1.2.0 h8616949_1 - libbrotlidec 1.2.0 h8616949_1 - libbrotlienc 1.2.0 h8616949_1 license: MIT license_family: MIT purls: [] size: 20194 timestamp: 1764017661405 - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda sha256: 422ac5c91f8ef07017c594d9135b7ae068157393d2a119b1908c7e350938579d md5: 48ece20aa479be6ac9a284772827d00c depends: - __osx >=11.0 - brotli-bin 1.2.0 hc919400_1 - libbrotlidec 1.2.0 hc919400_1 - libbrotlienc 1.2.0 hc919400_1 license: MIT license_family: MIT purls: [] size: 20237 timestamp: 1764018058424 - conda: https://prefix.dev/conda-forge/win-64/brotli-1.2.0-h2d644bc_1.conda sha256: a4fffdf1c9b9d3d0d787e20c724cff3a284dfa3773f9ce609c93b1cfd0ce8933 md5: bc58fdbced45bb096364de0fba1637af depends: - brotli-bin 1.2.0 hfd05255_1 - libbrotlidec 1.2.0 hfd05255_1 - libbrotlienc 1.2.0 hfd05255_1 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 20342 timestamp: 1764017988883 - conda: https://prefix.dev/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda sha256: 64b137f30b83b1dd61db6c946ae7511657eead59fdf74e84ef0ded219605aa94 md5: af39b9a8711d4a8d437b52c1d78eb6a1 depends: - __glibc >=2.17,<3.0.a0 - libbrotlidec 1.2.0 hb03c661_1 - libbrotlienc 1.2.0 hb03c661_1 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 21021 timestamp: 1764017221344 - conda: https://prefix.dev/conda-forge/osx-64/brotli-bin-1.2.0-h8616949_1.conda sha256: dcb5a2b29244b82af2545efad13dfdf8dddb86f88ce64ff415be9e7a10cc0383 md5: 34803b20dfec7af32ba675c5ccdbedbf depends: - __osx >=10.13 - libbrotlidec 1.2.0 h8616949_1 - libbrotlienc 1.2.0 h8616949_1 license: MIT license_family: MIT purls: [] size: 18589 timestamp: 1764017635544 - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda sha256: e2d142052a83ff2e8eab3fe68b9079cad80d109696dc063a3f92275802341640 md5: 377d015c103ad7f3371be1777f8b584c depends: - __osx >=11.0 - libbrotlidec 1.2.0 hc919400_1 - libbrotlienc 1.2.0 hc919400_1 license: MIT license_family: MIT purls: [] size: 18628 timestamp: 1764018033635 - conda: https://prefix.dev/conda-forge/win-64/brotli-bin-1.2.0-hfd05255_1.conda sha256: e76966232ef9612de33c2087e3c92c2dc42ea5f300050735a3c646f33bce0429 md5: 6abd7089eb3f0c790235fe469558d190 depends: - libbrotlidec 1.2.0 hfd05255_1 - libbrotlienc 1.2.0 hfd05255_1 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 22714 timestamp: 1764017952449 - conda: https://prefix.dev/conda-forge/linux-64/brotli-python-1.2.0-py311h66f275b_1.conda sha256: c36eb061d9ead85f97644cfb740d485dba9b8823357f35c17851078e95e975c1 md5: 86daecb8e4ed1042d5dc6efbe0152590 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 constrains: - libbrotlicommon 1.2.0 hb03c661_1 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping size: 367573 timestamp: 1764017405384 - conda: https://prefix.dev/conda-forge/linux-64/brotli-python-1.2.0-py313hf159716_1.conda sha256: dadec2879492adede0a9af0191203f9b023f788c18efd45ecac676d424c458ae md5: 6c4d3597cf43f3439a51b2b13e29a4ba depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: - libbrotlicommon 1.2.0 hb03c661_1 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping size: 367721 timestamp: 1764017371123 - conda: https://prefix.dev/conda-forge/osx-64/brotli-python-1.2.0-py311h7e844b6_1.conda sha256: 292026d98fd60bb25852792e2fd6ee97be35515057cfe258416ea6e1998e3564 md5: ae49e04114f7f1673920fdbf326a047f depends: - __osx >=10.13 - libcxx >=19 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 constrains: - libbrotlicommon 1.2.0 h8616949_1 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping size: 389997 timestamp: 1764017848151 - conda: https://prefix.dev/conda-forge/osx-64/brotli-python-1.2.0-py313h8d69aa9_1.conda sha256: 3d328413ff65a12af493066d721d12f5ee82a0adf3565629ce4c797c4680162c md5: 7c5e382b4d5161535f1dd258103fea51 depends: - __osx >=10.13 - libcxx >=19 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: - libbrotlicommon 1.2.0 h8616949_1 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping size: 389859 timestamp: 1764018040907 - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-python-1.2.0-py311hdc60ec4_1.conda sha256: 617545ec0e97d35ed2ff7852f2581a20c0dda80b366d0c42a43706687f971ba8 md5: 150cbf381febcf0a5e470a8d066e1bc0 depends: - __osx >=11.0 - libcxx >=19 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 constrains: - libbrotlicommon 1.2.0 hc919400_1 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping size: 359588 timestamp: 1764018467340 - conda: https://prefix.dev/conda-forge/osx-arm64/brotli-python-1.2.0-py313hde1f3bb_1.conda sha256: 2e21dccccd68bedd483300f9ab87a425645f6776e6e578e10e0dd98c946e1be9 md5: b03732afa9f4f54634d94eb920dfb308 depends: - __osx >=11.0 - libcxx >=19 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 constrains: - libbrotlicommon 1.2.0 hc919400_1 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping size: 359568 timestamp: 1764018359470 - conda: https://prefix.dev/conda-forge/win-64/brotli-python-1.2.0-py311hc5da9e4_1.conda sha256: 1803c838946d79ef6485ae8c7dafc93e28722c5999b059a34118ef758387a4c9 md5: b0c459f98ac5ea504a9d9df6242f7ee1 depends: - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - libbrotlicommon 1.2.0 hfd05255_1 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping size: 335333 timestamp: 1764018370925 - conda: https://prefix.dev/conda-forge/win-64/brotli-python-1.2.0-py313h3ebfc14_1.conda sha256: 3558006cd6e836de8dff53cbe5f0b9959f96ea6a6776b4e14f1c524916dd956c md5: 916a39a0261621b8c33e9db2366dd427 depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - libbrotlicommon 1.2.0 hfd05255_1 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping size: 335605 timestamp: 1764018132514 - conda: https://prefix.dev/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5 md5: 51a19bba1b8ebfb60df25cde030b7ebc depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: bzip2-1.0.6 license_family: BSD purls: [] size: 260341 timestamp: 1757437258798 - conda: https://prefix.dev/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda sha256: 8f50b58efb29c710f3cecf2027a8d7325ba769ab10c746eff75cea3ac050b10c md5: 97c4b3bd8a90722104798175a1bdddbf depends: - __osx >=10.13 license: bzip2-1.0.6 license_family: BSD purls: [] size: 132607 timestamp: 1757437730085 - conda: https://prefix.dev/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda sha256: b456200636bd5fecb2bec63f7e0985ad2097cf1b83d60ce0b6968dffa6d02aa1 md5: 58fd217444c2a5701a44244faf518206 depends: - __osx >=11.0 license: bzip2-1.0.6 license_family: BSD purls: [] size: 125061 timestamp: 1757437486465 - conda: https://prefix.dev/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda sha256: d882712855624641f48aa9dc3f5feea2ed6b4e6004585d3616386a18186fe692 md5: 1077e9333c41ff0be8edd1a5ec0ddace depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: bzip2-1.0.6 license_family: BSD purls: [] size: 55977 timestamp: 1757437738856 - conda: https://prefix.dev/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda sha256: cc9accf72fa028d31c2a038460787751127317dcfa991f8d1f1babf216bb454e md5: 920bb03579f15389b9e512095ad995b7 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 207882 timestamp: 1765214722852 - conda: https://prefix.dev/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda sha256: 2f5bc0292d595399df0d168355b4e9820affc8036792d6984bd751fdda2bcaea md5: fc9a153c57c9f070bebaa7eef30a8f17 depends: - __osx >=10.13 license: MIT license_family: MIT purls: [] size: 186122 timestamp: 1765215100384 - conda: https://prefix.dev/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda sha256: 2995f2aed4e53725e5efbc28199b46bf311c3cab2648fc4f10c2227d6d5fa196 md5: bcb3cba70cf1eec964a03b4ba7775f01 depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 180327 timestamp: 1765215064054 - conda: https://prefix.dev/conda-forge/win-64/c-ares-1.34.6-hfd05255_0.conda sha256: 5e1e2e24ce279f77e421fcc0e5846c944a8a75f7cf6158427c7302b02984291a md5: 7c6da34e5b6e60b414592c74582e28bf depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 193550 timestamp: 1765215100218 - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-h4c7d964_0.conda sha256: 4ddcb01be03f85d3db9d881407fb13a673372f1b9fac9c836ea441893390e049 md5: 84d389c9eee640dda3d26fc5335c67d8 depends: - __win license: ISC purls: [] size: 147139 timestamp: 1767500904211 - conda: https://prefix.dev/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda sha256: b5974ec9b50e3c514a382335efa81ed02b05906849827a34061c496f4defa0b2 md5: bddacf101bb4dd0e51811cb69c7790e2 depends: - __unix license: ISC purls: [] size: 146519 timestamp: 1767500828366 - conda: https://prefix.dev/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 noarch: python sha256: 561e6660f26c35d137ee150187d89767c988413c978e1b712d53f27ddf70ea17 md5: 9b347a7ec10940d3f7941ff6c460b551 depends: - cached_property >=1.5.2,<1.5.3.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 4134 timestamp: 1615209571450 - conda: https://prefix.dev/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 sha256: 6dbf7a5070cc43d90a1e4c2ec0c541c69d8e30a0e25f50ce9f6e4a432e42c5d7 md5: 576d629e47797577ab0f1b351297ef4a depends: - python >=3.6 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cached-property?source=hash-mapping size: 11065 timestamp: 1615209567874 - conda: https://prefix.dev/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda sha256: 06525fa0c4e4f56e771a3b986d0fdf0f0fc5a3270830ee47e127a5105bde1b9a md5: bb6c4808bfa69d6f7f6b07e5846ced37 depends: - __glibc >=2.17,<3.0.a0 - fontconfig >=2.15.0,<3.0a0 - fonts-conda-ecosystem - icu >=78.1,<79.0a0 - libexpat >=2.7.3,<3.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - libgcc >=14 - libglib >=2.86.3,<3.0a0 - libpng >=1.6.53,<1.7.0a0 - libstdcxx >=14 - libxcb >=1.17.0,<2.0a0 - libzlib >=1.3.1,<2.0a0 - pixman >=0.46.4,<1.0a0 - xorg-libice >=1.1.2,<2.0a0 - xorg-libsm >=1.2.6,<2.0a0 - xorg-libx11 >=1.8.12,<2.0a0 - xorg-libxext >=1.3.6,<2.0a0 - xorg-libxrender >=0.9.12,<0.10.0a0 license: LGPL-2.1-only or MPL-1.1 purls: [] size: 989514 timestamp: 1766415934926 - conda: https://prefix.dev/conda-forge/win-64/cairo-1.18.4-h477c42c_1.conda sha256: 9ee4ad706c5d3e1c6c469785d60e3c2b263eec569be0eac7be33fbaef978bccc md5: 52ea1beba35b69852d210242dd20f97d depends: - fontconfig >=2.15.0,<3.0a0 - fonts-conda-ecosystem - icu >=78.1,<79.0a0 - libexpat >=2.7.3,<3.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - libglib >=2.86.3,<3.0a0 - libpng >=1.6.53,<1.7.0a0 - libzlib >=1.3.1,<2.0a0 - pixman >=0.46.4,<1.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: LGPL-2.1-only or MPL-1.1 purls: [] size: 1537783 timestamp: 1766416059188 - conda: https://prefix.dev/conda-forge/noarch/certifi-2026.1.4-pyhd8ed1ab_0.conda sha256: 110338066d194a715947808611b763857c15458f8b3b97197387356844af9450 md5: eacc711330cd46939f66cd401ff9c44b depends: - python >=3.10 license: ISC purls: - pkg:pypi/certifi?source=compressed-mapping size: 150969 timestamp: 1767500900768 - conda: https://prefix.dev/conda-forge/linux-64/cffi-2.0.0-py311h03d9500_1.conda sha256: 3ad13377356c86d3a945ae30e9b8c8734300925ef81a3cb0a9db0d755afbe7bb md5: 3912e4373de46adafd8f1e97e4bd166b depends: - __glibc >=2.17,<3.0.a0 - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - pycparser - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: MIT license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping size: 303338 timestamp: 1761202960110 - conda: https://prefix.dev/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda sha256: 2162a91819945c826c6ef5efe379e88b1df0fe9a387eeba23ddcf7ebeacd5bd6 md5: d0616e7935acab407d1543b28c446f6f depends: - __glibc >=2.17,<3.0.a0 - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - pycparser - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping size: 298357 timestamp: 1761202966461 - conda: https://prefix.dev/conda-forge/osx-64/cffi-2.0.0-py311h26bcf6e_1.conda sha256: 5519d7a6fb4709454971a9212105b40d95b44b0f1f37ccc2112f45368bfa61b4 md5: 9a3f0928baf6f2754d9d437984c79b00 depends: - __osx >=10.13 - libffi >=3.5.2,<3.6.0a0 - pycparser - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: MIT license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping size: 295108 timestamp: 1761203293287 - conda: https://prefix.dev/conda-forge/osx-64/cffi-2.0.0-py313hf57695f_1.conda sha256: 16c8c80bebe1c3d671382a64beaa16996e632f5b75963379e2b084eb6bc02053 md5: b10f64f2e725afc9bf2d9b30eff6d0ea depends: - __osx >=10.13 - libffi >=3.5.2,<3.6.0a0 - pycparser - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping size: 290946 timestamp: 1761203173891 - conda: https://prefix.dev/conda-forge/osx-arm64/cffi-2.0.0-py311hd10dc20_1.conda sha256: 1ffde698463d6e7ed571bdb85cb17bfc1d3a107c026d20047995512dcc2749ec md5: 4d7f6780e36f18e7601811dddf3bbec5 depends: - __osx >=11.0 - libffi >=3.5.2,<3.6.0a0 - pycparser - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 license: MIT license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping size: 294848 timestamp: 1761203196617 - conda: https://prefix.dev/conda-forge/osx-arm64/cffi-2.0.0-py313h224173a_1.conda sha256: 1fa69651f5e81c25d48ac42064db825ed1a3e53039629db69f86b952f5ce603c md5: 050374657d1c7a4f2ea443c0d0cbd9a0 depends: - __osx >=11.0 - libffi >=3.5.2,<3.6.0a0 - pycparser - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping size: 291376 timestamp: 1761203583358 - conda: https://prefix.dev/conda-forge/win-64/cffi-2.0.0-py311h3485c13_1.conda sha256: c9caca6098e3d92b1a269159b759d757518f2c477fbbb5949cb9fee28807c1f1 md5: f02335db0282d5077df5bc84684f7ff9 depends: - pycparser - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping size: 297941 timestamp: 1761203850323 - conda: https://prefix.dev/conda-forge/win-64/cffi-2.0.0-py313h5ea7bf4_1.conda sha256: f867a11f42bb64a09b232e3decf10f8a8fe5194d7e3a216c6bac9f40483bd1c6 md5: 55b44664f66a2caf584d72196aa98af9 depends: - pycparser - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping size: 292681 timestamp: 1761203203673 - conda: https://prefix.dev/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda sha256: b32f8362e885f1b8417bac2b3da4db7323faa12d5db62b7fd6691c02d60d6f59 md5: a22d1fd9bf98827e280a02875d9a007a depends: - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/charset-normalizer?source=hash-mapping size: 50965 timestamp: 1760437331772 - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda sha256: 38cfe1ee75b21a8361c8824f5544c3866f303af1762693a178266d7f198e8715 md5: ea8a6c3256897cc31263de9f455e25d9 depends: - python >=3.10 - __unix - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/click?source=hash-mapping size: 97676 timestamp: 1764518652276 - conda: https://prefix.dev/conda-forge/noarch/click-8.3.1-pyha7b4d00_1.conda sha256: c3bc9a49930fa1c3383a1485948b914823290efac859a2587ca57a270a652e08 md5: 6cd3ccc98bacfcc92b2bd7f236f01a7e depends: - python >=3.10 - colorama - __win - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/click?source=hash-mapping size: 96620 timestamp: 1764518654675 - conda: https://prefix.dev/conda-forge/noarch/cloudpickle-3.1.2-pyhcf101f3_1.conda sha256: 4c287c2721d8a34c94928be8fe0e9a85754e90189dd4384a31b1806856b50a67 md5: 61b8078a0905b12529abc622406cb62c depends: - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cloudpickle?source=compressed-mapping size: 27353 timestamp: 1765303462831 - conda: https://prefix.dev/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 md5: 962b9857ee8e7018c22f2776ffa0b2d7 depends: - python >=3.9 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/colorama?source=hash-mapping size: 27011 timestamp: 1733218222191 - conda: https://prefix.dev/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda sha256: 576a44729314ad9e4e5ebe055fbf48beb8116b60e58f9070278985b2b634f212 md5: 2da13f2b299d8e1995bafbbe9689a2f7 depends: - python >=3.9 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/comm?source=hash-mapping size: 14690 timestamp: 1753453984907 - conda: https://prefix.dev/conda-forge/linux-64/contourpy-1.3.3-py311h724c32c_4.conda sha256: fd7aca059253cff3d8b0aec71f0c1bf2904823b13f1997bf222aea00a76f3cce md5: d04e508f5a03162c8bab4586a65d00bf depends: - numpy >=1.25 - python - libstdcxx >=14 - libgcc >=14 - __glibc >=2.17,<3.0.a0 - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/contourpy?source=compressed-mapping size: 320553 timestamp: 1769155975008 - conda: https://prefix.dev/conda-forge/linux-64/contourpy-1.3.3-py313hc8edb43_4.conda sha256: 7f86eb205d2d7fcf2c82654a08c6a240623ac34cb406206b4b1f1afa5cda8e49 md5: 33639459bc29437315d4bff9ed5bc7a7 depends: - numpy >=1.25 - python - __glibc >=2.17,<3.0.a0 - libstdcxx >=14 - libgcc >=14 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/contourpy?source=compressed-mapping size: 321850 timestamp: 1769155964333 - conda: https://prefix.dev/conda-forge/osx-64/contourpy-1.3.3-py311h9d13916_4.conda sha256: 4990e8c2418f07b787d764aee3171df4a1c7681050d00e10b4433eed3b997e9d md5: 12f0c1059f868ede7bd3394a1959ae0f depends: - numpy >=1.25 - python - libcxx >=19 - __osx >=10.13 - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/contourpy?source=hash-mapping size: 296923 timestamp: 1769156062903 - conda: https://prefix.dev/conda-forge/osx-64/contourpy-1.3.3-py313h98b818e_4.conda sha256: bb5ae30df17e054668717b46c2053534a8a7d1bc94aedb8d6d22917c59eaa63c md5: 24c06ae9a202f16555c5a1f8006a0bd7 depends: - numpy >=1.25 - python - libcxx >=19 - __osx >=10.13 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/contourpy?source=hash-mapping size: 298562 timestamp: 1769156074957 - conda: https://prefix.dev/conda-forge/osx-arm64/contourpy-1.3.3-py311h7d85929_4.conda sha256: 57b2c28cbb45e7dacb565541483d802a15c6beff5ccdabba19784a526191f4d3 md5: bd91dd35d73638e5c0f520a18850f6ba depends: - numpy >=1.25 - python - python 3.11.* *_cpython - __osx >=11.0 - libcxx >=19 - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/contourpy?source=compressed-mapping size: 286095 timestamp: 1769156091585 - conda: https://prefix.dev/conda-forge/osx-arm64/contourpy-1.3.3-py313h2af2deb_4.conda sha256: 6320cd6c16fdcf25efa493f9a2c54b2687911967a5e90544d599c535535387e9 md5: afd3e394d14e627be0de6e8ee3553dae depends: - numpy >=1.25 - python - libcxx >=19 - __osx >=11.0 - python 3.13.* *_cp313 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/contourpy?source=compressed-mapping size: 286789 timestamp: 1769156187387 - conda: https://prefix.dev/conda-forge/win-64/contourpy-1.3.3-py311h275cad7_4.conda sha256: a903bff178a45cfb89e77a59b33ce54c6cdc7b0e05d2f5355f32e2b8e97ecce1 md5: 9fb1f375c704c5287c97c60f6a88d137 depends: - numpy >=1.25 - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/contourpy?source=hash-mapping size: 244457 timestamp: 1769155974843 - conda: https://prefix.dev/conda-forge/win-64/contourpy-1.3.3-py313h1a38498_4.conda sha256: fb254e7e29535ea0a63b8fba6299f7e4ccd0efcc40750c8cd64e42a0a3b79da7 md5: 726aa233b5e4613e546ca84cd63cbd45 depends: - numpy >=1.25 - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/contourpy?source=compressed-mapping size: 245288 timestamp: 1769155992139 - conda: https://prefix.dev/conda-forge/linux-64/coverage-7.13.2-py311h3778330_0.conda sha256: ebbe8fbe667e871d6a060bf31126f3b91f9f85d9c097f037e79f59b334ef4ca1 md5: b25c1e3463dde575d6701b8dee76d965 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - tomli license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 396161 timestamp: 1769385876916 - conda: https://prefix.dev/conda-forge/linux-64/coverage-7.13.2-py313h3dea7bd_0.conda sha256: 9943483b28bf6443f4012ed4e5b1a1e6315f3bb27017335da8490d435aa07c8b md5: df05169cc886aaf53dc560db634519f8 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - tomli license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=compressed-mapping size: 394739 timestamp: 1769385692708 - conda: https://prefix.dev/conda-forge/linux-64/coverage-7.13.3-py313h3dea7bd_0.conda sha256: 4a0d55462f97301e74292b4495a1c9814f091d2ac2785ba0d203ef88e64d4ded md5: fa90494c873b21b3bdb21c3b588ff043 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - tomli license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 394734 timestamp: 1770134808569 - conda: https://prefix.dev/conda-forge/osx-64/coverage-7.13.2-py311h53ebfaf_0.conda sha256: 3bf269dc40eca55e400446e2be17734f525a8934b904ea52df1b3fb3282587a0 md5: c7f78dfecffa93ff8097af583880be30 depends: - __osx >=10.13 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - tomli license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 397293 timestamp: 1769385806471 - conda: https://prefix.dev/conda-forge/osx-64/coverage-7.13.2-py313h7c6a591_0.conda sha256: 31a2f8e7ab3f328c0bc713d64b86b72ca0580bed57ec4405bbdeef7719440e3d md5: e10ce180a5129664038aa8694792b7ff depends: - __osx >=10.13 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - tomli license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 394238 timestamp: 1769385945216 - conda: https://prefix.dev/conda-forge/osx-64/coverage-7.13.3-py313h7c6a591_0.conda sha256: 31617dfb96edb0f18d3c1c6d342b9151ecacf81dd2109c0800e875241ba818b4 md5: 8e5f49fe8ddcfe86bca9ff13c6e8126c depends: - __osx >=10.13 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - tomli license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 395162 timestamp: 1770134875843 - conda: https://prefix.dev/conda-forge/osx-arm64/coverage-7.13.2-py311hc290fe0_0.conda sha256: 2253b7653ad7ae17a02948b59df956393c8716301dd720aa39cc4073edd10ab7 md5: 8a8c4b7bcd85aa4405020e300ec56f4c depends: - __osx >=11.0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 - tomli license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 396791 timestamp: 1769385686617 - conda: https://prefix.dev/conda-forge/osx-arm64/coverage-7.13.2-py313h65a2061_0.conda sha256: 5f30fb8c9711f18fea52c2ecebbd86c0328795a84aed5bf8cc20c0585297b0c7 md5: 310642d43db19e0bf5e499f29c76a124 depends: - __osx >=11.0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 - tomli license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 395083 timestamp: 1769385793566 - conda: https://prefix.dev/conda-forge/osx-arm64/coverage-7.13.3-py313h65a2061_0.conda sha256: 9a356a08ff3ec15ea9f1ff9279dd6ac3a6a0d6fd8aa1041376a424ac4e098335 md5: 9a29d76b78c885e6a4a6371e0da939f3 depends: - __osx >=11.0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 - tomli license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 393352 timestamp: 1770135375670 - conda: https://prefix.dev/conda-forge/win-64/coverage-7.13.2-py311h3f79411_0.conda sha256: 7dc42e8025e8c163ceb445fc81ede7c041e928d3e2f34fb8d6d8e5b769d0015c md5: 7483b07166c6fad6544dab8709988180 depends: - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - tomli - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 423701 timestamp: 1769385589024 - conda: https://prefix.dev/conda-forge/win-64/coverage-7.13.2-py313hd650c13_0.conda sha256: c822d3d11a87cec7e7662b836f92477a4349e05a33b30591d4080135ecdbd8b7 md5: 0e793d2c02ed116904d51f084ac1850f depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - tomli - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 417412 timestamp: 1769385597617 - conda: https://prefix.dev/conda-forge/win-64/coverage-7.13.3-py313hd650c13_0.conda sha256: 44531cb691e150cd369f2608f21e41b56e01ae6314daf8065a586b775d65114a md5: 61d3901cc9e892d31089d2440ed3783f depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - tomli - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/coverage?source=hash-mapping size: 419101 timestamp: 1770134687284 - conda: https://prefix.dev/conda-forge/noarch/cpython-3.13.11-py313hd8ed1ab_101.conda noarch: generic sha256: f851800da77f360e39235383d685b6e3be4edf28fe233f3bcf09c45293f39ae1 md5: c74a6b9e8694e5122949f611d1552df5 depends: - python >=3.13,<3.14.0a0 - python_abi * *_cp313 license: Python-2.0 purls: [] size: 48249 timestamp: 1769471321757 - conda: https://prefix.dev/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda sha256: bb47aec5338695ff8efbddbc669064a3b10fe34ad881fb8ad5d64fbfa6910ed1 md5: 4c2a8fef270f6c69591889b93f9f55c1 depends: - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cycler?source=hash-mapping size: 14778 timestamp: 1764466758386 - conda: https://prefix.dev/conda-forge/linux-64/cyrus-sasl-2.1.28-hd9c7081_0.conda sha256: ee09ad7610c12c7008262d713416d0b58bf365bc38584dce48950025850bdf3f md5: cae723309a49399d2949362f4ab5c9e4 depends: - __glibc >=2.17,<3.0.a0 - krb5 >=1.21.3,<1.22.0a0 - libgcc >=13 - libntlm >=1.8,<2.0a0 - libstdcxx >=13 - libxcrypt >=4.4.36 - openssl >=3.5.0,<4.0a0 license: BSD-3-Clause-Attribution license_family: BSD purls: [] size: 209774 timestamp: 1750239039316 - conda: https://prefix.dev/conda-forge/linux-64/cytoolz-1.1.0-py311h49ec1c0_1.conda sha256: 8da7cec4fc78ea77fc10e21f273f6f640809c98c18a85c7ad39409c626dcf153 md5: 907579fcaf43b90c8c198ae8d43320ef depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - toolz >=0.10.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cytoolz?source=hash-mapping size: 592174 timestamp: 1760905827335 - conda: https://prefix.dev/conda-forge/linux-64/cytoolz-1.1.0-py313h07c4f96_1.conda sha256: a8ffc7cf31a698a57a46bf7977185ed1e644c5e35d4e166d8f260dca93af6ffb md5: bcca9afd203fe05d9582249ac12762da depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - toolz >=0.10.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cytoolz?source=hash-mapping size: 590435 timestamp: 1760905824293 - conda: https://prefix.dev/conda-forge/osx-64/cytoolz-1.1.0-py311hf197a57_1.conda sha256: 8227734b79e88f22e535cfef336aaef46d74d61dd402513c3bcbdc1719a66be8 md5: 2eb9b4036b9f3098918b25e8243ba76a depends: - __osx >=10.13 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - toolz >=0.10.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cytoolz?source=hash-mapping size: 549561 timestamp: 1760906058328 - conda: https://prefix.dev/conda-forge/osx-64/cytoolz-1.1.0-py313hf050af9_1.conda sha256: e2458af0964417f6ca0be05a82af20647c632362cc319c7a29eb268cef28e897 md5: 9eb5b350c5a60139b32c72bf8695139c depends: - __osx >=10.13 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - toolz >=0.10.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cytoolz?source=hash-mapping size: 555864 timestamp: 1760906288247 - conda: https://prefix.dev/conda-forge/osx-arm64/cytoolz-1.1.0-py311h9408147_1.conda sha256: ff760309c3bd0d49c6adfda56e355184f962e88b01f815ee5494bc6d243d1bb8 md5: 50353c64b5b367b5d22cab7115eb312b depends: - __osx >=11.0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 - toolz >=0.10.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cytoolz?source=hash-mapping size: 547264 timestamp: 1760906350101 - conda: https://prefix.dev/conda-forge/osx-arm64/cytoolz-1.1.0-py313h6535dbc_1.conda sha256: 4b00a25e9bf8b5d702b82dd5c6816d104856845a4e3ea7536abbc90017de7999 md5: cfd9eda010114a19249e394e58704cdb depends: - __osx >=11.0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 - toolz >=0.10.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cytoolz?source=hash-mapping size: 556265 timestamp: 1760906499050 - conda: https://prefix.dev/conda-forge/win-64/cytoolz-1.1.0-py311h3485c13_1.conda sha256: 2f595077cc3938fe70d3d7e21d18c99d27efc55fe5407dbf1ca5409626c41f98 md5: cf54fe91d3c09e6891f39a26cb7cabfc depends: - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - toolz >=0.10.0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cytoolz?source=hash-mapping size: 526010 timestamp: 1760906201247 - conda: https://prefix.dev/conda-forge/win-64/cytoolz-1.1.0-py313h5ea7bf4_1.conda sha256: 3c1e0e7a7d648532e8df97b7fe7b821460eab4011c163e4db686ee8d37db1126 md5: ef2e9ff6d43a07587e3483c34adf6cff depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - toolz >=0.10.0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/cytoolz?source=hash-mapping size: 521155 timestamp: 1760906037897 - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.1-pyhcf101f3_0.conda sha256: cc3a106881051c9a4bdaf05fdf7e175f0d63885b4624728101e7996a0e6e8ae3 md5: a86541105aa7920d2147d48bf370dc08 depends: - python >=3.10 - dask-core >=2026.1.1,<2026.1.2.0a0 - distributed >=2026.1.1,<2026.1.2.0a0 - cytoolz >=0.11.0 - lz4 >=4.3.2 - numpy >=1.24 - pandas >=2.0 - bokeh >=3.1.0 - jinja2 >=2.10.3 - pyarrow >=14.0.1 - python constrains: - openssl !=1.1.1e license: BSD-3-Clause license_family: BSD purls: [] size: 11445 timestamp: 1768579256349 - conda: https://prefix.dev/conda-forge/noarch/dask-2026.1.2-pyhcf101f3_0.conda sha256: 41ed4c27d2a93f6f2c636bbb6615bc8b43d0e7295dbaf89e0c26e777b6197bac md5: f438bd6e7ce6b4d442789f77d3fc7818 depends: - python >=3.10 - dask-core >=2026.1.2,<2026.1.3.0a0 - distributed >=2026.1.2,<2026.1.3.0a0 - cytoolz >=0.11.0 - lz4 >=4.3.2 - numpy >=1.24 - pandas >=2.0 - bokeh >=3.1.0 - jinja2 >=2.10.3 - pyarrow >=14.0.1 - python constrains: - openssl !=1.1.1e license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/dask?source=compressed-mapping size: 11425 timestamp: 1769901592404 - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.1-pyhcf101f3_1.conda sha256: f279cecdcc132861e49c8f779ff3bfd42b8de811ca97b82566b6c7b23a136b11 md5: 91e3b2a0d014ac032c066a2e18051686 depends: - python >=3.10 - click >=8.1 - cloudpickle >=3.0.0 - fsspec >=2021.9.0 - packaging >=20.0 - partd >=1.4.0 - pyyaml >=5.3.1 - toolz >=0.12.0 - importlib-metadata >=4.13.0 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/dask?source=hash-mapping size: 1063503 timestamp: 1768568095009 - conda: https://prefix.dev/conda-forge/noarch/dask-core-2026.1.2-pyhcf101f3_0.conda sha256: c8500be32e2c75b10fd7a0664b0e5abc956dece18a54774a53f357aeabe9e1b6 md5: b20e7ce9afd59036ab194f3d1e27edf5 depends: - python >=3.10 - click >=8.1 - cloudpickle >=3.0.0 - fsspec >=2021.9.0 - packaging >=20.0 - partd >=1.4.0 - pyyaml >=5.3.1 - toolz >=0.12.0 - importlib-metadata >=4.13.0 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/dask?source=hash-mapping size: 1063599 timestamp: 1769829714443 - conda: https://prefix.dev/conda-forge/linux-64/dbus-1.16.2-h24cb091_1.conda sha256: 8bb557af1b2b7983cf56292336a1a1853f26555d9c6cecf1e5b2b96838c9da87 md5: ce96f2f470d39bd96ce03945af92e280 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - libglib >=2.86.2,<3.0a0 - libexpat >=2.7.3,<3.0a0 license: AFL-2.1 OR GPL-2.0-or-later purls: [] size: 447649 timestamp: 1764536047944 - conda: https://prefix.dev/conda-forge/linux-64/debugpy-1.8.20-py313h5d5ffb9_0.conda sha256: 8d76d4eeb5a8e3c5666880b465593fdf4a44f47fbbe89ff5b8f9abbe43026326 md5: e94dbbec2589f3b1d821f43a4bf2ab45 depends: - python - libstdcxx >=14 - libgcc >=14 - __glibc >=2.17,<3.0.a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/debugpy?source=hash-mapping size: 2872698 timestamp: 1769744980407 - conda: https://prefix.dev/conda-forge/osx-64/debugpy-1.8.20-py313h8b5a893_0.conda sha256: 50e6280b8fc3eca1dad3a03deb7bb861c34c61e85331f3ff37f1faed833e968a md5: d97267b6016ad4bfb48874defeab29ea depends: - python - __osx >=10.13 - libcxx >=19 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/debugpy?source=hash-mapping size: 2771547 timestamp: 1769745020308 - conda: https://prefix.dev/conda-forge/osx-arm64/debugpy-1.8.20-py313h1188861_0.conda sha256: 372464b345220758769f49e76d125933008abec7048df4077a851adcc79da1e8 md5: b3a832c19cfa5dfcce7575750ef693ed depends: - python - libcxx >=19 - python 3.13.* *_cp313 - __osx >=11.0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/debugpy?source=hash-mapping size: 2761021 timestamp: 1769744996428 - conda: https://prefix.dev/conda-forge/win-64/debugpy-1.8.20-py313h927ade5_0.conda sha256: f6fe9cbd9e3d3c09f173eeb43676a58bc6169e97da0d190e0201e40828a3a62b md5: 75eb3091b05924429a3a8d2a9bbdfac2 depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/debugpy?source=hash-mapping size: 4003589 timestamp: 1769745018248 - conda: https://prefix.dev/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda sha256: c17c6b9937c08ad63cb20a26f403a3234088e57d4455600974a0ce865cb14017 md5: 9ce473d1d1be1cc3810856a48b3fab32 depends: - python >=3.9 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/decorator?source=hash-mapping size: 14129 timestamp: 1740385067843 - conda: https://prefix.dev/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 sha256: 9717a059677553562a8f38ff07f3b9f61727bd614f505658b0a5ecbcf8df89be md5: 961b3a227b437d82ad7054484cfa71b2 depends: - python >=3.6 license: PSF-2.0 license_family: PSF purls: - pkg:pypi/defusedxml?source=hash-mapping size: 24062 timestamp: 1615232388757 - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.1-pyhcf101f3_1.conda sha256: cc3dc8383c6693e387dba37a7feb360df0c7f3d8c5c11c92f4ca173e9a18476f md5: c15e359a982395be86a7576a91f9c5f5 depends: - python >=3.10 - click >=8.0 - cloudpickle >=3.0.0 - cytoolz >=0.12.0 - dask-core >=2026.1.1,<2026.1.2.0a0 - jinja2 >=2.10.3 - locket >=1.0.0 - msgpack-python >=1.0.2 - packaging >=20.0 - psutil >=5.8.0 - pyyaml >=5.4.1 - sortedcontainers >=2.0.5 - tblib >=1.6.0 - toolz >=0.12.0 - tornado >=6.2.0 - urllib3 >=1.26.5 - zict >=3.0.0 - python constrains: - openssl !=1.1.1e license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/distributed?source=hash-mapping size: 844011 timestamp: 1768575517215 - conda: https://prefix.dev/conda-forge/noarch/distributed-2026.1.2-pyhcf101f3_0.conda sha256: 1cbc2ffaef515c43f37d4684942850e1184956a89b1c0651bb656c81bc11aaa1 md5: 1eac93a6257796dd348d366a85f7f283 depends: - python >=3.10 - click >=8.0 - cloudpickle >=3.0.0 - cytoolz >=0.12.0 - dask-core >=2026.1.2,<2026.1.3.0a0 - jinja2 >=2.10.3 - locket >=1.0.0 - msgpack-python >=1.0.2 - packaging >=20.0 - psutil >=5.8.0 - pyyaml >=5.4.1 - sortedcontainers >=2.0.5 - tblib >=1.6.0 - toolz >=0.12.0 - tornado >=6.2.0 - urllib3 >=1.26.5 - zict >=3.0.0 - python constrains: - openssl !=1.1.1e license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/distributed?source=hash-mapping size: 844862 timestamp: 1769888496327 - conda: https://prefix.dev/conda-forge/noarch/donfig-0.8.1.post1-pyhd8ed1ab_1.conda sha256: d58e97d418f71703e822c422af5b9c431e3621a0ecdc8b0334c1ca33e076dfe7 md5: c56a7fa5597ad78b62e1f5d21f7f8b8f depends: - python >=3.9 - pyyaml license: MIT license_family: MIT purls: - pkg:pypi/donfig?source=hash-mapping size: 22491 timestamp: 1734368817583 - conda: https://prefix.dev/conda-forge/linux-64/double-conversion-3.4.0-hecca717_0.conda sha256: 40cdd1b048444d3235069d75f9c8e1f286db567f6278a93b4f024e5642cfaecc md5: dbe3ec0f120af456b3477743ffd99b74 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 license: BSD-3-Clause license_family: BSD purls: [] size: 71809 timestamp: 1765193127016 - conda: https://prefix.dev/conda-forge/win-64/double-conversion-3.4.0-hac47afa_0.conda sha256: 09e30a170e0da3e9847d449b594b5e55e6ae2852edd3a3680e05753a5e015605 md5: 3d3caf4ccc6415023640af4b1b33060a depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-3-Clause license_family: BSD purls: [] size: 70943 timestamp: 1765193243911 - conda: https://prefix.dev/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144 md5: 8e662bd460bda79b1ea39194e3c4c9ab depends: - python >=3.10 - typing_extensions >=4.6.0 license: MIT and PSF-2.0 purls: - pkg:pypi/exceptiongroup?source=hash-mapping size: 21333 timestamp: 1763918099466 - conda: https://prefix.dev/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda sha256: 1acc6a420efc5b64c384c1f35f49129966f8a12c93b4bb2bdc30079e5dc9d8a8 md5: a57b4be42619213a94f31d2c69c5dda7 depends: - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/execnet?source=hash-mapping size: 39499 timestamp: 1762974150770 - conda: https://prefix.dev/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda sha256: 210c8165a58fdbf16e626aac93cc4c14dbd551a01d1516be5ecad795d2422cad md5: ff9efb7f7469aed3c4a8106ffa29593c depends: - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/executing?source=hash-mapping size: 30753 timestamp: 1756729456476 - pypi: https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl name: filelock version: 3.20.3 sha256: 4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1 requires_python: '>=3.10' - pypi: https://files.pythonhosted.org/packages/1e/c6/ce545d678439fd6a28fa020719d224c08ba50886849a10544402b118e6fb/finch_mlir-0.0.2-cp313-cp313-macosx_11_0_arm64.whl name: finch-mlir version: 0.0.2 sha256: 060137bf11e2f87b5b0e5fd73bebff46ea677d93d0f9e431961bbf4204a59409 - pypi: https://files.pythonhosted.org/packages/2b/2c/29ab596b78a6e3601b499275a1048338804c0eda5a23324e154eb2463e5b/finch_mlir-0.0.2-cp311-cp311-macosx_11_0_x86_64.whl name: finch-mlir version: 0.0.2 sha256: b35d8c15116cf6b2aee5ac6c15922ab38678ede33da85f76be6d6b0b02949587 - pypi: https://files.pythonhosted.org/packages/59/ef/e62c0295ce64fdbaaef5496c15c59c24f2bf88a27c09c6d7f1933db5bdaf/finch_mlir-0.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: finch-mlir version: 0.0.2 sha256: abb166521211e6b4f3c83f5aeb3f621711524a8d5d8889c2d1f559691fd0aa11 - pypi: https://files.pythonhosted.org/packages/63/53/1a8ef274d988c693e80b1225fdaa71a74443932c0761c22464cf4a1d69be/finch_mlir-0.0.2-cp313-cp313-macosx_11_0_x86_64.whl name: finch-mlir version: 0.0.2 sha256: cdc0f19d4808fe4762c0136cb5883b5ad0e23e389a3b3bd0d85fefd4fffccc36 - pypi: https://files.pythonhosted.org/packages/75/4f/3642d809f18857126239398d9fac520ace9e7b9e78958a75e88b021ae0cd/finch_mlir-0.0.2-cp311-cp311-win_amd64.whl name: finch-mlir version: 0.0.2 sha256: b209d24916c9f015470200d9022acd17acb9a6e4915b74ec32d984e27ec59622 - pypi: https://files.pythonhosted.org/packages/bd/c8/cd8cba0b633db2cf2fb9eaf0afe7b0552394bcf2c5b1e206b982ab37dd7d/finch_mlir-0.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: finch-mlir version: 0.0.2 sha256: 25fd818b8c60a884fd495a95bae9aa607cf65c59cf4d1cc97e4adf6529631883 - pypi: https://files.pythonhosted.org/packages/ce/e9/47681764301f53bcb3220ef1b77d328e09c8db33dbd048a7407d983d8618/finch_mlir-0.0.2-cp311-cp311-macosx_11_0_arm64.whl name: finch-mlir version: 0.0.2 sha256: f7dfd413a75738baabd30b5592655f0f3f9f73ea9d88f9bd64edb1fd60fcbfc8 - pypi: https://files.pythonhosted.org/packages/f8/c0/635d9c9e195b6ef6258aab8cae1edb1889e29f93e6a5ee85317f5e7117c6/finch_mlir-0.0.2-cp313-cp313-win_amd64.whl name: finch-mlir version: 0.0.2 sha256: 8fe26a172daae264badf58c9a980149a3034fd73fb7b56b47968f3c1d9a6503f - pypi: https://files.pythonhosted.org/packages/3d/b1/42c7ee1f4af047a236c54467260d7d0d5b7892888568406640c6d62aa0f5/finch_tensor-0.2.14-py3-none-any.whl name: finch-tensor version: 0.2.14 sha256: 772cece64ede30cd87f053f02e8c64bb2b604f20877c4e0195aee961aa0a32a6 requires_dist: - juliacall>=0.9.24,<0.10.0 - juliapkg>=0.1.16,<0.2.0 - numba>=0.61.0 ; extra == 'test' - numpy>=1.19 - pre-commit>=3.6.0,<4 ; extra == 'test' - pytest>=7.4.4,<8 ; extra == 'test' - pytest-cov>=4.1.0,<5 ; extra == 'test' - scipy>=1.7,<2 ; extra == 'test' - sparse>=0.16.0 ; extra == 'test' requires_python: '>=3.11,<4.0' - conda: https://prefix.dev/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b md5: 0c96522c6bdaed4b1566d11387caaf45 license: BSD-3-Clause license_family: BSD purls: [] size: 397370 timestamp: 1566932522327 - conda: https://prefix.dev/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c md5: 34893075a5c9e55cdafac56607368fc6 license: OFL-1.1 license_family: Other purls: [] size: 96530 timestamp: 1620479909603 - conda: https://prefix.dev/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 md5: 4d59c254e01d9cde7957100457e2d5fb license: OFL-1.1 license_family: Other purls: [] size: 700814 timestamp: 1620479612257 - conda: https://prefix.dev/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 md5: 49023d73832ef61042f6a237cb2687e7 license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 license_family: Other purls: [] size: 1620504 timestamp: 1727511233259 - conda: https://prefix.dev/conda-forge/linux-64/fontconfig-2.15.0-h7e30c49_1.conda sha256: 7093aa19d6df5ccb6ca50329ef8510c6acb6b0d8001191909397368b65b02113 md5: 8f5b0b297b59e1ac160ad4beec99dbee depends: - __glibc >=2.17,<3.0.a0 - freetype >=2.12.1,<3.0a0 - libexpat >=2.6.3,<3.0a0 - libgcc >=13 - libuuid >=2.38.1,<3.0a0 - libzlib >=1.3.1,<2.0a0 license: MIT license_family: MIT purls: [] size: 265599 timestamp: 1730283881107 - conda: https://prefix.dev/conda-forge/win-64/fontconfig-2.15.0-h765892d_1.conda sha256: ed122fc858fb95768ca9ca77e73c8d9ddc21d4b2e13aaab5281e27593e840691 md5: 9bb0026a2131b09404c59c4290c697cd depends: - freetype >=2.12.1,<3.0a0 - libexpat >=2.6.3,<3.0a0 - libiconv >=1.17,<2.0a0 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: MIT license_family: MIT purls: [] size: 192355 timestamp: 1730284147944 - conda: https://prefix.dev/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 md5: fee5683a3f04bd15cbd8318b096a27ab depends: - fonts-conda-forge license: BSD-3-Clause license_family: BSD purls: [] size: 3667 timestamp: 1566974674465 - conda: https://prefix.dev/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 md5: a7970cd949a077b7cb9696379d338681 depends: - font-ttf-ubuntu - font-ttf-inconsolata - font-ttf-dejavu-sans-mono - font-ttf-source-code-pro license: BSD-3-Clause license_family: BSD purls: [] size: 4059 timestamp: 1762351264405 - conda: https://prefix.dev/conda-forge/linux-64/fonttools-4.61.1-py313h3dea7bd_0.conda sha256: 97f225199e6e5dfb93f551087c0951fee92db2d29a9dcb6a0346d66bff06fea4 md5: c0f36dfbb130da4f6ce2df31f6b25ea8 depends: - __glibc >=2.17,<3.0.a0 - brotli - libgcc >=14 - munkres - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/fonttools?source=hash-mapping size: 2988776 timestamp: 1765633043435 - conda: https://prefix.dev/conda-forge/osx-64/fonttools-4.61.1-py313h0f4d31d_0.conda sha256: 5375b893af274c09b265e65af8ff49016e0d23c8e03509d830be09eda46585e9 md5: 77978c974cba250d6ee95a4c29aad08e depends: - __osx >=10.13 - brotli - munkres - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/fonttools?source=hash-mapping size: 2949850 timestamp: 1765632894603 - conda: https://prefix.dev/conda-forge/osx-arm64/fonttools-4.61.1-py313h7d74516_0.conda sha256: 52d4aacd7c154adff1f0e86609bf1b0e63b7049c947c4df1e78eedb9f2913091 md5: 894eb0c3e9a17643906a6da3209bf045 depends: - __osx >=11.0 - brotli - munkres - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/fonttools?source=hash-mapping size: 2897709 timestamp: 1765632961717 - conda: https://prefix.dev/conda-forge/win-64/fonttools-4.61.1-py313hd650c13_0.conda sha256: da82b8e843103bf4aaab470e4b8025286357dc8c34cd47817350dcb14ad307fb md5: c6fbf3a96192c26a75ed5755bd904fea depends: - brotli - munkres - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: - pkg:pypi/fonttools?source=hash-mapping size: 2523451 timestamp: 1765632913315 - conda: https://prefix.dev/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda sha256: 2509992ec2fd38ab27c7cdb42cf6cadc566a1cc0d1021a2673475d9fa87c6276 md5: d3549fd50d450b6d9e7dddff25dd2110 depends: - cached-property >=1.3.0 - python >=3.9,<4 license: MPL-2.0 license_family: MOZILLA purls: - pkg:pypi/fqdn?source=hash-mapping size: 16705 timestamp: 1733327494780 - conda: https://prefix.dev/conda-forge/linux-64/freetype-2.14.1-ha770c72_0.conda sha256: bf8e4dffe46f7d25dc06f31038cacb01672c47b9f45201f065b0f4d00ab0a83e md5: 4afc585cd97ba8a23809406cd8a9eda8 depends: - libfreetype 2.14.1 ha770c72_0 - libfreetype6 2.14.1 h73754d4_0 license: GPL-2.0-only OR FTL purls: [] size: 173114 timestamp: 1757945422243 - conda: https://prefix.dev/conda-forge/osx-64/freetype-2.14.1-h694c41f_0.conda sha256: 9f8282510db291496e89618fc66a58a1124fe7a6276fbd57ed18c602ce2576e9 md5: ca641fdf8b7803f4b7212b6d66375930 depends: - libfreetype 2.14.1 h694c41f_0 - libfreetype6 2.14.1 h6912278_0 license: GPL-2.0-only OR FTL purls: [] size: 173969 timestamp: 1757945973505 - conda: https://prefix.dev/conda-forge/osx-arm64/freetype-2.14.1-hce30654_0.conda sha256: 14427aecd72e973a73d5f9dfd0e40b6bc3791d253de09b7bf233f6a9a190fd17 md5: 1ec9a1ee7a2c9339774ad9bb6fe6caec depends: - libfreetype 2.14.1 hce30654_0 - libfreetype6 2.14.1 h6da58f4_0 license: GPL-2.0-only OR FTL purls: [] size: 173399 timestamp: 1757947175403 - conda: https://prefix.dev/conda-forge/win-64/freetype-2.14.1-h57928b3_0.conda sha256: a9b3313edea0bf14ea6147ea43a1059d0bf78771a1336d2c8282891efc57709a md5: d69c21967f35eb2ce7f1f85d6b6022d3 depends: - libfreetype 2.14.1 h57928b3_0 - libfreetype6 2.14.1 hdbac1cb_0 license: GPL-2.0-only OR FTL purls: [] size: 184553 timestamp: 1757946164012 - conda: https://prefix.dev/conda-forge/noarch/fsspec-2026.1.0-pyhd8ed1ab_0.conda sha256: bfba6c280366f48b00a6a7036988fc2bc3fea5ac1d8303152c9da69d72a22936 md5: 1daaf94a304a27ba3446a306235a37ea depends: - python >=3.10 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/fsspec?source=compressed-mapping size: 148116 timestamp: 1768000866082 - conda: https://prefix.dev/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda sha256: 6c33bf0c4d8f418546ba9c250db4e4221040936aef8956353bc764d4877bc39a md5: d411fc29e338efb48c5fd4576d71d881 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - libstdcxx >=13 license: BSD-3-Clause license_family: BSD purls: [] size: 119654 timestamp: 1726600001928 - conda: https://prefix.dev/conda-forge/osx-64/gflags-2.2.2-hac325c4_1005.conda sha256: c0bea66f71a6f4baa8d4f0248e17f65033d558d9e882c0af571b38bcca3e4b46 md5: a26de8814083a6971f14f9c8c3cb36c2 depends: - __osx >=10.13 - libcxx >=17 license: BSD-3-Clause license_family: BSD purls: [] size: 84946 timestamp: 1726600054963 - conda: https://prefix.dev/conda-forge/osx-arm64/gflags-2.2.2-hf9b8971_1005.conda sha256: fd56ed8a1dab72ab90d8a8929b6f916a6d9220ca297ff077f8f04c5ed3408e20 md5: 57a511a5905caa37540eb914dfcbf1fb depends: - __osx >=11.0 - libcxx >=17 license: BSD-3-Clause license_family: BSD purls: [] size: 82090 timestamp: 1726600145480 - conda: https://prefix.dev/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda sha256: 40fdf5a9d5cc7a3503cd0c33e1b90b1e6eab251aaaa74e6b965417d089809a15 md5: 93f742fe078a7b34c29a182958d4d765 depends: - python >=3.9 - python-dateutil >=2.8.1 license: Apache-2.0 license_family: APACHE size: 16538 timestamp: 1734344477841 - conda: https://prefix.dev/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda sha256: dc824dc1d0aa358e28da2ecbbb9f03d932d976c8dca11214aa1dcdfcbd054ba2 md5: ff862eebdfeb2fd048ae9dc92510baca depends: - gflags >=2.2.2,<2.3.0a0 - libgcc-ng >=12 - libstdcxx-ng >=12 license: BSD-3-Clause license_family: BSD purls: [] size: 143452 timestamp: 1718284177264 - conda: https://prefix.dev/conda-forge/osx-64/glog-0.7.1-h2790a97_0.conda sha256: dd56547db8625eb5c91bb0a9fbe8bd6f5c7fbf5b6059d46365e94472c46b24f9 md5: 06cf91665775b0da395229cd4331b27d depends: - __osx >=10.13 - gflags >=2.2.2,<2.3.0a0 - libcxx >=16 license: BSD-3-Clause license_family: BSD purls: [] size: 117017 timestamp: 1718284325443 - conda: https://prefix.dev/conda-forge/osx-arm64/glog-0.7.1-heb240a5_0.conda sha256: 9fc77de416953aa959039db72bc41bfa4600ae3ff84acad04a7d0c1ab9552602 md5: fef68d0a95aa5b84b5c1a4f6f3bf40e1 depends: - __osx >=11.0 - gflags >=2.2.2,<2.3.0a0 - libcxx >=16 license: BSD-3-Clause license_family: BSD purls: [] size: 112215 timestamp: 1718284365403 - conda: https://prefix.dev/conda-forge/linux-64/graphblas-9.4.5-hb61eb52_0.conda sha256: 871e80fd4b3868710724f23b9ec03b4b13f42147d8c6a2986913aecd0045888b md5: c9221ec08b1accd2f5531f371fc334bc depends: - __glibc >=2.17,<3.0.a0 - _openmp_mutex * *_llvm - _openmp_mutex >=4.5 - libgcc >=13 - libstdcxx >=13 - llvm-openmp >=19.1.7 license: Apache-2.0 license_family: Apache purls: [] size: 10947457 timestamp: 1740361915534 - conda: https://prefix.dev/conda-forge/osx-64/graphblas-9.4.5-hb362918_0.conda sha256: 963f4e38429ec0c8b4c792f73b82622a7a7f69a9dfb3b665adaf345bedf655fb md5: 4a4e848bb7a219cd168fc3e1cefec10e depends: - __osx >=10.13 - libcxx >=18 - llvm-openmp >=18.1.8 license: Apache-2.0 license_family: Apache purls: [] size: 7866217 timestamp: 1740361785914 - conda: https://prefix.dev/conda-forge/osx-arm64/graphblas-9.4.5-h22bf013_0.conda sha256: 8276b9fa4e6c00423f8d2e96e989ebb6551e2be4fb7cef52d2adb5bce8e6f9d8 md5: aee00c6d916882c1c0676de0f386c204 depends: - __osx >=11.0 - libcxx >=18 - llvm-openmp >=18.1.8 license: Apache-2.0 license_family: Apache purls: [] size: 6291064 timestamp: 1740361683627 - conda: https://prefix.dev/conda-forge/win-64/graphblas-9.4.5-h1163047_0.conda sha256: cec29980f51e0fe9f1b2c1f4df309921e77d797cefd4497fe2365db50deab599 md5: ebc77bcb337b2323a1f133194ca6fc27 depends: - llvm-openmp >=19.1.7 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: Apache-2.0 license_family: Apache purls: [] size: 5822086 timestamp: 1740363249936 - conda: https://prefix.dev/conda-forge/noarch/graphblas-algorithms-2023.10.0-pyhd8ed1ab_0.conda sha256: 0fdd5f719af12e161b8ffcbe32980e784152653ffbd74d93042f2d23284025ee md5: 34e7057bba18f103f40534a24f0cda25 depends: - python >=3.9 - python-graphblas >=2023.1.0 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/graphblas-algorithms?source=hash-mapping size: 64157 timestamp: 1697686628670 - conda: https://prefix.dev/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda sha256: 25ba37da5c39697a77fce2c9a15e48cf0a84f1464ad2aafbe53d8357a9f6cc8c md5: 2cd94587f3a401ae05e03a6caf09539d depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 license: LGPL-2.0-or-later license_family: LGPL purls: [] size: 99596 timestamp: 1755102025473 - conda: https://prefix.dev/conda-forge/win-64/graphite2-1.3.14-hac47afa_2.conda sha256: 5f1714b07252f885a62521b625898326ade6ca25fbc20727cfe9a88f68a54bfd md5: b785694dd3ec77a011ccf0c24725382b depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: LGPL-2.0-or-later license_family: LGPL purls: [] size: 96336 timestamp: 1755102441729 - conda: https://prefix.dev/conda-forge/noarch/griffe-1.15.0-pyhd8ed1ab_0.conda sha256: 7a42213d6a6dae486c56a835a107fc8704eabf686a2b95adde009e06848426cd md5: 0bc57a76679376b93a489824aa08c294 depends: - colorama >=0.4 - python >=3.10 license: ISC size: 114576 timestamp: 1762806629967 - conda: https://prefix.dev/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda sha256: 96cac6573fd35ae151f4d6979bab6fbc90cb6b1fb99054ba19eb075da9822fcb md5: b8993c19b0c32a2f7b66cbb58ca27069 depends: - python >=3.10 - typing_extensions - python license: MIT license_family: MIT purls: - pkg:pypi/h11?source=compressed-mapping size: 39069 timestamp: 1767729720872 - conda: https://prefix.dev/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 depends: - python >=3.10 - hyperframe >=6.1,<7 - hpack >=4.1,<5 - python license: MIT license_family: MIT purls: - pkg:pypi/h2?source=hash-mapping size: 95967 timestamp: 1756364871835 - conda: https://prefix.dev/conda-forge/linux-64/harfbuzz-12.3.2-h6083320_0.conda sha256: 92015faf283f9c0a8109e2761042cd47ae7a4505e24af42a53bc3767cb249912 md5: d170a70fc1d5c605fcebdf16851bd54a depends: - __glibc >=2.17,<3.0.a0 - cairo >=1.18.4,<2.0a0 - graphite2 >=1.3.14,<2.0a0 - icu >=78.2,<79.0a0 - libexpat >=2.7.3,<3.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - libgcc >=14 - libglib >=2.86.3,<3.0a0 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 license: MIT license_family: MIT purls: [] size: 2035859 timestamp: 1769445400168 - conda: https://prefix.dev/conda-forge/win-64/harfbuzz-12.3.2-h5a1b470_0.conda sha256: f55c689dfb49a3778c2e3369a9103393f6cbd8efc9105753b8e081909dae74dd md5: fb5d7b9527b418f83e3316f3e6daa8a2 depends: - cairo >=1.18.4,<2.0a0 - graphite2 >=1.3.14,<2.0a0 - icu >=78.2,<79.0a0 - libexpat >=2.7.3,<3.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - libglib >=2.86.3,<3.0a0 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: MIT license_family: MIT purls: [] size: 1127522 timestamp: 1769445644521 - conda: https://prefix.dev/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba md5: 0a802cb9888dd14eeefc611f05c40b6e depends: - python >=3.9 license: MIT license_family: MIT purls: - pkg:pypi/hpack?source=hash-mapping size: 30731 timestamp: 1737618390337 - conda: https://prefix.dev/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda sha256: 04d49cb3c42714ce533a8553986e1642d0549a05dc5cc48e0d43ff5be6679a5b md5: 4f14640d58e2cc0aa0819d9d8ba125bb depends: - python >=3.9 - h11 >=0.16 - h2 >=3,<5 - sniffio 1.* - anyio >=4.0,<5.0 - certifi - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/httpcore?source=hash-mapping size: 49483 timestamp: 1745602916758 - conda: https://prefix.dev/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda sha256: cd0f1de3697b252df95f98383e9edb1d00386bfdd03fdf607fa42fe5fcb09950 md5: d6989ead454181f4f9bc987d3dc4e285 depends: - anyio - certifi - httpcore 1.* - idna - python >=3.9 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/httpx?source=hash-mapping size: 63082 timestamp: 1733663449209 - conda: https://prefix.dev/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 md5: 8e6923fc12f1fe8f8c4e5c9f343256ac depends: - python >=3.9 license: MIT license_family: MIT purls: - pkg:pypi/hyperframe?source=hash-mapping size: 17397 timestamp: 1737618427549 - conda: https://prefix.dev/conda-forge/noarch/hypothesis-6.151.5-pyha770c72_0.conda sha256: dc17b5078990fd2c577fbd1f1a8923bd9131391730d9401e7cbdc6516595d353 md5: 7e7674df0b90dafb3d2c45c3a38ac3f5 depends: - attrs >=22.2.0 - click >=7.0 - exceptiongroup >=1.0.0 - python >=3.10 - setuptools - sortedcontainers >=2.1.0,<3.0.0 license: MPL-2.0 purls: - pkg:pypi/hypothesis?source=compressed-mapping size: 386920 timestamp: 1770181684591 - conda: https://prefix.dev/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda sha256: 142a722072fa96cf16ff98eaaf641f54ab84744af81754c292cb81e0881c0329 md5: 186a18e3ba246eccfc7cff00cd19a870 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 license: MIT license_family: MIT purls: [] size: 12728445 timestamp: 1767969922681 - conda: https://prefix.dev/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda sha256: d4cefbca587429d1192509edc52c88de52bc96c2447771ddc1f8bee928aed5ef md5: 1e93aca311da0210e660d2247812fa02 depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 12358010 timestamp: 1767970350308 - conda: https://prefix.dev/conda-forge/win-64/icu-78.2-h637d24d_0.conda sha256: 5a41fb28971342e293769fc968b3414253a2f8d9e30ed7c31517a15b4887246a md5: 0ee3bb487600d5e71ab7d28951b2016a depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 13222158 timestamp: 1767970128854 - conda: https://prefix.dev/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 md5: 53abe63df7e10a6ba605dc5f9f961d36 depends: - python >=3.10 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/idna?source=hash-mapping size: 50721 timestamp: 1760286526795 - conda: https://prefix.dev/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda sha256: c18ab120a0613ada4391b15981d86ff777b5690ca461ea7e9e49531e8f374745 md5: 63ccfdc3a3ce25b027b8767eb722fca8 depends: - python >=3.9 - zipp >=3.20 - python license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/importlib-metadata?source=hash-mapping size: 34641 timestamp: 1747934053147 - conda: https://prefix.dev/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda sha256: e1a9e3b1c8fe62dc3932a616c284b5d8cbe3124bbfbedcf4ce5c828cb166ee19 md5: 9614359868482abba1bd15ce465e3c42 depends: - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/iniconfig?source=compressed-mapping size: 13387 timestamp: 1760831448842 - conda: https://prefix.dev/conda-forge/noarch/ipykernel-6.31.0-pyh5552912_0.conda sha256: 4eb35a7f81d43800c7d18b27c0fff9a2f23372839ac907ad116c24edcea6ab19 md5: c83fa42af2cd5b2d4576d4501dad6232 depends: - appnope - __osx - comm >=0.1.1 - debugpy >=1.6.5 - ipython >=7.23.1 - jupyter_client >=8.0.0 - jupyter_core >=4.12,!=5.0.* - matplotlib-inline >=0.1 - nest-asyncio >=1.4 - packaging >=22 - psutil >=5.7 - python >=3.10 - pyzmq >=25 - tornado >=6.2 - traitlets >=5.4.0 - python constrains: - appnope >=0.1.2 license: BSD-3-Clause license_family: BSD size: 128210 timestamp: 1760967038077 - conda: https://prefix.dev/conda-forge/noarch/ipykernel-6.31.0-pyh6dadd2b_0.conda sha256: 620bed30fed3942e52f63f0e7a9effdcaacf4aa2214145e052f3af143f211dec md5: 192487fef6ebc9f726eaffb119a84286 depends: - python - __win - comm >=0.1.1 - debugpy >=1.6.5 - ipython >=7.23.1 - jupyter_client >=8.0.0 - jupyter_core >=4.12,!=5.0.* - matplotlib-inline >=0.1 - nest-asyncio >=1.4 - packaging >=22 - psutil >=5.7 - python >=3.10 - pyzmq >=25 - tornado >=6.2 - traitlets >=5.4.0 - python constrains: - appnope >=0.1.2 license: BSD-3-Clause license_family: BSD size: 128350 timestamp: 1760967073264 - conda: https://prefix.dev/conda-forge/noarch/ipykernel-6.31.0-pyha191276_0.conda sha256: 35477c6ca12f48c3af0cbca01f65065dcc37c4a306886d6237e309e041b8434b md5: d29c9fbbd0c41a7d4fbc5629314f3b00 depends: - python - __linux - comm >=0.1.1 - debugpy >=1.6.5 - ipython >=7.23.1 - jupyter_client >=8.0.0 - jupyter_core >=4.12,!=5.0.* - matplotlib-inline >=0.1 - nest-asyncio >=1.4 - packaging >=22 - psutil >=5.7 - python >=3.10 - pyzmq >=25 - tornado >=6.2 - traitlets >=5.4.0 - python constrains: - appnope >=0.1.2 license: BSD-3-Clause license_family: BSD size: 129645 timestamp: 1760967030510 - conda: https://prefix.dev/conda-forge/noarch/ipykernel-7.1.0-pyh5552912_0.conda sha256: b5f7eaba3bb109be49d00a0a8bda267ddf8fa66cc1b54fc5944529ed6f3e8503 md5: 1849eec35b60082d2bd66b4e36dec2b6 depends: - appnope - __osx - comm >=0.1.1 - debugpy >=1.6.5 - ipython >=7.23.1 - jupyter_client >=8.0.0 - jupyter_core >=4.12,!=5.0.* - matplotlib-inline >=0.1 - nest-asyncio >=1.4 - packaging >=22 - psutil >=5.7 - python >=3.10 - pyzmq >=25 - tornado >=6.2 - traitlets >=5.4.0 - python constrains: - appnope >=0.1.2 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/ipykernel?source=hash-mapping size: 132289 timestamp: 1761567969884 - conda: https://prefix.dev/conda-forge/noarch/ipykernel-7.1.0-pyh6dadd2b_0.conda sha256: 75e42103bc3350422896f727041e24767795b214a20f50bf39c371626b8aae8b md5: f22cb16c5ad68fd33d0f65c8739b6a06 depends: - python - __win - comm >=0.1.1 - debugpy >=1.6.5 - ipython >=7.23.1 - jupyter_client >=8.0.0 - jupyter_core >=4.12,!=5.0.* - matplotlib-inline >=0.1 - nest-asyncio >=1.4 - packaging >=22 - psutil >=5.7 - python >=3.10 - pyzmq >=25 - tornado >=6.2 - traitlets >=5.4.0 - python constrains: - appnope >=0.1.2 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/ipykernel?source=hash-mapping size: 132418 timestamp: 1761567966860 - conda: https://prefix.dev/conda-forge/noarch/ipykernel-7.1.0-pyha191276_0.conda sha256: a9d6b74115dbd62e19017ff8fa4885b07b5164427f262cc15b5307e5aaf3ee73 md5: c6f63cfe66adaa5650788e3106b6683a depends: - python - __linux - comm >=0.1.1 - debugpy >=1.6.5 - ipython >=7.23.1 - jupyter_client >=8.0.0 - jupyter_core >=4.12,!=5.0.* - matplotlib-inline >=0.1 - nest-asyncio >=1.4 - packaging >=22 - psutil >=5.7 - python >=3.10 - pyzmq >=25 - tornado >=6.2 - traitlets >=5.4.0 - python constrains: - appnope >=0.1.2 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/ipykernel?source=hash-mapping size: 133820 timestamp: 1761567932044 - conda: https://prefix.dev/conda-forge/noarch/ipython-9.9.0-pyh53cf698_0.conda sha256: 4ff1733c59b72cf0c8ed9ddb6e948e99fc6b79b76989282c0c7a46aab56e6176 md5: 8481978caa2f108e6ddbf8008a345546 depends: - __unix - pexpect >4.3 - decorator >=4.3.2 - ipython_pygments_lexers >=1.0.0 - jedi >=0.18.1 - matplotlib-inline >=0.1.5 - prompt-toolkit >=3.0.41,<3.1.0 - pygments >=2.11.0 - python >=3.11 - stack_data >=0.6.0 - traitlets >=5.13.0 - typing_extensions >=4.6 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/ipython?source=compressed-mapping size: 646242 timestamp: 1767621166614 - conda: https://prefix.dev/conda-forge/noarch/ipython-9.9.0-pyhe2676ad_0.conda sha256: 1697fae5859f61938ab44af38126115ad18fc059462bb370c5f8740d7bc4a803 md5: fe785355648dec69d2f06fa14c9e6e84 depends: - __win - colorama >=0.4.4 - decorator >=4.3.2 - ipython_pygments_lexers >=1.0.0 - jedi >=0.18.1 - matplotlib-inline >=0.1.5 - prompt-toolkit >=3.0.41,<3.1.0 - pygments >=2.11.0 - python >=3.11 - stack_data >=0.6.0 - traitlets >=5.13.0 - typing_extensions >=4.6 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/ipython?source=compressed-mapping size: 645119 timestamp: 1767621201570 - conda: https://prefix.dev/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda sha256: 894682a42a7d659ae12878dbcb274516a7031bbea9104e92f8e88c1f2765a104 md5: bd80ba060603cc228d9d81c257093119 depends: - pygments - python >=3.9 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/ipython-pygments-lexers?source=hash-mapping size: 13993 timestamp: 1737123723464 - conda: https://prefix.dev/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda sha256: 08e838d29c134a7684bca0468401d26840f41c92267c4126d7b43a6b533b0aed md5: 0b0154421989637d424ccf0f104be51a depends: - arrow >=0.15.0 - python >=3.9 license: MIT license_family: MIT purls: - pkg:pypi/isoduration?source=hash-mapping size: 19832 timestamp: 1733493720346 - conda: https://prefix.dev/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda sha256: 92c4d217e2dc68983f724aa983cca5464dcb929c566627b26a2511159667dba8 md5: a4f4c5dc9b80bc50e0d3dc4e6e8f1bd9 depends: - parso >=0.8.3,<0.9.0 - python >=3.9 license: Apache-2.0 AND MIT purls: - pkg:pypi/jedi?source=hash-mapping size: 843646 timestamp: 1733300981994 - conda: https://prefix.dev/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b md5: 04558c96691bed63104678757beb4f8d depends: - markupsafe >=2.0 - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jinja2?source=compressed-mapping size: 120685 timestamp: 1764517220861 - conda: https://prefix.dev/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda sha256: 301539229d7be6420c084490b8145583291123f0ce6b92f56be5948a2c83a379 md5: 615de2a4d97af50c350e5cf160149e77 depends: - python >=3.10 - setuptools license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/joblib?source=hash-mapping size: 226448 timestamp: 1765794135253 - conda: https://prefix.dev/conda-forge/noarch/json5-0.13.0-pyhd8ed1ab_0.conda sha256: ba03ca5a6db38d9f48bd30172e8c512dea7a686a5c7701c6fcdb7b3023dae2ad md5: 8d5f66ebf832c4ce28d5c37a0e76605c depends: - python >=3.10 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/json5?source=hash-mapping size: 34017 timestamp: 1767325114901 - conda: https://prefix.dev/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda sha256: 1a1328476d14dfa8b84dbacb7f7cd7051c175498406dc513ca6c679dc44f3981 md5: cd2214824e36b0180141d422aba01938 depends: - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jsonpointer?source=hash-mapping size: 13967 timestamp: 1765026384757 - conda: https://prefix.dev/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 md5: ada41c863af263cc4c5fcbaff7c3e4dc depends: - attrs >=22.2.0 - jsonschema-specifications >=2023.3.6 - python >=3.10 - referencing >=0.28.4 - rpds-py >=0.25.0 - python license: MIT license_family: MIT purls: - pkg:pypi/jsonschema?source=compressed-mapping size: 82356 timestamp: 1767839954256 - conda: https://prefix.dev/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 md5: 439cd0f567d697b20a8f45cb70a1005a depends: - python >=3.10 - referencing >=0.31.0 - python license: MIT license_family: MIT purls: - pkg:pypi/jsonschema-specifications?source=hash-mapping size: 19236 timestamp: 1757335715225 - conda: https://prefix.dev/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda sha256: 6886fc61e4e4edd38fd38729976b134e8bd2143f7fce56cc80d7ac7bac99bce1 md5: 8368d58342d0825f0843dc6acdd0c483 depends: - jsonschema >=4.26.0,<4.26.1.0a0 - fqdn - idna - isoduration - jsonpointer >1.13 - rfc3339-validator - rfc3986-validator >0.1.0 - rfc3987-syntax >=1.1.0 - uri-template - webcolors >=24.6.0 license: MIT license_family: MIT purls: [] size: 4740 timestamp: 1767839954258 - pypi: https://files.pythonhosted.org/packages/14/1d/d6d77bd84c5261a5cbcb17e5000527d0f895e512545bd442caf28a7e3336/juliacall-0.9.31-py3-none-any.whl name: juliacall version: 0.9.31 sha256: 171dd97489a855336558c49fea2eb26dcbeb1ddb1344acaddf99fff2a5a1b9ad requires_dist: - juliapkg>=0.1.21,<0.2 requires_python: '>=3.10,<4' - pypi: https://files.pythonhosted.org/packages/39/6e/361d176cc94ccb8aac22a39677e146a91406005f8f6bb098b15606c523f6/juliapkg-0.1.22-py3-none-any.whl name: juliapkg version: 0.1.22 sha256: fc197c21087345e296036190c769b888f7701bf1fb47d7036a20d01221ec550a requires_dist: - filelock>=3.16,<4.0 - semver>=3.0,<4.0 - tomli>=2.0,<3.0 - tomlkit>=0.13.3,<0.14 - click>=8.0,<9.0 ; extra == 'cli' requires_python: '>=3.9' - conda: https://prefix.dev/conda-forge/linux-64/juliaup-1.19.4-hdab8a38_0.conda sha256: cdeb24faf31e3901c24d6ffe9d23becef25ad579eb78ef908a0ea1f5e2939c47 md5: e7798f9a875be2698d0ab463a2d3bfa9 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 constrains: - __glibc >=2.17 license: MIT license_family: MIT purls: [] size: 3483133 timestamp: 1769253944261 - conda: https://prefix.dev/conda-forge/osx-64/juliaup-1.19.4-hb64060d_0.conda sha256: 31aab26b66a0d1dec2643f347d80969cf23a98bc39db86958b60820648164509 md5: 2eed7eec65c8e87dccecaa442bd1bfdb depends: - __osx >=10.15 constrains: - __osx >=10.13 license: MIT license_family: MIT purls: [] size: 2262916 timestamp: 1769254230563 - conda: https://prefix.dev/conda-forge/osx-arm64/juliaup-1.19.4-h748bcf4_0.conda sha256: 986406eaeef96af3c3d9c7aa9f433e51a92781b7b6af3828be4a7d1a6e37fa00 md5: 327f93c8f6a0c2be8b2552467426958c depends: - __osx >=11.0 constrains: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 2185757 timestamp: 1769254126725 - conda: https://prefix.dev/conda-forge/win-64/juliaup-1.19.4-h77a83cd_0.conda sha256: 870656f641591ac06f1ae265d274e8af8161f8829bfb91916c60b25be9f6f6c7 md5: dfc99d65d509715fea7d75a67058545d depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 1659419 timestamp: 1769254269177 - conda: https://prefix.dev/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.conda sha256: 897ad2e2c2335ef3c2826d7805e16002a1fd0d509b4ae0bc66617f0e0ff07bc2 md5: 62b7c96c6cd77f8173cc5cada6a9acaa depends: - importlib-metadata >=4.8.3 - jupyter_server >=1.1.2 - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyter-lsp?source=hash-mapping size: 60377 timestamp: 1756388269267 - conda: https://prefix.dev/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda sha256: e402bd119720862a33229624ec23645916a7d47f30e1711a4af9e005162b84f3 md5: 8a3d6d0523f66cf004e563a50d9392b3 depends: - jupyter_core >=5.1 - python >=3.10 - python-dateutil >=2.8.2 - pyzmq >=25.0 - tornado >=6.4.1 - traitlets >=5.3 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyter-client?source=compressed-mapping size: 112785 timestamp: 1767954655912 - conda: https://prefix.dev/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda sha256: ed709a6c25b731e01563521ef338b93986cd14b5bc17f35e9382000864872ccc md5: a8db462b01221e9f5135be466faeb3e0 depends: - __win - pywin32 - platformdirs >=2.5 - python >=3.10 - traitlets >=5.3 - python constrains: - pywin32 >=300 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyter-core?source=hash-mapping size: 64679 timestamp: 1760643889625 - conda: https://prefix.dev/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda sha256: 1d34b80e5bfcd5323f104dbf99a2aafc0e5d823019d626d0dce5d3d356a2a52a md5: b38fe4e78ee75def7e599843ef4c1ab0 depends: - __unix - python - platformdirs >=2.5 - python >=3.10 - traitlets >=5.3 - python constrains: - pywin32 >=300 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyter-core?source=hash-mapping size: 65503 timestamp: 1760643864586 - conda: https://prefix.dev/conda-forge/noarch/jupyter_events-0.12.0-pyh29332c3_0.conda sha256: 37e6ac3ccf7afcc730c3b93cb91a13b9ae827fd306f35dd28f958a74a14878b5 md5: f56000b36f09ab7533877e695e4e8cb0 depends: - jsonschema-with-format-nongpl >=4.18.0 - packaging - python >=3.9 - python-json-logger >=2.0.4 - pyyaml >=5.3 - referencing - rfc3339-validator - rfc3986-validator >=0.1.1 - traitlets >=5.3 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyter-events?source=hash-mapping size: 23647 timestamp: 1738765986736 - conda: https://prefix.dev/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda sha256: 74c4e642be97c538dae1895f7052599dfd740d8bd251f727bce6453ce8d6cd9a md5: d79a87dcfa726bcea8e61275feed6f83 depends: - anyio >=3.1.0 - argon2-cffi >=21.1 - jinja2 >=3.0.3 - jupyter_client >=7.4.4 - jupyter_core >=4.12,!=5.0.* - jupyter_events >=0.11.0 - jupyter_server_terminals >=0.4.4 - nbconvert-core >=6.4.4 - nbformat >=5.3.0 - overrides >=5.0 - packaging >=22.0 - prometheus_client >=0.9 - python >=3.10 - pyzmq >=24 - send2trash >=1.8.2 - terminado >=0.8.3 - tornado >=6.2.0 - traitlets >=5.6.0 - websocket-client >=1.7 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyter-server?source=hash-mapping size: 347094 timestamp: 1755870522134 - conda: https://prefix.dev/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda sha256: 5eda79ed9f53f590031d29346abd183051263227dd9ee667b5ca1133ce297654 md5: 7b8bace4943e0dc345fc45938826f2b8 depends: - python >=3.10 - terminado >=0.8.3 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyter-server-terminals?source=hash-mapping size: 22052 timestamp: 1768574057200 - conda: https://prefix.dev/conda-forge/noarch/jupyterlab-4.5.3-pyhd8ed1ab_0.conda sha256: 18b5bff46717023ef5e81ae6ba71b254c1aca474db32c6dc21897c46ea26fa75 md5: 106f4e36e14797b9c2abfc3849d9e92f depends: - async-lru >=1.0.0 - httpx >=0.25.0,<1 - ipykernel >=6.5.0,!=6.30.0 - jinja2 >=3.0.3 - jupyter-lsp >=2.0.0 - jupyter_core - jupyter_server >=2.4.0,<3 - jupyterlab_server >=2.28.0,<3 - notebook-shim >=0.2 - packaging - python >=3.10 - setuptools >=41.1.0 - tomli >=1.2.2 - tornado >=6.2.0 - traitlets license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyterlab?source=compressed-mapping size: 8554335 timestamp: 1769190054941 - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda sha256: dc24b900742fdaf1e077d9a3458fd865711de80bca95fe3c6d46610c532c6ef0 md5: fd312693df06da3578383232528c468d depends: - pygments >=2.4.1,<3 - python >=3.9 constrains: - jupyterlab >=4.0.8,<5.0.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyterlab-pygments?source=hash-mapping size: 18711 timestamp: 1733328194037 - conda: https://prefix.dev/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda sha256: 381d2d6a259a3be5f38a69463e0f6c5dcf1844ae113058007b51c3bef13a7cee md5: a63877cb23de826b1620d3adfccc4014 depends: - babel >=2.10 - jinja2 >=3.0.3 - json5 >=0.9.0 - jsonschema >=4.18 - jupyter_server >=1.21,<3 - packaging >=21.3 - python >=3.10 - requests >=2.31 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyterlab-server?source=hash-mapping size: 51621 timestamp: 1761145478692 - conda: https://prefix.dev/conda-forge/noarch/jupytext-1.19.1-pyhbbac1ac_0.conda sha256: 1027cf4d0eb0c40f36de9e9b78bcdc7edc17b62ff9e7a20ad6bc81422f30713c md5: d8f030e3730713c93a358fdb46f08281 depends: - markdown-it-py >=1.0 - mdit-py-plugins - nbformat - packaging - python >=3.10 - pyyaml - tomli license: MIT license_family: MIT size: 113306 timestamp: 1769455798581 - conda: https://prefix.dev/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 md5: b38117a3c920364aff79f870c984b4a3 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 license: LGPL-2.1-or-later purls: [] size: 134088 timestamp: 1754905959823 - conda: https://prefix.dev/conda-forge/linux-64/kiwisolver-1.4.9-py313hc8edb43_2.conda sha256: 60d7d525db89401f88f5c91bdbb79d3afbf005e7d7c1326318659fa097607e51 md5: 3e0e65595330e26515e31b7fc6d933c7 depends: - python - __glibc >=2.17,<3.0.a0 - libstdcxx >=14 - libgcc >=14 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/kiwisolver?source=hash-mapping size: 77616 timestamp: 1762488778882 - conda: https://prefix.dev/conda-forge/osx-64/kiwisolver-1.4.9-py313ha1c5e85_2.conda sha256: 011e58aac5a2c0e22643b81339c3f35bff7ec52c46ef403ced227ac87aaab313 md5: cadc416f7c960ce1436bb6cc8a0f75e4 depends: - python - __osx >=10.13 - libcxx >=19 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/kiwisolver?source=hash-mapping size: 69575 timestamp: 1762488825063 - conda: https://prefix.dev/conda-forge/osx-arm64/kiwisolver-1.4.9-py313h7add70c_2.conda sha256: adc6b89070b6858b81fbe24dd034a73295e8fa9ccb68ed871bf04f1ed498f51c md5: 9583687276aaa393e723f3b7970be69f depends: - python - libcxx >=19 - python 3.13.* *_cp313 - __osx >=11.0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/kiwisolver?source=hash-mapping size: 68438 timestamp: 1762488945877 - conda: https://prefix.dev/conda-forge/win-64/kiwisolver-1.4.9-py313h1a38498_2.conda sha256: 40eafae7e9cdbe97eeb56ab0882816d3f68a2af4080a822f7349f986de2adeb6 md5: f77249adfa3f0091e016610346affd09 depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/kiwisolver?source=hash-mapping size: 73825 timestamp: 1762488792613 - conda: https://prefix.dev/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda sha256: 99df692f7a8a5c27cd14b5fb1374ee55e756631b9c3d659ed3ee60830249b238 md5: 3f43953b7d3fb3aaa1d0d0723d91e368 depends: - keyutils >=1.6.1,<2.0a0 - libedit >=3.1.20191231,<3.2.0a0 - libedit >=3.1.20191231,<4.0a0 - libgcc-ng >=12 - libstdcxx-ng >=12 - openssl >=3.3.1,<4.0a0 license: MIT license_family: MIT purls: [] size: 1370023 timestamp: 1719463201255 - conda: https://prefix.dev/conda-forge/osx-64/krb5-1.21.3-h37d8d59_0.conda sha256: 83b52685a4ce542772f0892a0f05764ac69d57187975579a0835ff255ae3ef9c md5: d4765c524b1d91567886bde656fb514b depends: - __osx >=10.13 - libcxx >=16 - libedit >=3.1.20191231,<3.2.0a0 - libedit >=3.1.20191231,<4.0a0 - openssl >=3.3.1,<4.0a0 license: MIT license_family: MIT purls: [] size: 1185323 timestamp: 1719463492984 - conda: https://prefix.dev/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda sha256: 4442f957c3c77d69d9da3521268cad5d54c9033f1a73f99cde0a3658937b159b md5: c6dc8a0fdec13a0565936655c33069a1 depends: - __osx >=11.0 - libcxx >=16 - libedit >=3.1.20191231,<3.2.0a0 - libedit >=3.1.20191231,<4.0a0 - openssl >=3.3.1,<4.0a0 license: MIT license_family: MIT purls: [] size: 1155530 timestamp: 1719463474401 - conda: https://prefix.dev/conda-forge/win-64/krb5-1.21.3-hdf4eb48_0.conda sha256: 18e8b3430d7d232dad132f574268f56b3eb1a19431d6d5de8c53c29e6c18fa81 md5: 31aec030344e962fbd7dbbbbd68e60a9 depends: - openssl >=3.3.1,<4.0a0 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: MIT license_family: MIT purls: [] size: 712034 timestamp: 1719463874284 - conda: https://prefix.dev/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda sha256: 49570840fb15f5df5d4b4464db8ee43a6d643031a2bc70ef52120a52e3809699 md5: 9b965c999135d43a3d0f7bd7d024e26a depends: - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/lark?source=compressed-mapping size: 94312 timestamp: 1761596921009 - conda: https://prefix.dev/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda sha256: 836ec4b895352110335b9fdcfa83a8dcdbe6c5fb7c06c4929130600caea91c0a md5: 6f2e2c8f58160147c4d1c6f4c14cbac4 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libjpeg-turbo >=3.1.2,<4.0a0 - libtiff >=4.7.1,<4.8.0a0 license: MIT license_family: MIT purls: [] size: 249959 timestamp: 1768184673131 - conda: https://prefix.dev/conda-forge/osx-64/lcms2-2.18-h90db99b_0.conda sha256: 3ec16c491425999a8461e1b7c98558060a4645a20cf4c9ac966103c724008cc2 md5: 753acc10c7277f953f168890e5397c80 depends: - __osx >=10.13 - libjpeg-turbo >=3.1.2,<4.0a0 - libtiff >=4.7.1,<4.8.0a0 license: MIT license_family: MIT purls: [] size: 226870 timestamp: 1768184917403 - conda: https://prefix.dev/conda-forge/osx-arm64/lcms2-2.18-hdfa7624_0.conda sha256: d768da024ab74a4b30642401877fa914a68bdc238667f16b1ec2e0e98b2451a6 md5: 6631a7bd2335bb9699b1dbc234b19784 depends: - __osx >=11.0 - libjpeg-turbo >=3.1.2,<4.0a0 - libtiff >=4.7.1,<4.8.0a0 license: MIT license_family: MIT purls: [] size: 211756 timestamp: 1768184994800 - conda: https://prefix.dev/conda-forge/win-64/lcms2-2.18-hf2c6c5f_0.conda sha256: 7eeb18c5c86db146b62da66d9e8b0e753a52987f9134a494309588bbeceddf28 md5: b6c68d6b829b044cd17a41e0a8a23ca1 depends: - libjpeg-turbo >=3.1.2,<4.0a0 - libtiff >=4.7.1,<4.8.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 522238 timestamp: 1768184858107 - conda: https://prefix.dev/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda sha256: 1027bd8aa0d5144e954e426ab6218fd5c14e54a98f571985675468b339c808ca md5: 3ec0aa5037d39b06554109a01e6fb0c6 depends: - __glibc >=2.17,<3.0.a0 - zstd >=1.5.7,<1.6.0a0 constrains: - binutils_impl_linux-64 2.45 license: GPL-3.0-only license_family: GPL purls: [] size: 730831 timestamp: 1766513089214 - conda: https://prefix.dev/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda sha256: 412381a43d5ff9bbed82cd52a0bbca5b90623f62e41007c9c42d3870c60945ff md5: 9344155d33912347b37f0ae6c410a835 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - libstdcxx >=13 license: Apache-2.0 license_family: Apache purls: [] size: 264243 timestamp: 1745264221534 - conda: https://prefix.dev/conda-forge/osx-64/lerc-4.0.0-hcca01a6_1.conda sha256: cc1f1d7c30aa29da4474ec84026ec1032a8df1d7ec93f4af3b98bb793d01184e md5: 21f765ced1a0ef4070df53cb425e1967 depends: - __osx >=10.13 - libcxx >=18 license: Apache-2.0 license_family: Apache purls: [] size: 248882 timestamp: 1745264331196 - conda: https://prefix.dev/conda-forge/osx-arm64/lerc-4.0.0-hd64df32_1.conda sha256: 12361697f8ffc9968907d1a7b5830e34c670e4a59b638117a2cdfed8f63a38f8 md5: a74332d9b60b62905e3d30709df08bf1 depends: - __osx >=11.0 - libcxx >=18 license: Apache-2.0 license_family: Apache purls: [] size: 188306 timestamp: 1745264362794 - conda: https://prefix.dev/conda-forge/win-64/lerc-4.0.0-h6470a55_1.conda sha256: 868a3dff758cc676fa1286d3f36c3e0101cca56730f7be531ab84dc91ec58e9d md5: c1b81da6d29a14b542da14a36c9fbf3f depends: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: Apache-2.0 license_family: Apache purls: [] size: 164701 timestamp: 1745264384716 - conda: https://prefix.dev/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda sha256: dcd1429a1782864c452057a6c5bc1860f2b637dc20a2b7e6eacd57395bbceff8 md5: 83b160d4da3e1e847bf044997621ed63 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - libstdcxx >=13 constrains: - libabseil-static =20250512.1=cxx17* - abseil-cpp =20250512.1 license: Apache-2.0 license_family: Apache purls: [] size: 1310612 timestamp: 1750194198254 - conda: https://prefix.dev/conda-forge/osx-64/libabseil-20250512.1-cxx17_hfc00f1c_0.conda sha256: a878efebf62f039a1f1733c1e150a75a99c7029ece24e34efdf23d56256585b1 md5: ddf1acaed2276c7eb9d3c76b49699a11 depends: - __osx >=10.13 - libcxx >=18 constrains: - abseil-cpp =20250512.1 - libabseil-static =20250512.1=cxx17* license: Apache-2.0 license_family: Apache purls: [] size: 1162435 timestamp: 1750194293086 - conda: https://prefix.dev/conda-forge/osx-arm64/libabseil-20250512.1-cxx17_hd41c47c_0.conda sha256: 7f0ee9ae7fa2cf7ac92b0acf8047c8bac965389e48be61bf1d463e057af2ea6a md5: 360dbb413ee2c170a0a684a33c4fc6b8 depends: - __osx >=11.0 - libcxx >=18 constrains: - libabseil-static =20250512.1=cxx17* - abseil-cpp =20250512.1 license: Apache-2.0 license_family: Apache purls: [] size: 1174081 timestamp: 1750194620012 - conda: https://prefix.dev/conda-forge/win-64/libabseil-20250512.1-cxx17_habfad5f_0.conda sha256: 78790771f44e146396d9ae92efbe1022168295afd8d174f653a1fa16f0f0fa32 md5: d6a4cd236fc1c69a1cfc9698fb5e391f depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.42.34438 constrains: - libabseil-static =20250512.1=cxx17* - abseil-cpp =20250512.1 license: Apache-2.0 license_family: Apache purls: [] size: 1615210 timestamp: 1750194549591 - conda: https://prefix.dev/conda-forge/linux-64/libarrow-23.0.0-h2c50142_1_cpu.conda build_number: 1 sha256: 694c0c4fae6a643a9a0bb366371c629d17ec7d5e0cd41bc56439da9d922972df md5: fba261a7ee565b711b45c5bea554e5a0 depends: - __glibc >=2.17,<3.0.a0 - aws-crt-cpp >=0.35.4,<0.35.5.0a0 - aws-sdk-cpp >=1.11.606,<1.11.607.0a0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - azure-identity-cpp >=1.13.2,<1.13.3.0a0 - azure-storage-blobs-cpp >=12.16.0,<12.16.1.0a0 - azure-storage-files-datalake-cpp >=12.14.0,<12.14.1.0a0 - bzip2 >=1.0.8,<2.0a0 - glog >=0.7.1,<0.8.0a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libbrotlidec >=1.2.0,<1.3.0a0 - libbrotlienc >=1.2.0,<1.3.0a0 - libgcc >=14 - libgoogle-cloud >=2.39.0,<2.40.0a0 - libgoogle-cloud-storage >=2.39.0,<2.40.0a0 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - orc >=2.2.2,<2.2.3.0a0 - snappy >=1.2.2,<1.3.0a0 - zstd >=1.5.7,<1.6.0a0 constrains: - parquet-cpp <0.0a0 - arrow-cpp <0.0a0 - apache-arrow-proc =*=cpu license: Apache-2.0 license_family: APACHE purls: [] size: 6499554 timestamp: 1769493211977 - conda: https://prefix.dev/conda-forge/osx-64/libarrow-23.0.0-h8071b21_1_cpu.conda build_number: 1 sha256: 8768b493dbf8700b4f77f93e0d792cf2525db701ba211f9cf2278cf063be04f9 md5: 512a46ffda8e0d6a4c34c386f32a1d8e depends: - __osx >=11.0 - aws-crt-cpp >=0.35.4,<0.35.5.0a0 - aws-sdk-cpp >=1.11.606,<1.11.607.0a0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - azure-identity-cpp >=1.13.2,<1.13.3.0a0 - azure-storage-blobs-cpp >=12.16.0,<12.16.1.0a0 - azure-storage-files-datalake-cpp >=12.14.0,<12.14.1.0a0 - bzip2 >=1.0.8,<2.0a0 - glog >=0.7.1,<0.8.0a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libbrotlidec >=1.2.0,<1.3.0a0 - libbrotlienc >=1.2.0,<1.3.0a0 - libcxx >=21 - libgoogle-cloud >=2.39.0,<2.40.0a0 - libgoogle-cloud-storage >=2.39.0,<2.40.0a0 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - libzlib >=1.3.1,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - orc >=2.2.2,<2.2.3.0a0 - snappy >=1.2.2,<1.3.0a0 - zstd >=1.5.7,<1.6.0a0 constrains: - apache-arrow-proc =*=cpu - parquet-cpp <0.0a0 - arrow-cpp <0.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 4346216 timestamp: 1769492712538 - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-23.0.0-h4365f54_1_cpu.conda build_number: 1 sha256: f51e188fafef9b00d23986305a8fa5287639205db9ff57df84044d9a95d89d35 md5: 4e93106b5de97aafe06b94247b6e963c depends: - __osx >=11.0 - aws-crt-cpp >=0.35.4,<0.35.5.0a0 - aws-sdk-cpp >=1.11.606,<1.11.607.0a0 - azure-core-cpp >=1.16.1,<1.16.2.0a0 - azure-identity-cpp >=1.13.2,<1.13.3.0a0 - azure-storage-blobs-cpp >=12.16.0,<12.16.1.0a0 - azure-storage-files-datalake-cpp >=12.14.0,<12.14.1.0a0 - bzip2 >=1.0.8,<2.0a0 - glog >=0.7.1,<0.8.0a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libbrotlidec >=1.2.0,<1.3.0a0 - libbrotlienc >=1.2.0,<1.3.0a0 - libcxx >=21 - libgoogle-cloud >=2.39.0,<2.40.0a0 - libgoogle-cloud-storage >=2.39.0,<2.40.0a0 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - libzlib >=1.3.1,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - orc >=2.2.2,<2.2.3.0a0 - snappy >=1.2.2,<1.3.0a0 - zstd >=1.5.7,<1.6.0a0 constrains: - apache-arrow-proc =*=cpu - parquet-cpp <0.0a0 - arrow-cpp <0.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 4233089 timestamp: 1769490230644 - conda: https://prefix.dev/conda-forge/win-64/libarrow-23.0.0-hcf7e2ff_1_cpu.conda build_number: 1 sha256: e87845b9a4c3457478f28a25d71eea128f67151602eb6b5078bb96133dd90f53 md5: 5458c2c427b406cf3b1680a5a0da1e4d depends: - aws-crt-cpp >=0.35.4,<0.35.5.0a0 - aws-sdk-cpp >=1.11.606,<1.11.607.0a0 - bzip2 >=1.0.8,<2.0a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libbrotlidec >=1.2.0,<1.3.0a0 - libbrotlienc >=1.2.0,<1.3.0a0 - libcrc32c >=1.1.2,<1.2.0a0 - libcurl >=8.18.0,<9.0a0 - libgoogle-cloud >=2.39.0,<2.40.0a0 - libgoogle-cloud-storage >=2.39.0,<2.40.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - libzlib >=1.3.1,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - orc >=2.2.2,<2.2.3.0a0 - snappy >=1.2.2,<1.3.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - zstd >=1.5.7,<1.6.0a0 constrains: - arrow-cpp <0.0a0 - apache-arrow-proc =*=cpu - parquet-cpp <0.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 4199029 timestamp: 1769494406026 - conda: https://prefix.dev/conda-forge/linux-64/libarrow-acero-23.0.0-h635bf11_1_cpu.conda build_number: 1 sha256: 44532bfceadae7a575a037011e6262e6f93b2b370074c9ec07c1d30330f344dc md5: 8b1290b259b24a4b29b3a3d6dec0fe53 depends: - __glibc >=2.17,<3.0.a0 - libarrow 23.0.0 h2c50142_1_cpu - libarrow-compute 23.0.0 h8c2c5c3_1_cpu - libgcc >=14 - libstdcxx >=14 license: Apache-2.0 license_family: APACHE purls: [] size: 609922 timestamp: 1769493439664 - conda: https://prefix.dev/conda-forge/osx-64/libarrow-acero-23.0.0-h9737151_1_cpu.conda build_number: 1 sha256: 0aed6c436e09a04022fb89db6cb46e4455402ec3d152e237099498ccea30d003 md5: 017da997ab188e57a1f78e278e214d29 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h8071b21_1_cpu - libarrow-compute 23.0.0 hc26cc94_1_cpu - libcxx >=21 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 562954 timestamp: 1769493512948 - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-acero-23.0.0-h6de58dd_1_cpu.conda build_number: 1 sha256: 85f9a278c020af2560c8f9f5b17e0c2a1ad0d1e6263e98b6e6b6a3a696682378 md5: f2d2fabd9783477884ea989794ddaf67 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h4365f54_1_cpu - libarrow-compute 23.0.0 h45df96a_1_cpu - libcxx >=21 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 541119 timestamp: 1769490550224 - conda: https://prefix.dev/conda-forge/win-64/libarrow-acero-23.0.0-h7d8d6a5_1_cpu.conda build_number: 1 sha256: b2da6b71c70a3f808a97479aa3797cb7e48684cbf620418a2f04658371962fb9 md5: 5c2f71be902e7924281e0c705ed6293e depends: - libarrow 23.0.0 hcf7e2ff_1_cpu - libarrow-compute 23.0.0 h2db994a_1_cpu - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: APACHE purls: [] size: 464199 timestamp: 1769494720237 - conda: https://prefix.dev/conda-forge/linux-64/libarrow-compute-23.0.0-h8c2c5c3_1_cpu.conda build_number: 1 sha256: 7d49e48aca75f289eeab26220737af1abee7aaf678b5ba35753a6d2b02b2ea94 md5: 102be5396c7899675268c17993e1a072 depends: - __glibc >=2.17,<3.0.a0 - libarrow 23.0.0 h2c50142_1_cpu - libgcc >=14 - libre2-11 >=2025.8.12 - libstdcxx >=14 - libutf8proc >=2.11.3,<2.12.0a0 - re2 license: Apache-2.0 license_family: APACHE purls: [] size: 3004043 timestamp: 1769493288356 - conda: https://prefix.dev/conda-forge/osx-64/libarrow-compute-23.0.0-hc26cc94_1_cpu.conda build_number: 1 sha256: 5a2f2cc1292cc46920474dfe4f96570c3d6da57df7cde627d00ee8cebf183163 md5: 13f3890256ec1710409043eb6e81359a depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h8071b21_1_cpu - libcxx >=21 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - libre2-11 >=2025.8.12 - libutf8proc >=2.11.3,<2.12.0a0 - re2 license: Apache-2.0 license_family: APACHE purls: [] size: 2404719 timestamp: 1769493029077 - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-compute-23.0.0-h45df96a_1_cpu.conda build_number: 1 sha256: 759961ad6926a13e47792fddb182c2c99fcc889ea5a28c61ab5b708e77bc01e9 md5: 3913b945371055c48978733b8fb5e51b depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h4365f54_1_cpu - libcxx >=21 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - libre2-11 >=2025.8.12 - libutf8proc >=2.11.3,<2.12.0a0 - re2 license: Apache-2.0 license_family: APACHE purls: [] size: 2258796 timestamp: 1769490343927 - conda: https://prefix.dev/conda-forge/win-64/libarrow-compute-23.0.0-h2db994a_1_cpu.conda build_number: 1 sha256: eed7e6ab33588a4239b0d3823cb646762009b9ca6548a8cb5b3725b41bf9d480 md5: 27c755779b48e4fcaee5dbe08ad99ae1 depends: - libarrow 23.0.0 hcf7e2ff_1_cpu - libre2-11 >=2025.8.12 - libutf8proc >=2.11.3,<2.12.0a0 - re2 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: APACHE purls: [] size: 1773412 timestamp: 1769494516760 - conda: https://prefix.dev/conda-forge/linux-64/libarrow-dataset-23.0.0-h635bf11_1_cpu.conda build_number: 1 sha256: 5e7be5b81662940067db5854220781aed85fa35747d4bd88b533b9c22942859b md5: 651c34402277a875986db6fa7930d42d depends: - __glibc >=2.17,<3.0.a0 - libarrow 23.0.0 h2c50142_1_cpu - libarrow-acero 23.0.0 h635bf11_1_cpu - libarrow-compute 23.0.0 h8c2c5c3_1_cpu - libgcc >=14 - libparquet 23.0.0 h7376487_1_cpu - libstdcxx >=14 license: Apache-2.0 license_family: APACHE purls: [] size: 609156 timestamp: 1769493539181 - conda: https://prefix.dev/conda-forge/osx-64/libarrow-dataset-23.0.0-h9737151_1_cpu.conda build_number: 1 sha256: 958a9eb275b4ac844d62c0dd32ccb4da0215d44d7a8e5c3812fbdae2ac6c30a3 md5: d94ed1c83b5fad095968ab6f11b0b6e5 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h8071b21_1_cpu - libarrow-acero 23.0.0 h9737151_1_cpu - libarrow-compute 23.0.0 hc26cc94_1_cpu - libcxx >=21 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libparquet 23.0.0 ha0d2768_1_cpu - libprotobuf >=6.31.1,<6.31.2.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 551251 timestamp: 1769493821666 - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-dataset-23.0.0-h6de58dd_1_cpu.conda build_number: 1 sha256: b05c90d40457b710954eae08d624d574fb16f23a1a443ae024171da7803963f1 md5: 7b415053e0e3f5863d76b92a69dbf9df depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h4365f54_1_cpu - libarrow-acero 23.0.0 h6de58dd_1_cpu - libarrow-compute 23.0.0 h45df96a_1_cpu - libcxx >=21 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libparquet 23.0.0 hcc2992d_1_cpu - libprotobuf >=6.31.1,<6.31.2.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 537548 timestamp: 1769490690214 - conda: https://prefix.dev/conda-forge/win-64/libarrow-dataset-23.0.0-h7d8d6a5_1_cpu.conda build_number: 1 sha256: ab6693aaf8e1a3c170d400c63bd32ed45b69cdcc62a6002b07f723c46d266942 md5: ab025adf6a1df12705d5e86e2d283cc8 depends: - libarrow 23.0.0 hcf7e2ff_1_cpu - libarrow-acero 23.0.0 h7d8d6a5_1_cpu - libarrow-compute 23.0.0 h2db994a_1_cpu - libparquet 23.0.0 h7051d1f_1_cpu - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: APACHE purls: [] size: 446808 timestamp: 1769494845412 - conda: https://prefix.dev/conda-forge/linux-64/libarrow-substrait-23.0.0-h3f74fd7_1_cpu.conda build_number: 1 sha256: 955beae76625c953f211e098e9ac3fa51e3a6f87f0dae6da76cf4eb53e0279eb md5: bcf3ca0f04ed703121db4012e8c8bf5a depends: - __glibc >=2.17,<3.0.a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h2c50142_1_cpu - libarrow-acero 23.0.0 h635bf11_1_cpu - libarrow-dataset 23.0.0 h635bf11_1_cpu - libgcc >=14 - libprotobuf >=6.31.1,<6.31.2.0a0 - libstdcxx >=14 license: Apache-2.0 license_family: APACHE purls: [] size: 517309 timestamp: 1769493572255 - conda: https://prefix.dev/conda-forge/osx-64/libarrow-substrait-23.0.0-h7f2e36e_1_cpu.conda build_number: 1 sha256: 2db5ac60983f74070dbfbf95d34ccedffc21232c2b4ec5936de3aedd2c2390e8 md5: 4f2b6ff44fceeb46dec7251f207738c6 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h8071b21_1_cpu - libarrow-acero 23.0.0 h9737151_1_cpu - libarrow-dataset 23.0.0 h9737151_1_cpu - libcxx >=21 - libprotobuf >=6.31.1,<6.31.2.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 465218 timestamp: 1769493925118 - conda: https://prefix.dev/conda-forge/osx-arm64/libarrow-substrait-23.0.0-hb5627e6_1_cpu.conda build_number: 1 sha256: 378c571505fceba58e0d5521f0054b29e449276fad0564999aa9aaa02a2d6b9b md5: a37a44ae8672cf995de6dd04b375c3d8 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h4365f54_1_cpu - libarrow-acero 23.0.0 h6de58dd_1_cpu - libarrow-dataset 23.0.0 h6de58dd_1_cpu - libcxx >=21 - libprotobuf >=6.31.1,<6.31.2.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 472469 timestamp: 1769490756805 - conda: https://prefix.dev/conda-forge/win-64/libarrow-substrait-23.0.0-hf865cc0_1_cpu.conda build_number: 1 sha256: d442612b2eb85f26339d503e0c180bc2289bd4108540faea9c7849a9799e715f md5: 641df8b6b4725c87f3284d62f1254954 depends: - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 hcf7e2ff_1_cpu - libarrow-acero 23.0.0 h7d8d6a5_1_cpu - libarrow-dataset 23.0.0 h7d8d6a5_1_cpu - libprotobuf >=6.31.1,<6.31.2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: APACHE purls: [] size: 375573 timestamp: 1769494893495 - conda: https://prefix.dev/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda build_number: 5 sha256: 18c72545080b86739352482ba14ba2c4815e19e26a7417ca21a95b76ec8da24c md5: c160954f7418d7b6e87eaf05a8913fa9 depends: - libopenblas >=0.3.30,<0.3.31.0a0 - libopenblas >=0.3.30,<1.0a0 constrains: - mkl <2026 - liblapack 3.11.0 5*_openblas - libcblas 3.11.0 5*_openblas - blas 2.305 openblas - liblapacke 3.11.0 5*_openblas license: BSD-3-Clause license_family: BSD purls: [] size: 18213 timestamp: 1765818813880 - conda: https://prefix.dev/conda-forge/osx-64/libblas-3.11.0-5_he492b99_openblas.conda build_number: 5 sha256: 4754de83feafa6c0b41385f8dab1b13f13476232e16f524564a340871a9fc3bc md5: 36d2e68a156692cbae776b75d6ca6eae depends: - libopenblas >=0.3.30,<0.3.31.0a0 - libopenblas >=0.3.30,<1.0a0 constrains: - liblapack 3.11.0 5*_openblas - blas 2.305 openblas - libcblas 3.11.0 5*_openblas - mkl <2026 - liblapacke 3.11.0 5*_openblas license: BSD-3-Clause license_family: BSD purls: [] size: 18476 timestamp: 1765819054657 - conda: https://prefix.dev/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda build_number: 5 sha256: 620a6278f194dcabc7962277da6835b1e968e46ad0c8e757736255f5ddbfca8d md5: bcc025e2bbaf8a92982d20863fe1fb69 depends: - libopenblas >=0.3.30,<0.3.31.0a0 - libopenblas >=0.3.30,<1.0a0 constrains: - libcblas 3.11.0 5*_openblas - liblapack 3.11.0 5*_openblas - liblapacke 3.11.0 5*_openblas - blas 2.305 openblas - mkl <2026 license: BSD-3-Clause license_family: BSD purls: [] size: 18546 timestamp: 1765819094137 - conda: https://prefix.dev/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda build_number: 5 sha256: f0cb7b2697461a306341f7ff32d5b361bb84f3e94478464c1e27ee01fc8f276b md5: f9decf88743af85c9c9e05556a4c47c0 depends: - mkl >=2025.3.0,<2026.0a0 constrains: - liblapack 3.11.0 5*_mkl - libcblas 3.11.0 5*_mkl - blas 2.305 mkl - liblapacke 3.11.0 5*_mkl license: BSD-3-Clause license_family: BSD purls: [] size: 67438 timestamp: 1765819100043 - conda: https://prefix.dev/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda sha256: 318f36bd49ca8ad85e6478bd8506c88d82454cc008c1ac1c6bf00a3c42fa610e md5: 72c8fd1af66bd67bf580645b426513ed depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 79965 timestamp: 1764017188531 - conda: https://prefix.dev/conda-forge/osx-64/libbrotlicommon-1.2.0-h8616949_1.conda sha256: 4c19b211b3095f541426d5a9abac63e96a5045e509b3d11d4f9482de53efe43b md5: f157c098841474579569c85a60ece586 depends: - __osx >=10.13 license: MIT license_family: MIT purls: [] size: 78854 timestamp: 1764017554982 - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda sha256: a7cb9e660531cf6fbd4148cff608c85738d0b76f0975c5fc3e7d5e92840b7229 md5: 006e7ddd8a110771134fcc4e1e3a6ffa depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 79443 timestamp: 1764017945924 - conda: https://prefix.dev/conda-forge/win-64/libbrotlicommon-1.2.0-hfd05255_1.conda sha256: 5097303c2fc8ebf9f9ea9731520aa5ce4847d0be41764edd7f6dee2100b82986 md5: 444b0a45bbd1cb24f82eedb56721b9c4 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 82042 timestamp: 1764017799966 - conda: https://prefix.dev/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda sha256: 12fff21d38f98bc446d82baa890e01fd82e3b750378fedc720ff93522ffb752b md5: 366b40a69f0ad6072561c1d09301c886 depends: - __glibc >=2.17,<3.0.a0 - libbrotlicommon 1.2.0 hb03c661_1 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 34632 timestamp: 1764017199083 - conda: https://prefix.dev/conda-forge/osx-64/libbrotlidec-1.2.0-h8616949_1.conda sha256: 729158be90ae655a4e0427fe4079767734af1f9b69ff58cf94ca6e8d4b3eb4b7 md5: 63186ac7a8a24b3528b4b14f21c03f54 depends: - __osx >=10.13 - libbrotlicommon 1.2.0 h8616949_1 license: MIT license_family: MIT purls: [] size: 30835 timestamp: 1764017584474 - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda sha256: 2eae444039826db0454b19b52a3390f63bfe24f6b3e63089778dd5a5bf48b6bf md5: 079e88933963f3f149054eec2c487bc2 depends: - __osx >=11.0 - libbrotlicommon 1.2.0 hc919400_1 license: MIT license_family: MIT purls: [] size: 29452 timestamp: 1764017979099 - conda: https://prefix.dev/conda-forge/win-64/libbrotlidec-1.2.0-hfd05255_1.conda sha256: 3239ce545cf1c32af6fffb7fc7c75cb1ef5b6ea8221c66c85416bb2d46f5cccb md5: 450e3ae947fc46b60f1d8f8f318b40d4 depends: - libbrotlicommon 1.2.0 hfd05255_1 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 34449 timestamp: 1764017851337 - conda: https://prefix.dev/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda sha256: a0c15c79997820bbd3fbc8ecf146f4fe0eca36cc60b62b63ac6cf78857f1dd0d md5: 4ffbb341c8b616aa2494b6afb26a0c5f depends: - __glibc >=2.17,<3.0.a0 - libbrotlicommon 1.2.0 hb03c661_1 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 298378 timestamp: 1764017210931 - conda: https://prefix.dev/conda-forge/osx-64/libbrotlienc-1.2.0-h8616949_1.conda sha256: 8ece7b41b6548d6601ac2c2cd605cf2261268fc4443227cc284477ed23fbd401 md5: 12a58fd3fc285ce20cf20edf21a0ff8f depends: - __osx >=10.13 - libbrotlicommon 1.2.0 h8616949_1 license: MIT license_family: MIT purls: [] size: 310355 timestamp: 1764017609985 - conda: https://prefix.dev/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda sha256: 01436c32bb41f9cb4bcf07dda647ce4e5deb8307abfc3abdc8da5317db8189d1 md5: b2b7c8288ca1a2d71ff97a8e6a1e8883 depends: - __osx >=11.0 - libbrotlicommon 1.2.0 hc919400_1 license: MIT license_family: MIT purls: [] size: 290754 timestamp: 1764018009077 - conda: https://prefix.dev/conda-forge/win-64/libbrotlienc-1.2.0-hfd05255_1.conda sha256: 3226df6b7df98734440739f75527d585d42ca2bfe912fbe8d1954c512f75341a md5: ccd93cfa8e54fd9df4e83dbe55ff6e8c depends: - libbrotlicommon 1.2.0 hfd05255_1 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 252903 timestamp: 1764017901735 - conda: https://prefix.dev/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda build_number: 5 sha256: 0cbdcc67901e02dc17f1d19e1f9170610bd828100dc207de4d5b6b8ad1ae7ad8 md5: 6636a2b6f1a87572df2970d3ebc87cc0 depends: - libblas 3.11.0 5_h4a7cf45_openblas constrains: - liblapacke 3.11.0 5*_openblas - blas 2.305 openblas - liblapack 3.11.0 5*_openblas license: BSD-3-Clause license_family: BSD purls: [] size: 18194 timestamp: 1765818837135 - conda: https://prefix.dev/conda-forge/osx-64/libcblas-3.11.0-5_h9b27e0a_openblas.conda build_number: 5 sha256: 8077c29ea720bd152be6e6859a3765228cde51301fe62a3b3f505b377c2cb48c md5: b31d771cbccff686e01a687708a7ca41 depends: - libblas 3.11.0 5_he492b99_openblas constrains: - liblapack 3.11.0 5*_openblas - blas 2.305 openblas - liblapacke 3.11.0 5*_openblas license: BSD-3-Clause license_family: BSD purls: [] size: 18484 timestamp: 1765819073006 - conda: https://prefix.dev/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda build_number: 5 sha256: 38809c361bbd165ecf83f7f05fae9b791e1baa11e4447367f38ae1327f402fc0 md5: efd8bd15ca56e9d01748a3beab8404eb depends: - libblas 3.11.0 5_h51639a9_openblas constrains: - liblapacke 3.11.0 5*_openblas - liblapack 3.11.0 5*_openblas - blas 2.305 openblas license: BSD-3-Clause license_family: BSD purls: [] size: 18548 timestamp: 1765819108956 - conda: https://prefix.dev/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda build_number: 5 sha256: 49dc59d8e58360920314b8d276dd80da7866a1484a9abae4ee2760bc68f3e68d md5: b3fa8e8b55310ba8ef0060103afb02b5 depends: - libblas 3.11.0 5_hf2e6a31_mkl constrains: - liblapack 3.11.0 5*_mkl - liblapacke 3.11.0 5*_mkl - blas 2.305 mkl license: BSD-3-Clause license_family: BSD purls: [] size: 68079 timestamp: 1765819124349 - conda: https://prefix.dev/conda-forge/linux-64/libclang-cpp21.1-21.1.8-default_h99862b1_2.conda sha256: ee878abf2ecbba378525a900a1ebe773ce2313fffeba6e8aca85f6fc62d0a0e1 md5: 3c71daed530c0c26671a1b1b7010e746 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libllvm21 >=21.1.8,<21.2.0a0 - libstdcxx >=14 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] size: 21054598 timestamp: 1769313958672 - conda: https://prefix.dev/conda-forge/linux-64/libclang13-21.1.8-default_h746c552_2.conda sha256: 77102b261874b35f37a12e79bab2272596e8bfda9e94cf13d1ae480ccd8d2e87 md5: 0ad9019bb10eda915fb0ce5f78fef13b depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libllvm21 >=21.1.8,<21.2.0a0 - libstdcxx >=14 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] size: 12346110 timestamp: 1769314238631 - conda: https://prefix.dev/conda-forge/win-64/libclang13-21.1.8-default_ha2db4b5_2.conda sha256: ca513e2a98ff35855a0f6594632846b62a584369ff12a0cca66466a88f37e9a3 md5: 511af9070467adf0e8af89ce18d516cf depends: - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - zstd >=1.5.7,<1.6.0a0 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] size: 28997951 timestamp: 1769320556440 - conda: https://prefix.dev/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 sha256: fd1d153962764433fe6233f34a72cdeed5dcf8a883a85769e8295ce940b5b0c5 md5: c965a5aa0d5c1c37ffc62dff36e28400 depends: - libgcc-ng >=9.4.0 - libstdcxx-ng >=9.4.0 license: BSD-3-Clause license_family: BSD purls: [] size: 20440 timestamp: 1633683576494 - conda: https://prefix.dev/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 sha256: 3043869ac1ee84554f177695e92f2f3c2c507b260edad38a0bf3981fce1632ff md5: 23d6d5a69918a438355d7cbc4c3d54c9 depends: - libcxx >=11.1.0 license: BSD-3-Clause license_family: BSD purls: [] size: 20128 timestamp: 1633683906221 - conda: https://prefix.dev/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 sha256: 58477b67cc719060b5b069ba57161e20ba69b8695d154a719cb4b60caf577929 md5: 32bd82a6a625ea6ce090a81c3d34edeb depends: - libcxx >=11.1.0 license: BSD-3-Clause license_family: BSD purls: [] size: 18765 timestamp: 1633683992603 - conda: https://prefix.dev/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 sha256: 75e60fbe436ba8a11c170c89af5213e8bec0418f88b7771ab7e3d9710b70c54e md5: cd4cc2d0c610c8cb5419ccc979f2d6ce depends: - vc >=14.1,<15.0a0 - vs2015_runtime >=14.16.27012 license: BSD-3-Clause license_family: BSD purls: [] size: 25694 timestamp: 1633684287072 - conda: https://prefix.dev/conda-forge/linux-64/libcups-2.3.3-hb8b1518_5.conda sha256: cb83980c57e311783ee831832eb2c20ecb41e7dee6e86e8b70b8cef0e43eab55 md5: d4a250da4737ee127fb1fa6452a9002e depends: - __glibc >=2.17,<3.0.a0 - krb5 >=1.21.3,<1.22.0a0 - libgcc >=13 - libstdcxx >=13 - libzlib >=1.3.1,<2.0a0 license: Apache-2.0 license_family: Apache purls: [] size: 4523621 timestamp: 1749905341688 - conda: https://prefix.dev/conda-forge/linux-64/libcurl-8.18.0-h4e3cde8_0.conda sha256: 5454709d9fb6e9c3dd6423bc284fa7835a7823bfa8323f6e8786cdd555101fab md5: 0a5563efed19ca4461cf927419b6eb73 depends: - __glibc >=2.17,<3.0.a0 - krb5 >=1.21.3,<1.22.0a0 - libgcc >=14 - libnghttp2 >=1.67.0,<2.0a0 - libssh2 >=1.11.1,<2.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - zstd >=1.5.7,<1.6.0a0 license: curl license_family: MIT purls: [] size: 462942 timestamp: 1767821743793 - conda: https://prefix.dev/conda-forge/osx-64/libcurl-8.18.0-h9348e2b_0.conda sha256: 1a0af3b7929af3c5893ebf50161978f54ae0256abb9532d4efba2735a0688325 md5: de1910529f64ba4a9ac9005e0be78601 depends: - __osx >=10.13 - krb5 >=1.21.3,<1.22.0a0 - libnghttp2 >=1.67.0,<2.0a0 - libssh2 >=1.11.1,<2.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - zstd >=1.5.7,<1.6.0a0 license: curl license_family: MIT purls: [] size: 419089 timestamp: 1767822218800 - conda: https://prefix.dev/conda-forge/osx-arm64/libcurl-8.18.0-he38603e_0.conda sha256: 11c78b3e89bc332933386f0a11ac60d9200afb7a811b9e3bec98aef8d4a6389b md5: 36190179a799f3aee3c2d20a8a2b970d depends: - __osx >=11.0 - krb5 >=1.21.3,<1.22.0a0 - libnghttp2 >=1.67.0,<2.0a0 - libssh2 >=1.11.1,<2.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - zstd >=1.5.7,<1.6.0a0 license: curl license_family: MIT purls: [] size: 402681 timestamp: 1767822693908 - conda: https://prefix.dev/conda-forge/win-64/libcurl-8.18.0-h43ecb02_0.conda sha256: 86258e30845571ea13855e8a0605275905781476f3edf8ae5df90a06fcada93a md5: 2688214a9bee5d5650cd4f5f6af5c8f2 depends: - krb5 >=1.21.3,<1.22.0a0 - libssh2 >=1.11.1,<2.0a0 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: curl license_family: MIT purls: [] size: 383261 timestamp: 1767821977053 - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_0.conda sha256: cbd8e821e97436d8fc126c24b50df838b05ba4c80494fbb93ccaf2e3b2d109fb md5: 9f8a60a77ecafb7966ca961c94f33bd1 depends: - __osx >=10.13 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] size: 569777 timestamp: 1765919624323 - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h3d58e20_1.conda sha256: facdc3861f2d9e8de3cb42cd5b32d56b2a3e0d957bf8e80641cedaf3ab2c7156 md5: 7a582e52af3e0e495ba3ba9e1e87c7bb depends: - __osx >=10.13 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] size: 572248 timestamp: 1769754786463 - conda: https://prefix.dev/conda-forge/osx-64/libcxx-21.1.8-h4fb565c_2.conda sha256: 2619d471c50c466320e2aea906a4363e34efe181e61346e4453bc68264c5185f md5: 1ac756454e65fb3fd7bc7de599526e43 depends: - __osx >=10.13 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] size: 571912 timestamp: 1770237202404 - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-h55c6f16_2.conda sha256: 5fbeb2fc2673f0455af6079abf93faaf27f11a92574ad51565fa1ecac9a4e2aa md5: 4cb5878bdb9ebfa65b7cdff5445087c5 depends: - __osx >=11.0 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] size: 570068 timestamp: 1770238262922 - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_0.conda sha256: 82e228975fd491bcf1071ecd0a6ec2a0fcc5f57eb0bd1d52cb13a18d57c67786 md5: 780f0251b757564e062187044232c2b7 depends: - __osx >=11.0 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] size: 569118 timestamp: 1765919724254 - conda: https://prefix.dev/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_1.conda sha256: 3a924cbce92b0dceb5d392036e692bac1e60ae90d85c7c78264c672a205c007b md5: cd7367d0c0f49853f8f3560bfb4456ab depends: - __osx >=11.0 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] size: 570705 timestamp: 1769754656112 - conda: https://prefix.dev/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 md5: 6c77a605a7a689d17d4819c0f8ac9a00 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 73490 timestamp: 1761979956660 - conda: https://prefix.dev/conda-forge/osx-64/libdeflate-1.25-h517ebb2_0.conda sha256: 025f8b1e85dd8254e0ca65f011919fb1753070eb507f03bca317871a884d24de md5: 31aa65919a729dc48180893f62c25221 depends: - __osx >=10.13 license: MIT license_family: MIT purls: [] size: 70840 timestamp: 1761980008502 - conda: https://prefix.dev/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda sha256: 5e0b6961be3304a5f027a8c00bd0967fc46ae162cffb7553ff45c70f51b8314c md5: a6130c709305cd9828b4e1bd9ba0000c depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 55420 timestamp: 1761980066242 - conda: https://prefix.dev/conda-forge/win-64/libdeflate-1.25-h51727cc_0.conda sha256: 834e4881a18b690d5ec36f44852facd38e13afe599e369be62d29bd675f107ee md5: e77030e67343e28b084fabd7db0ce43e depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 156818 timestamp: 1761979842440 - conda: https://prefix.dev/conda-forge/linux-64/libdrm-2.4.125-hb03c661_1.conda sha256: c076a213bd3676cc1ef22eeff91588826273513ccc6040d9bea68bccdc849501 md5: 9314bc5a1fe7d1044dc9dfd3ef400535 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libpciaccess >=0.18,<0.19.0a0 license: MIT license_family: MIT purls: [] size: 310785 timestamp: 1757212153962 - conda: https://prefix.dev/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 md5: c277e0a4d549b03ac1e9d6cbbe3d017b depends: - ncurses - __glibc >=2.17,<3.0.a0 - libgcc >=13 - ncurses >=6.5,<7.0a0 license: BSD-2-Clause license_family: BSD purls: [] size: 134676 timestamp: 1738479519902 - conda: https://prefix.dev/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda sha256: 6cc49785940a99e6a6b8c6edbb15f44c2dd6c789d9c283e5ee7bdfedd50b4cd6 md5: 1f4ed31220402fcddc083b4bff406868 depends: - ncurses - __osx >=10.13 - ncurses >=6.5,<7.0a0 license: BSD-2-Clause license_family: BSD purls: [] size: 115563 timestamp: 1738479554273 - conda: https://prefix.dev/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda sha256: 66aa216a403de0bb0c1340a88d1a06adaff66bae2cfd196731aa24db9859d631 md5: 44083d2d2c2025afca315c7a172eab2b depends: - ncurses - __osx >=11.0 - ncurses >=6.5,<7.0a0 license: BSD-2-Clause license_family: BSD purls: [] size: 107691 timestamp: 1738479560845 - conda: https://prefix.dev/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_2.conda sha256: 7fd5408d359d05a969133e47af580183fbf38e2235b562193d427bb9dad79723 md5: c151d5eb730e9b7480e6d48c0fc44048 depends: - __glibc >=2.17,<3.0.a0 - libglvnd 1.7.0 ha4b6fd6_2 license: LicenseRef-libglvnd purls: [] size: 44840 timestamp: 1731330973553 - conda: https://prefix.dev/conda-forge/linux-64/libev-4.33-hd590300_2.conda sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 md5: 172bf1cd1ff8629f2b1179945ed45055 depends: - libgcc-ng >=12 license: BSD-2-Clause license_family: BSD purls: [] size: 112766 timestamp: 1702146165126 - conda: https://prefix.dev/conda-forge/osx-64/libev-4.33-h10d778d_2.conda sha256: 0d238488564a7992942aa165ff994eca540f687753b4f0998b29b4e4d030ff43 md5: 899db79329439820b7e8f8de41bca902 license: BSD-2-Clause license_family: BSD purls: [] size: 106663 timestamp: 1702146352558 - conda: https://prefix.dev/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda sha256: 95cecb3902fbe0399c3a7e67a5bed1db813e5ab0e22f4023a5e0f722f2cc214f md5: 36d33e440c31857372a72137f78bacf5 license: BSD-2-Clause license_family: BSD purls: [] size: 107458 timestamp: 1702146414478 - conda: https://prefix.dev/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda sha256: 2e14399d81fb348e9d231a82ca4d816bf855206923759b69ad006ba482764131 md5: a1cfcc585f0c42bf8d5546bb1dfb668d depends: - libgcc-ng >=12 - openssl >=3.1.1,<4.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 427426 timestamp: 1685725977222 - conda: https://prefix.dev/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda sha256: e0bd9af2a29f8dd74309c0ae4f17a7c2b8c4b89f875ff1d6540c941eefbd07fb md5: e38e467e577bd193a7d5de7c2c540b04 depends: - openssl >=3.1.1,<4.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 372661 timestamp: 1685726378869 - conda: https://prefix.dev/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda sha256: 8c136d7586259bb5c0d2b913aaadc5b9737787ae4f40e3ad1beaf96c80b919b7 md5: 1a109764bff3bdc7bdd84088347d71dc depends: - openssl >=3.1.1,<4.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 368167 timestamp: 1685726248899 - conda: https://prefix.dev/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda sha256: af03882afb7a7135288becf340c2f0cf8aa8221138a9a7b108aaeb308a486da1 md5: 25efbd786caceef438be46da78a7b5ef depends: - openssl >=3.1.1,<4.0a0 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: BSD-3-Clause license_family: BSD purls: [] size: 410555 timestamp: 1685726568668 - conda: https://prefix.dev/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda sha256: 1e1b08f6211629cbc2efe7a5bca5953f8f6b3cae0eeb04ca4dacee1bd4e2db2f md5: 8b09ae86839581147ef2e5c5e229d164 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 constrains: - expat 2.7.3.* license: MIT license_family: MIT purls: [] size: 76643 timestamp: 1763549731408 - conda: https://prefix.dev/conda-forge/osx-64/libexpat-2.7.3-heffb93a_0.conda sha256: d11b3a6ce5b2e832f430fd112084533a01220597221bee16d6c7dc3947dffba6 md5: 222e0732a1d0780a622926265bee14ef depends: - __osx >=10.13 constrains: - expat 2.7.3.* license: MIT license_family: MIT purls: [] size: 74058 timestamp: 1763549886493 - conda: https://prefix.dev/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda sha256: fce22610ecc95e6d149e42a42fbc3cc9d9179bd4eb6232639a60f06e080eec98 md5: b79875dbb5b1db9a4a22a4520f918e1a depends: - __osx >=11.0 constrains: - expat 2.7.3.* license: MIT license_family: MIT purls: [] size: 67800 timestamp: 1763549994166 - conda: https://prefix.dev/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda sha256: 844ab708594bdfbd7b35e1a67c379861bcd180d6efe57b654f482ae2f7f5c21e md5: 8c9e4f1a0e688eef2e95711178061a0f depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - expat 2.7.3.* license: MIT license_family: MIT purls: [] size: 70137 timestamp: 1763550049107 - conda: https://prefix.dev/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 md5: a360c33a5abe61c07959e449fa1453eb depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 58592 timestamp: 1769456073053 - conda: https://prefix.dev/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda sha256: 951958d1792238006fdc6fce7f71f1b559534743b26cc1333497d46e5903a2d6 md5: 66a0dc7464927d0853b590b6f53ba3ea depends: - __osx >=10.13 license: MIT license_family: MIT purls: [] size: 53583 timestamp: 1769456300951 - conda: https://prefix.dev/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda sha256: 6686a26466a527585e6a75cc2a242bf4a3d97d6d6c86424a441677917f28bec7 md5: 43c04d9cb46ef176bb2a4c77e324d599 depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 40979 timestamp: 1769456747661 - conda: https://prefix.dev/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda sha256: 59d01f2dfa8b77491b5888a5ab88ff4e1574c9359f7e229da254cdfe27ddc190 md5: 720b39f5ec0610457b725eb3f396219a depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 45831 timestamp: 1769456418774 - conda: https://prefix.dev/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda sha256: 4641d37faeb97cf8a121efafd6afd040904d4bca8c46798122f417c31d5dfbec md5: f4084e4e6577797150f9b04a4560ceb0 depends: - libfreetype6 >=2.14.1 license: GPL-2.0-only OR FTL purls: [] size: 7664 timestamp: 1757945417134 - conda: https://prefix.dev/conda-forge/osx-64/libfreetype-2.14.1-h694c41f_0.conda sha256: 035e23ef87759a245d51890aedba0b494a26636784910c3730d76f3dc4482b1d md5: e0e2edaf5e0c71b843e25a7ecc451cc9 depends: - libfreetype6 >=2.14.1 license: GPL-2.0-only OR FTL purls: [] size: 7780 timestamp: 1757945952392 - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda sha256: 9de25a86066f078822d8dd95a83048d7dc2897d5d655c0e04a8a54fca13ef1ef md5: f35fb38e89e2776994131fbf961fa44b depends: - libfreetype6 >=2.14.1 license: GPL-2.0-only OR FTL purls: [] size: 7810 timestamp: 1757947168537 - conda: https://prefix.dev/conda-forge/win-64/libfreetype-2.14.1-h57928b3_0.conda sha256: 2029702ec55e968ce18ec38cc8cf29f4c8c4989a0d51797164dab4f794349a64 md5: 3235024fe48d4087721797ebd6c9d28c depends: - libfreetype6 >=2.14.1 license: GPL-2.0-only OR FTL purls: [] size: 8109 timestamp: 1757946135015 - conda: https://prefix.dev/conda-forge/linux-64/libfreetype6-2.14.1-h73754d4_0.conda sha256: 4a7af818a3179fafb6c91111752954e29d3a2a950259c14a2fc7ba40a8b03652 md5: 8e7251989bca326a28f4a5ffbd74557a depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libpng >=1.6.50,<1.7.0a0 - libzlib >=1.3.1,<2.0a0 constrains: - freetype >=2.14.1 license: GPL-2.0-only OR FTL purls: [] size: 386739 timestamp: 1757945416744 - conda: https://prefix.dev/conda-forge/osx-64/libfreetype6-2.14.1-h6912278_0.conda sha256: f5f28092e368efc773bcd1c381d123f8b211528385a9353e36f8808d00d11655 md5: dfbdc8fd781dc3111541e4234c19fdbd depends: - __osx >=10.13 - libpng >=1.6.50,<1.7.0a0 - libzlib >=1.3.1,<2.0a0 constrains: - freetype >=2.14.1 license: GPL-2.0-only OR FTL purls: [] size: 374993 timestamp: 1757945949585 - conda: https://prefix.dev/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda sha256: cc4aec4c490123c0f248c1acd1aeab592afb6a44b1536734e20937cda748f7cd md5: 6d4ede03e2a8e20eb51f7f681d2a2550 depends: - __osx >=11.0 - libpng >=1.6.50,<1.7.0a0 - libzlib >=1.3.1,<2.0a0 constrains: - freetype >=2.14.1 license: GPL-2.0-only OR FTL purls: [] size: 346703 timestamp: 1757947166116 - conda: https://prefix.dev/conda-forge/win-64/libfreetype6-2.14.1-hdbac1cb_0.conda sha256: 223710600b1a5567163f7d66545817f2f144e4ef8f84e99e90f6b8a4e19cb7ad md5: 6e7c5c5ab485057b5d07fd8188ba5c28 depends: - libpng >=1.6.50,<1.7.0a0 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - freetype >=2.14.1 license: GPL-2.0-only OR FTL purls: [] size: 340264 timestamp: 1757946133889 - conda: https://prefix.dev/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda sha256: 6eed58051c2e12b804d53ceff5994a350c61baf117ec83f5f10c953a3f311451 md5: 6d0363467e6ed84f11435eb309f2ff06 depends: - __glibc >=2.17,<3.0.a0 - _openmp_mutex >=4.5 constrains: - libgcc-ng ==15.2.0=*_16 - libgomp 15.2.0 he0feb66_16 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 1042798 timestamp: 1765256792743 - conda: https://prefix.dev/conda-forge/osx-64/libgcc-15.2.0-h08519bb_15.conda sha256: e04b115ae32f8cbf95905971856ff557b296511735f4e1587b88abf519ff6fb8 md5: c816665789d1e47cdfd6da8a81e1af64 depends: - _openmp_mutex constrains: - libgomp 15.2.0 15 - libgcc-ng ==15.2.0=*_15 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 422960 timestamp: 1764839601296 - conda: https://prefix.dev/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda sha256: 646c91dbc422fe92a5f8a3a5409c9aac66549f4ce8f8d1cab7c2aa5db789bb69 md5: 8b216bac0de7a9d60f3ddeba2515545c depends: - _openmp_mutex constrains: - libgcc-ng ==15.2.0=*_16 - libgomp 15.2.0 16 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 402197 timestamp: 1765258985740 - conda: https://prefix.dev/conda-forge/win-64/libgcc-15.2.0-h8ee18e1_16.conda sha256: 24984e1e768440ba73021f08a1da0c1ec957b30d7071b9a89b877a273d17cae8 md5: 1edb8bd8e093ebd31558008e9cb23b47 depends: - _openmp_mutex >=4.5 - libwinpthread >=12.0.0.r4.gg4f2fc60ca constrains: - libgomp 15.2.0 h8ee18e1_16 - libgcc-ng ==15.2.0=*_16 - msys2-conda-epoch <0.0a0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 819696 timestamp: 1765260437409 - conda: https://prefix.dev/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_16.conda sha256: 5f07f9317f596a201cc6e095e5fc92621afca64829785e483738d935f8cab361 md5: 5a68259fac2da8f2ee6f7bfe49c9eb8b depends: - libgcc 15.2.0 he0feb66_16 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 27256 timestamp: 1765256804124 - conda: https://prefix.dev/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda sha256: 8a7b01e1ee1c462ad243524d76099e7174ebdd94ff045fe3e9b1e58db196463b md5: 40d9b534410403c821ff64f00d0adc22 depends: - libgfortran5 15.2.0 h68bc16d_16 constrains: - libgfortran-ng ==15.2.0=*_16 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 27215 timestamp: 1765256845586 - conda: https://prefix.dev/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_15.conda sha256: 7bb4d51348e8f7c1a565df95f4fc2a2021229d42300aab8366eda0ea1af90587 md5: a089323fefeeaba2ae60e1ccebf86ddc depends: - libgfortran5 15.2.0 hd16e46c_15 constrains: - libgfortran-ng ==15.2.0=*_15 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 139002 timestamp: 1764839892631 - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda sha256: 68a6c1384d209f8654112c4c57c68c540540dd8e09e17dd1facf6cf3467798b5 md5: 11e09edf0dde4c288508501fe621bab4 depends: - libgfortran5 15.2.0 hdae7583_16 constrains: - libgfortran-ng ==15.2.0=*_16 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 138630 timestamp: 1765259217400 - conda: https://prefix.dev/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda sha256: d0e974ebc937c67ae37f07a28edace978e01dc0f44ee02f29ab8a16004b8148b md5: 39183d4e0c05609fd65f130633194e37 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=15.2.0 constrains: - libgfortran 15.2.0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 2480559 timestamp: 1765256819588 - conda: https://prefix.dev/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_15.conda sha256: 456385a7d3357d5fdfc8e11bf18dcdf71753c4016c440f92a2486057524dd59a md5: c2a6149bf7f82774a0118b9efef966dd depends: - libgcc >=15.2.0 constrains: - libgfortran 15.2.0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 1061950 timestamp: 1764839609607 - conda: https://prefix.dev/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda sha256: 9fb7f4ff219e3fb5decbd0ee90a950f4078c90a86f5d8d61ca608c913062f9b0 md5: 265a9d03461da24884ecc8eb58396d57 depends: - libgcc >=15.2.0 constrains: - libgfortran 15.2.0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 598291 timestamp: 1765258993165 - conda: https://prefix.dev/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_2.conda sha256: dc2752241fa3d9e40ce552c1942d0a4b5eeb93740c9723873f6fcf8d39ef8d2d md5: 928b8be80851f5d8ffb016f9c81dae7a depends: - __glibc >=2.17,<3.0.a0 - libglvnd 1.7.0 ha4b6fd6_2 - libglx 1.7.0 ha4b6fd6_2 license: LicenseRef-libglvnd purls: [] size: 134712 timestamp: 1731330998354 - conda: https://prefix.dev/conda-forge/linux-64/libglib-2.86.3-h6548e54_0.conda sha256: 82d6c2ee9f548c84220fb30fb1b231c64a53561d6e485447394f0a0eeeffe0e6 md5: 034bea55a4feef51c98e8449938e9cee depends: - __glibc >=2.17,<3.0.a0 - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - libiconv >=1.18,<2.0a0 - libzlib >=1.3.1,<2.0a0 - pcre2 >=10.47,<10.48.0a0 constrains: - glib 2.86.3 *_0 license: LGPL-2.1-or-later purls: [] size: 3946542 timestamp: 1765221858705 - conda: https://prefix.dev/conda-forge/win-64/libglib-2.86.3-h0c9aed9_0.conda sha256: 84b74fc81fff745f3d21a26c317ace44269a563a42ead3500034c27e407e1021 md5: c2d5b6b790ef21abac0b5331094ccb56 depends: - libffi >=3.5.2,<3.6.0a0 - libiconv >=1.18,<2.0a0 - libintl >=0.22.5,<1.0a0 - libzlib >=1.3.1,<2.0a0 - pcre2 >=10.47,<10.48.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - glib 2.86.3 *_0 license: LGPL-2.1-or-later purls: [] size: 3818991 timestamp: 1765222145992 - conda: https://prefix.dev/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_2.conda sha256: 1175f8a7a0c68b7f81962699751bb6574e6f07db4c9f72825f978e3016f46850 md5: 434ca7e50e40f4918ab701e3facd59a0 depends: - __glibc >=2.17,<3.0.a0 license: LicenseRef-libglvnd purls: [] size: 132463 timestamp: 1731330968309 - conda: https://prefix.dev/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_2.conda sha256: 2d35a679624a93ce5b3e9dd301fff92343db609b79f0363e6d0ceb3a6478bfa7 md5: c8013e438185f33b13814c5c488acd5c depends: - __glibc >=2.17,<3.0.a0 - libglvnd 1.7.0 ha4b6fd6_2 - xorg-libx11 >=1.8.10,<2.0a0 license: LicenseRef-libglvnd purls: [] size: 75504 timestamp: 1731330988898 - conda: https://prefix.dev/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda sha256: 5b3e5e4e9270ecfcd48f47e3a68f037f5ab0f529ccb223e8e5d5ac75a58fc687 md5: 26c46f90d0e727e95c6c9498a33a09f3 depends: - __glibc >=2.17,<3.0.a0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 603284 timestamp: 1765256703881 - conda: https://prefix.dev/conda-forge/win-64/libgomp-15.2.0-h8ee18e1_16.conda sha256: 9c86aadc1bd9740f2aca291da8052152c32dd1c617d5d4fd0f334214960649bb md5: ab8189163748f95d4cb18ea1952943c3 depends: - libwinpthread >=12.0.0.r4.gg4f2fc60ca constrains: - msys2-conda-epoch <0.0a0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 663567 timestamp: 1765260367147 - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-2.39.0-hdb79228_0.conda sha256: d3341cf69cb02c07bbd1837968f993da01b7bd467e816b1559a3ca26c1ff14c5 md5: a2e30ccd49f753fd30de0d30b1569789 depends: - __glibc >=2.17,<3.0.a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcurl >=8.14.1,<9.0a0 - libgcc >=14 - libgrpc >=1.73.1,<1.74.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - libstdcxx >=14 - openssl >=3.5.1,<4.0a0 constrains: - libgoogle-cloud 2.39.0 *_0 license: Apache-2.0 license_family: Apache purls: [] size: 1307909 timestamp: 1752048413383 - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-2.39.0-hed66dea_0.conda sha256: 9b50362bafd60c4a3eb6c37e6dbf7e200562dab7ae1b282b1ebd633d4d77d4bd md5: 06564befaabd2760dfa742e47074bad2 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcurl >=8.14.1,<9.0a0 - libcxx >=19 - libgrpc >=1.73.1,<1.74.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - openssl >=3.5.1,<4.0a0 constrains: - libgoogle-cloud 2.39.0 *_0 license: Apache-2.0 license_family: Apache purls: [] size: 899629 timestamp: 1752048034356 - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-2.39.0-head0a95_0.conda sha256: 209facdb8ea5b68163f146525720768fa3191cef86c82b2538e8c3cafa1e9dd4 md5: ad7272a081abe0966d0297691154eda5 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcurl >=8.14.1,<9.0a0 - libcxx >=19 - libgrpc >=1.73.1,<1.74.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - openssl >=3.5.1,<4.0a0 constrains: - libgoogle-cloud 2.39.0 *_0 license: Apache-2.0 license_family: Apache purls: [] size: 876283 timestamp: 1752047598741 - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-2.39.0-h19ee442_0.conda sha256: 8f5b26e9ea985c819a67e41664da82219534f9b9c8ba190f7d3c440361e5accb md5: c2c512f98c5c666782779439356a1713 depends: - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcurl >=8.14.1,<9.0a0 - libgrpc >=1.73.1,<1.74.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - libgoogle-cloud 2.39.0 *_0 license: Apache-2.0 license_family: Apache purls: [] size: 14952 timestamp: 1752049549178 - conda: https://prefix.dev/conda-forge/linux-64/libgoogle-cloud-storage-2.39.0-hdbdcf42_0.conda sha256: 59eb8365f0aee384f2f3b2a64dcd454f1a43093311aa5f21a8bb4bd3c79a6db8 md5: bd21962ff8a9d1ce4720d42a35a4af40 depends: - __glibc >=2.17,<3.0.a0 - libabseil - libcrc32c >=1.1.2,<1.2.0a0 - libcurl - libgcc >=14 - libgoogle-cloud 2.39.0 hdb79228_0 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - openssl license: Apache-2.0 license_family: Apache purls: [] size: 804189 timestamp: 1752048589800 - conda: https://prefix.dev/conda-forge/osx-64/libgoogle-cloud-storage-2.39.0-h8ac052b_0.conda sha256: fe790fc9ed8ffa468d27e886735fe11844369caee406d98f1da2c0d8aed0401e md5: 7600fb1377c8eb5a161e4a2520933daa depends: - __osx >=11.0 - libabseil - libcrc32c >=1.1.2,<1.2.0a0 - libcurl - libcxx >=19 - libgoogle-cloud 2.39.0 hed66dea_0 - libzlib >=1.3.1,<2.0a0 - openssl license: Apache-2.0 license_family: Apache purls: [] size: 543323 timestamp: 1752048443047 - conda: https://prefix.dev/conda-forge/osx-arm64/libgoogle-cloud-storage-2.39.0-hfa3a374_0.conda sha256: a5160c23b8b231b88d0ff738c7f52b0ee703c4c0517b044b18f4d176e729dfd8 md5: 147a468b9b6c3ced1fccd69b864ae289 depends: - __osx >=11.0 - libabseil - libcrc32c >=1.1.2,<1.2.0a0 - libcurl - libcxx >=19 - libgoogle-cloud 2.39.0 head0a95_0 - libzlib >=1.3.1,<2.0a0 - openssl license: Apache-2.0 license_family: Apache purls: [] size: 525153 timestamp: 1752047915306 - conda: https://prefix.dev/conda-forge/win-64/libgoogle-cloud-storage-2.39.0-he04ea4c_0.conda sha256: 51c29942d9bb856081605352ac74c45cad4fedbaac89de07c74efb69a3be9ab3 md5: 26198e3dc20bbcbea8dd6fa5ab7ea1e0 depends: - libabseil - libcrc32c >=1.1.2,<1.2.0a0 - libcurl - libgoogle-cloud 2.39.0 h19ee442_0 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: Apache purls: [] size: 14904 timestamp: 1752049852815 - conda: https://prefix.dev/conda-forge/linux-64/libgrpc-1.73.1-h3288cfb_1.conda sha256: bc9d32af6167b1f5bcda216dc44eddcb27f3492440571ab12f6e577472a05e34 md5: ff63bb12ac31c176ff257e3289f20770 depends: - __glibc >=2.17,<3.0.a0 - c-ares >=1.34.5,<2.0a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libgcc >=14 - libprotobuf >=6.31.1,<6.31.2.0a0 - libre2-11 >=2025.8.12 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - re2 constrains: - grpc-cpp =1.73.1 license: Apache-2.0 license_family: APACHE purls: [] size: 8349777 timestamp: 1761058442526 - conda: https://prefix.dev/conda-forge/osx-64/libgrpc-1.73.1-h451496d_1.conda sha256: 30378f4c9055224fecd1da8b9a65e2c0293cde68edca0f8a306fd9e92fd6ee1f md5: d6ea2acfae86b523b54938c6bc30e378 depends: - __osx >=11.0 - c-ares >=1.34.5,<2.0a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcxx >=19 - libprotobuf >=6.31.1,<6.31.2.0a0 - libre2-11 >=2025.8.12 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - re2 constrains: - grpc-cpp =1.73.1 license: Apache-2.0 license_family: APACHE purls: [] size: 5468625 timestamp: 1761060387315 - conda: https://prefix.dev/conda-forge/osx-arm64/libgrpc-1.73.1-h3063b79_1.conda sha256: c2099872b1aa06bf8153e35e5b706d2000c1fc16f4dde2735ccd77a0643a4683 md5: f5856b3b9dae4463348a7ec23c1301f2 depends: - __osx >=11.0 - c-ares >=1.34.5,<2.0a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcxx >=19 - libprotobuf >=6.31.1,<6.31.2.0a0 - libre2-11 >=2025.8.12 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - re2 constrains: - grpc-cpp =1.73.1 license: Apache-2.0 license_family: APACHE purls: [] size: 5377798 timestamp: 1761053602943 - conda: https://prefix.dev/conda-forge/win-64/libgrpc-1.73.1-h317e13b_1.conda sha256: 95a83e98c35b8ec03d84f0714eefb2630078d9224360a93dbef6f2403414f76f md5: 855b10d858d6c078a28d670cf32baa67 depends: - c-ares >=1.34.5,<2.0a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - libre2-11 >=2025.8.12 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - re2 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - grpc-cpp =1.73.1 license: Apache-2.0 license_family: APACHE purls: [] size: 14433486 timestamp: 1761053760632 - conda: https://prefix.dev/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda sha256: 8cdf11333a81085468d9aa536ebb155abd74adc293576f6013fc0c85a7a90da3 md5: 3b576f6860f838f950c570f4433b086e depends: - libwinpthread >=12.0.0.r4.gg4f2fc60ca - libxml2 - libxml2-16 >=2.14.6 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-3-Clause license_family: BSD purls: [] size: 2411241 timestamp: 1765104337762 - conda: https://prefix.dev/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f md5: 915f5995e94f60e9a4826e0b0920ee88 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: LGPL-2.1-only purls: [] size: 790176 timestamp: 1754908768807 - conda: https://prefix.dev/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda sha256: a1c8cecdf9966921e13f0ae921309a1f415dfbd2b791f2117cf7e8f5e61a48b6 md5: 210a85a1119f97ea7887188d176db135 depends: - __osx >=10.13 license: LGPL-2.1-only purls: [] size: 737846 timestamp: 1754908900138 - conda: https://prefix.dev/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda sha256: de0336e800b2af9a40bdd694b03870ac4a848161b35c8a2325704f123f185f03 md5: 4d5a7445f0b25b6a3ddbb56e790f5251 depends: - __osx >=11.0 license: LGPL-2.1-only purls: [] size: 750379 timestamp: 1754909073836 - conda: https://prefix.dev/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda sha256: 0dcdb1a5f01863ac4e8ba006a8b0dc1a02d2221ec3319b5915a1863254d7efa7 md5: 64571d1dd6cdcfa25d0664a5950fdaa2 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: LGPL-2.1-only purls: [] size: 696926 timestamp: 1754909290005 - conda: https://prefix.dev/conda-forge/win-64/libintl-0.22.5-h5728263_3.conda sha256: c7e4600f28bcada8ea81456a6530c2329312519efcf0c886030ada38976b0511 md5: 2cf0cf76cc15d360dfa2f17fd6cf9772 depends: - libiconv >=1.17,<2.0a0 license: LGPL-2.1-or-later purls: [] size: 95568 timestamp: 1723629479451 - conda: https://prefix.dev/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda sha256: cc9aba923eea0af8e30e0f94f2ad7156e2984d80d1e8e7fe6be5a1f257f0eb32 md5: 8397539e3a0bbd1695584fb4f927485a depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 constrains: - jpeg <0.0.0a license: IJG AND BSD-3-Clause AND Zlib purls: [] size: 633710 timestamp: 1762094827865 - conda: https://prefix.dev/conda-forge/osx-64/libjpeg-turbo-3.1.2-h8616949_0.conda sha256: ebe2877abc046688d6ea299e80d8322d10c69763f13a102010f90f7168cc5f54 md5: 48dda187f169f5a8f1e5e07701d5cdd9 depends: - __osx >=10.13 constrains: - jpeg <0.0.0a license: IJG AND BSD-3-Clause AND Zlib purls: [] size: 586189 timestamp: 1762095332781 - conda: https://prefix.dev/conda-forge/osx-arm64/libjpeg-turbo-3.1.2-hc919400_0.conda sha256: 6c061c56058bb10374daaef50e81b39cf43e8aee21f0037022c0c39c4f31872f md5: f0695fbecf1006f27f4395d64bd0c4b8 depends: - __osx >=11.0 constrains: - jpeg <0.0.0a license: IJG AND BSD-3-Clause AND Zlib purls: [] size: 551197 timestamp: 1762095054358 - conda: https://prefix.dev/conda-forge/win-64/libjpeg-turbo-3.1.2-hfd05255_0.conda sha256: 795e2d4feb2f7fc4a2c6e921871575feb32b8082b5760726791f080d1e2c2597 md5: 56a686f92ac0273c0f6af58858a3f013 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - jpeg <0.0.0a license: IJG AND BSD-3-Clause AND Zlib purls: [] size: 841783 timestamp: 1762094814336 - conda: https://prefix.dev/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda build_number: 5 sha256: c723b6599fcd4c6c75dee728359ef418307280fa3e2ee376e14e85e5bbdda053 md5: b38076eb5c8e40d0106beda6f95d7609 depends: - libblas 3.11.0 5_h4a7cf45_openblas constrains: - blas 2.305 openblas - liblapacke 3.11.0 5*_openblas - libcblas 3.11.0 5*_openblas license: BSD-3-Clause license_family: BSD purls: [] size: 18200 timestamp: 1765818857876 - conda: https://prefix.dev/conda-forge/osx-64/liblapack-3.11.0-5_h859234e_openblas.conda build_number: 5 sha256: 2c915fe2b3d806d4b82776c882ba66ba3e095e9e2c41cc5c3375bffec6bddfdc md5: eb5b1c25d4ac30813a6ca950a58710d6 depends: - libblas 3.11.0 5_he492b99_openblas constrains: - libcblas 3.11.0 5*_openblas - blas 2.305 openblas - liblapacke 3.11.0 5*_openblas license: BSD-3-Clause license_family: BSD purls: [] size: 18491 timestamp: 1765819090240 - conda: https://prefix.dev/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda build_number: 5 sha256: 735a6e6f7d7da6f718b6690b7c0a8ae4815afb89138aa5793abe78128e951dbb md5: ca9d752201b7fa1225bca036ee300f2b depends: - libblas 3.11.0 5_h51639a9_openblas constrains: - libcblas 3.11.0 5*_openblas - blas 2.305 openblas - liblapacke 3.11.0 5*_openblas license: BSD-3-Clause license_family: BSD purls: [] size: 18551 timestamp: 1765819121855 - conda: https://prefix.dev/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda build_number: 5 sha256: a2d33f5cc2b8a9042f2af6981c6733ab1a661463823eaa56595a9c58c0ab77e1 md5: e62c42a4196dee97d20400612afcb2b1 depends: - libblas 3.11.0 5_hf2e6a31_mkl constrains: - libcblas 3.11.0 5*_mkl - blas 2.305 mkl - liblapacke 3.11.0 5*_mkl license: BSD-3-Clause license_family: BSD purls: [] size: 80225 timestamp: 1765819148014 - conda: https://prefix.dev/conda-forge/linux-64/libllvm21-21.1.8-hf7376ad_0.conda sha256: 91bb4f5be1601b40b4995911d785e29387970f0b3c80f33f7f9028f95335399f md5: 1a2708a460884d6861425b7f9a7bef99 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - libxml2 - libxml2-16 >=2.14.6 - libzlib >=1.3.1,<2.0a0 - zstd >=1.5.7,<1.6.0a0 license: Apache-2.0 WITH LLVM-exception license_family: Apache purls: [] size: 44333366 timestamp: 1765959132513 - conda: https://prefix.dev/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb md5: c7c83eecbb72d88b940c249af56c8b17 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 constrains: - xz 5.8.2.* license: 0BSD purls: [] size: 113207 timestamp: 1768752626120 - conda: https://prefix.dev/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda sha256: 7ab3c98abd3b5d5ec72faa8d9f5d4b50dcee4970ed05339bc381861199dabb41 md5: 688a0c3d57fa118b9c97bf7e471ab46c depends: - __osx >=10.13 constrains: - xz 5.8.2.* license: 0BSD purls: [] size: 105482 timestamp: 1768753411348 - conda: https://prefix.dev/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda sha256: 7bfc7ffb2d6a9629357a70d4eadeadb6f88fa26ebc28f606b1c1e5e5ed99dc7e md5: 009f0d956d7bfb00de86901d16e486c7 depends: - __osx >=11.0 constrains: - xz 5.8.2.* license: 0BSD purls: [] size: 92242 timestamp: 1768752982486 - conda: https://prefix.dev/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda sha256: f25bf293f550c8ed2e0c7145eb404324611cfccff37660869d97abf526eb957c md5: ba0bfd4c3cf73f299ffe46ff0eaeb8e3 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - xz 5.8.2.* license: 0BSD purls: [] size: 106169 timestamp: 1768752763559 - conda: https://prefix.dev/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 md5: 2c21e66f50753a083cbe6b80f38268fa depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: BSD-2-Clause license_family: BSD purls: [] size: 92400 timestamp: 1769482286018 - conda: https://prefix.dev/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda sha256: 1096c740109386607938ab9f09a7e9bca06d86770a284777586d6c378b8fb3fd md5: ec88ba8a245855935b871a7324373105 depends: - __osx >=10.13 license: BSD-2-Clause license_family: BSD purls: [] size: 79899 timestamp: 1769482558610 - conda: https://prefix.dev/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda sha256: 1089c7f15d5b62c622625ec6700732ece83be8b705da8c6607f4dabb0c4bd6d2 md5: 57c4be259f5e0b99a5983799a228ae55 depends: - __osx >=11.0 license: BSD-2-Clause license_family: BSD purls: [] size: 73690 timestamp: 1769482560514 - conda: https://prefix.dev/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda sha256: 40dcd0b9522a6e0af72a9db0ced619176e7cfdb114855c7a64f278e73f8a7514 md5: e4a9fc2bba3b022dad998c78856afe47 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-2-Clause license_family: BSD purls: [] size: 89411 timestamp: 1769482314283 - conda: https://prefix.dev/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda sha256: a4a7dab8db4dc81c736e9a9b42bdfd97b087816e029e221380511960ac46c690 md5: b499ce4b026493a13774bcf0f4c33849 depends: - __glibc >=2.17,<3.0.a0 - c-ares >=1.34.5,<2.0a0 - libev >=4.33,<4.34.0a0 - libev >=4.33,<5.0a0 - libgcc >=14 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.2,<4.0a0 license: MIT license_family: MIT purls: [] size: 666600 timestamp: 1756834976695 - conda: https://prefix.dev/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda sha256: c48d7e1cc927aef83ff9c48ae34dd1d7495c6ccc1edc4a3a6ba6aff1624be9ac md5: e7630cef881b1174d40f3e69a883e55f depends: - __osx >=10.13 - c-ares >=1.34.5,<2.0a0 - libcxx >=19 - libev >=4.33,<4.34.0a0 - libev >=4.33,<5.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.2,<4.0a0 license: MIT license_family: MIT purls: [] size: 605680 timestamp: 1756835898134 - conda: https://prefix.dev/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda sha256: a07cb53b5ffa2d5a18afc6fd5a526a5a53dd9523fbc022148bd2f9395697c46d md5: a4b4dd73c67df470d091312ab87bf6ae depends: - __osx >=11.0 - c-ares >=1.34.5,<2.0a0 - libcxx >=19 - libev >=4.33,<4.34.0a0 - libev >=4.33,<5.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.2,<4.0a0 license: MIT license_family: MIT purls: [] size: 575454 timestamp: 1756835746393 - conda: https://prefix.dev/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 md5: d864d34357c3b65a4b731f78c0801dc4 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 license: LGPL-2.1-only license_family: GPL purls: [] size: 33731 timestamp: 1750274110928 - conda: https://prefix.dev/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda sha256: 3b3f19ced060013c2dd99d9d46403be6d319d4601814c772a3472fe2955612b0 md5: 7c7927b404672409d9917d49bff5f2d6 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 license: LGPL-2.1-or-later purls: [] size: 33418 timestamp: 1734670021371 - conda: https://prefix.dev/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda sha256: 199d79c237afb0d4780ccd2fbf829cea80743df60df4705202558675e07dd2c5 md5: be43915efc66345cccb3c310b6ed0374 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libgfortran - libgfortran5 >=14.3.0 constrains: - openblas >=0.3.30,<0.3.31.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 5927939 timestamp: 1763114673331 - conda: https://prefix.dev/conda-forge/osx-64/libopenblas-0.3.30-openmp_h6006d49_4.conda sha256: ba642353f7f41ab2d2eb6410fbe522238f0f4483bcd07df30b3222b4454ee7cd md5: 9241a65e6e9605e4581a2a8005d7f789 depends: - __osx >=10.13 - libgfortran - libgfortran5 >=14.3.0 - llvm-openmp >=19.1.7 constrains: - openblas >=0.3.30,<0.3.31.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 6268795 timestamp: 1763117623665 - conda: https://prefix.dev/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda sha256: ebbbc089b70bcde87c4121a083c724330f02a690fb9d7c6cd18c30f1b12504fa md5: a6f6d3a31bb29e48d37ce65de54e2df0 depends: - __osx >=11.0 - libgfortran - libgfortran5 >=14.3.0 - llvm-openmp >=19.1.7 constrains: - openblas >=0.3.30,<0.3.31.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 4284132 timestamp: 1768547079205 - conda: https://prefix.dev/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda sha256: 215086c108d80349e96051ad14131b751d17af3ed2cb5a34edd62fa89bfe8ead md5: 7df50d44d4a14d6c31a2c54f2cd92157 depends: - __glibc >=2.17,<3.0.a0 - libglvnd 1.7.0 ha4b6fd6_2 license: LicenseRef-libglvnd purls: [] size: 50757 timestamp: 1731330993524 - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-1.21.0-hb9b0907_1.conda sha256: ba9b09066f9abae9b4c98ffedef444bbbf4c068a094f6c77d70ef6f006574563 md5: 1c0320794855f457dea27d35c4c71e23 depends: - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcurl >=8.14.1,<9.0a0 - libgrpc >=1.73.1,<1.74.0a0 - libopentelemetry-cpp-headers 1.21.0 ha770c72_1 - libprotobuf >=6.31.1,<6.31.2.0a0 - libzlib >=1.3.1,<2.0a0 - nlohmann_json - prometheus-cpp >=1.3.0,<1.4.0a0 constrains: - cpp-opentelemetry-sdk =1.21.0 license: Apache-2.0 license_family: APACHE purls: [] size: 885397 timestamp: 1751782709380 - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-1.21.0-h7d3f41d_1.conda sha256: 94df4129f94dbb17998a60bff0b53c700e6124a6cb67f3047fe7059ebaa7d357 md5: 952dd64cff4a72cadf5e81572a7a81c8 depends: - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcurl >=8.14.1,<9.0a0 - libgrpc >=1.73.1,<1.74.0a0 - libopentelemetry-cpp-headers 1.21.0 h694c41f_1 - libprotobuf >=6.31.1,<6.31.2.0a0 - libzlib >=1.3.1,<2.0a0 - nlohmann_json - prometheus-cpp >=1.3.0,<1.4.0a0 constrains: - cpp-opentelemetry-sdk =1.21.0 license: Apache-2.0 license_family: APACHE purls: [] size: 585875 timestamp: 1751782877386 - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-1.21.0-he15edb5_1.conda sha256: 4bf8f703ddd140fe54d4c8464ac96b28520fbc1083cce52c136a85a854745d5c md5: cbcea547d6d831863ab0a4e164099062 depends: - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcurl >=8.14.1,<9.0a0 - libgrpc >=1.73.1,<1.74.0a0 - libopentelemetry-cpp-headers 1.21.0 hce30654_1 - libprotobuf >=6.31.1,<6.31.2.0a0 - libzlib >=1.3.1,<2.0a0 - nlohmann_json - prometheus-cpp >=1.3.0,<1.4.0a0 constrains: - cpp-opentelemetry-sdk =1.21.0 license: Apache-2.0 license_family: APACHE purls: [] size: 564609 timestamp: 1751782939921 - conda: https://prefix.dev/conda-forge/linux-64/libopentelemetry-cpp-headers-1.21.0-ha770c72_1.conda sha256: b3a1b36d5f92fbbfd7b6426982a99561bdbd7e4adbafca1b7f127c9a5ab0a60f md5: 9e298d76f543deb06eb0f3413675e13a license: Apache-2.0 license_family: APACHE purls: [] size: 363444 timestamp: 1751782679053 - conda: https://prefix.dev/conda-forge/osx-64/libopentelemetry-cpp-headers-1.21.0-h694c41f_1.conda sha256: 5b43ec55305a6fabd8eb37cee06bc3260d3641f260435194837d0b64faa0b355 md5: 62636543478d53b28c1fc5efce346622 license: Apache-2.0 license_family: APACHE purls: [] size: 362175 timestamp: 1751782820895 - conda: https://prefix.dev/conda-forge/osx-arm64/libopentelemetry-cpp-headers-1.21.0-hce30654_1.conda sha256: ce74278453dec1e3c11158ec368c8f1b03862e279b63f79ed01f38567a1174e6 md5: c7df4b2d612208f3a27486c113b6aefc license: Apache-2.0 license_family: APACHE purls: [] size: 363213 timestamp: 1751782889359 - conda: https://prefix.dev/conda-forge/linux-64/libparquet-23.0.0-h7376487_1_cpu.conda build_number: 1 sha256: 2498642c6366d1f141ee4c22e8504e0704bd961a46b091a28674b1b2d63c778d md5: e7562d15926b3cea66a6e3546b133c5d depends: - __glibc >=2.17,<3.0.a0 - libarrow 23.0.0 h2c50142_1_cpu - libgcc >=14 - libstdcxx >=14 - libthrift >=0.22.0,<0.22.1.0a0 - openssl >=3.5.4,<4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 1391319 timestamp: 1769493405333 - conda: https://prefix.dev/conda-forge/osx-64/libparquet-23.0.0-ha0d2768_1_cpu.conda build_number: 1 sha256: f97c0941c91d4739171e084a51ff1ccd56d1ba941ae30fc4d7abd1a2b62bc12c md5: b5d2acb91e5f4fe5fa73ef33794bcd7a depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h8071b21_1_cpu - libcxx >=21 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - libthrift >=0.22.0,<0.22.1.0a0 - openssl >=3.5.4,<4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 1096763 timestamp: 1769493413729 - conda: https://prefix.dev/conda-forge/osx-arm64/libparquet-23.0.0-hcc2992d_1_cpu.conda build_number: 1 sha256: 1cec55158a0346323362c27e9f8115f9e65fb2364053fb20d9e80bca4516b734 md5: 4c1f3011d9a4ef9da705c27873ef7315 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libarrow 23.0.0 h4365f54_1_cpu - libcxx >=21 - libopentelemetry-cpp >=1.21.0,<1.22.0a0 - libprotobuf >=6.31.1,<6.31.2.0a0 - libthrift >=0.22.0,<0.22.1.0a0 - openssl >=3.5.4,<4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 1072584 timestamp: 1769490502928 - conda: https://prefix.dev/conda-forge/win-64/libparquet-23.0.0-h7051d1f_1_cpu.conda build_number: 1 sha256: 762f7a6e06a344b122f0dac3dbd4ec53ae323d45c3fd2fd7412c366acb0a4eed md5: b794aad0d176eda860e9389b34fa536c depends: - libarrow 23.0.0 hcf7e2ff_1_cpu - libthrift >=0.22.0,<0.22.1.0a0 - openssl >=3.5.4,<4.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: APACHE purls: [] size: 947165 timestamp: 1769494675637 - conda: https://prefix.dev/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda sha256: 0bd91de9b447a2991e666f284ae8c722ffb1d84acb594dbd0c031bd656fa32b2 md5: 70e3400cbbfa03e96dcde7fc13e38c7b depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 license: MIT license_family: MIT purls: [] size: 28424 timestamp: 1749901812541 - conda: https://prefix.dev/conda-forge/linux-64/libpng-1.6.54-h421ea60_0.conda sha256: 5de60d34aac848a9991a09fcdea7c0e783d00024aefec279d55e87c0c44742cd md5: d361fa2a59e53b61c2675bfa073e5b7e depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libzlib >=1.3.1,<2.0a0 license: zlib-acknowledgement purls: [] size: 317435 timestamp: 1768285668880 - conda: https://prefix.dev/conda-forge/osx-64/libpng-1.6.54-h07817ec_0.conda sha256: c0efdf9b34132e7d4e0051bf65a97f1b9e1125c7f8a9067a35ec119af367eb38 md5: 3d43dcdfcc3971939c80f855cf2df235 depends: - __osx >=10.13 - libzlib >=1.3.1,<2.0a0 license: zlib-acknowledgement purls: [] size: 298894 timestamp: 1768285676981 - conda: https://prefix.dev/conda-forge/osx-arm64/libpng-1.6.54-h132b30e_0.conda sha256: 1c271c0ec73b69f7570c5da67d0e47ddf7ff079bc1ca2dfaccd267ea39314b06 md5: 1b80fd1eecb98f1cb7de4239f5d7dc15 depends: - __osx >=11.0 - libzlib >=1.3.1,<2.0a0 license: zlib-acknowledgement purls: [] size: 288910 timestamp: 1768285694469 - conda: https://prefix.dev/conda-forge/win-64/libpng-1.6.54-h7351971_0.conda sha256: 6e269361aa18a57bd2e593e480d83d93fc5f839d33d3bfc31b4ffe10edf6751c md5: 638ecb69e44b6a588afd5633e81f9e61 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - libzlib >=1.3.1,<2.0a0 license: zlib-acknowledgement purls: [] size: 383094 timestamp: 1768285706434 - conda: https://prefix.dev/conda-forge/linux-64/libpq-18.1-hb80d175_3.conda sha256: 21adefed86a36622dd500d7862cb980c5bdaab6ed3f4930a9b9afceabc7a6d58 md5: c39da2ad0e7dd600d1eb3146783b057d depends: - __glibc >=2.17,<3.0.a0 - icu >=78.1,<79.0a0 - krb5 >=1.21.3,<1.22.0a0 - libgcc >=14 - openldap >=2.6.10,<2.7.0a0 - openssl >=3.5.4,<4.0a0 license: PostgreSQL purls: [] size: 2761692 timestamp: 1766448056465 - conda: https://prefix.dev/conda-forge/linux-64/libprotobuf-6.31.1-h49aed37_4.conda sha256: 0ef142ac31e6fd59b4af89ac800acb6deb3fbd9cc4ccf070c03cc2c784dc7296 md5: 07479fc04ba3ddd5d9f760ef1635cfa7 depends: - __glibc >=2.17,<3.0.a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libgcc >=14 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 4372578 timestamp: 1766316228461 - conda: https://prefix.dev/conda-forge/osx-64/libprotobuf-6.31.1-hcc66ac3_4.conda sha256: 2058eb9748a6e29a1821fea8aeea48e87d73c83be47b0504ac03914fee944d0e md5: f22705f9ebb3f79832d635c4c2919b15 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcxx >=19 - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 3079808 timestamp: 1766315644973 - conda: https://prefix.dev/conda-forge/osx-arm64/libprotobuf-6.31.1-h98f38fd_4.conda sha256: 505d62fb2a487aff594a30f6c419f8e861fb3a47e25e407dae2779ac4a585b18 md5: 8a6b4281c176f1695ae0015f420e6aa9 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcxx >=19 - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 3131502 timestamp: 1766315339805 - conda: https://prefix.dev/conda-forge/win-64/libprotobuf-6.31.1-hdcda5b4_4.conda sha256: a0f78f254f5833c8ec3ac38caf5dd7d826b5d7496df5aebc4b11baabd741e041 md5: 2031f591ca8c1289838a4f85ea1c7e74 depends: - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-3-Clause license_family: BSD purls: [] size: 7488966 timestamp: 1766316540495 - conda: https://prefix.dev/conda-forge/linux-64/libre2-11-2025.11.05-h7b12aa8_0.conda sha256: eb5d5ef4d12cdf744e0f728b35bca910843c8cf1249f758cf15488ca04a21dbb md5: a30848ebf39327ea078cf26d114cff53 depends: - __glibc >=2.17,<3.0.a0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libgcc >=14 - libstdcxx >=14 constrains: - re2 2025.11.05.* license: BSD-3-Clause license_family: BSD purls: [] size: 211099 timestamp: 1762397758105 - conda: https://prefix.dev/conda-forge/osx-64/libre2-11-2025.11.05-h554ac88_0.conda sha256: 901fb4cfdabf1495e7f080f8e8e218d1ad182c9bcd3cea2862481fef0e9d534f md5: a0237623ed85308cb816c3dcced23db2 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcxx >=19 constrains: - re2 2025.11.05.* license: BSD-3-Clause license_family: BSD purls: [] size: 180107 timestamp: 1762398117273 - conda: https://prefix.dev/conda-forge/osx-arm64/libre2-11-2025.11.05-h91c62da_0.conda sha256: 7b525313ab16415c4a3191ccf59157c3a4520ed762c8ec61fcfb81d27daa4723 md5: 060f099756e6baf2ed51b9065e44eda8 depends: - __osx >=11.0 - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - libcxx >=19 constrains: - re2 2025.11.05.* license: BSD-3-Clause license_family: BSD purls: [] size: 165593 timestamp: 1762398300610 - conda: https://prefix.dev/conda-forge/win-64/libre2-11-2025.11.05-h0eb2380_0.conda sha256: 8eb2c205588e6d751fe387e90f1321ac8bbaef0a12d125a1dd898e925327f8ae md5: 960713477ad3d7f82e5199fa1b940495 depends: - libabseil * cxx17* - libabseil >=20250512.1,<20250513.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - re2 2025.11.05.* license: BSD-3-Clause license_family: BSD purls: [] size: 263996 timestamp: 1762397947932 - conda: https://prefix.dev/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda sha256: 0105bd108f19ea8e6a78d2d994a6d4a8db16d19a41212070d2d1d48a63c34161 md5: a587892d3c13b6621a6091be690dbca2 depends: - libgcc-ng >=12 license: ISC purls: [] size: 205978 timestamp: 1716828628198 - conda: https://prefix.dev/conda-forge/osx-64/libsodium-1.0.20-hfdf4475_0.conda sha256: d3975cfe60e81072666da8c76b993af018cf2e73fe55acba2b5ba0928efaccf5 md5: 6af4b059e26492da6013e79cbcb4d069 depends: - __osx >=10.13 license: ISC purls: [] size: 210249 timestamp: 1716828641383 - conda: https://prefix.dev/conda-forge/osx-arm64/libsodium-1.0.20-h99b78c6_0.conda sha256: fade8223e1e1004367d7101dd17261003b60aa576df6d7802191f8972f7470b1 md5: a7ce36e284c5faaf93c220dfc39e3abd depends: - __osx >=11.0 license: ISC purls: [] size: 164972 timestamp: 1716828607917 - conda: https://prefix.dev/conda-forge/win-64/libsodium-1.0.20-hc70643c_0.conda sha256: 7bcb3edccea30f711b6be9601e083ecf4f435b9407d70fc48fbcf9e5d69a0fc6 md5: 198bb594f202b205c7d18b936fa4524f depends: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: ISC purls: [] size: 202344 timestamp: 1716828757533 - conda: https://prefix.dev/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda sha256: 04596fcee262a870e4b7c9807224680ff48d4d0cc0dac076a602503d3dc6d217 md5: da5be73701eecd0e8454423fd6ffcf30 depends: - __glibc >=2.17,<3.0.a0 - icu >=78.2,<79.0a0 - libgcc >=14 - libzlib >=1.3.1,<2.0a0 license: blessing purls: [] size: 942808 timestamp: 1768147973361 - conda: https://prefix.dev/conda-forge/osx-64/libsqlite-3.51.2-hb99441e_0.conda sha256: 710a7ea27744199023c92e66ad005de7f8db9cf83f10d5a943d786f0dac53b7c md5: d910105ce2b14dfb2b32e92ec7653420 depends: - __osx >=10.13 - libzlib >=1.3.1,<2.0a0 license: blessing purls: [] size: 987506 timestamp: 1768148247615 - conda: https://prefix.dev/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda sha256: 6e9b9f269732cbc4698c7984aa5b9682c168e2a8d1e0406e1ff10091ca046167 md5: 4b0bf313c53c3e89692f020fb55d5f2c depends: - __osx >=11.0 - icu >=78.2,<79.0a0 - libzlib >=1.3.1,<2.0a0 license: blessing purls: [] size: 909777 timestamp: 1768148320535 - conda: https://prefix.dev/conda-forge/win-64/libsqlite-3.51.2-hf5d6505_0.conda sha256: 756478128e3e104bd7e7c3ce6c1b0efad7e08c7320c69fdc726e039323c63fbb md5: 903979414b47d777d548e5f0165e6cd8 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: blessing purls: [] size: 1291616 timestamp: 1768148278261 - conda: https://prefix.dev/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda sha256: fa39bfd69228a13e553bd24601332b7cfeb30ca11a3ca50bb028108fe90a7661 md5: eecce068c7e4eddeb169591baac20ac4 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.0,<4.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 304790 timestamp: 1745608545575 - conda: https://prefix.dev/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda sha256: 00654ba9e5f73aa1f75c1f69db34a19029e970a4aeb0fa8615934d8e9c369c3c md5: a6cb15db1c2dc4d3a5f6cf3772e09e81 depends: - __osx >=10.13 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.0,<4.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 284216 timestamp: 1745608575796 - conda: https://prefix.dev/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda sha256: 8bfe837221390ffc6f111ecca24fa12d4a6325da0c8d131333d63d6c37f27e0a md5: b68e8f66b94b44aaa8de4583d3d4cc40 depends: - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.0,<4.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 279193 timestamp: 1745608793272 - conda: https://prefix.dev/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda sha256: cbdf93898f2e27cefca5f3fe46519335d1fab25c4ea2a11b11502ff63e602c09 md5: 9dce2f112bfd3400f4f432b3d0ac07b2 depends: - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.0,<4.0a0 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: BSD-3-Clause license_family: BSD purls: [] size: 292785 timestamp: 1745608759342 - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda sha256: 813427918316a00c904723f1dfc3da1bbc1974c5cfe1ed1e704c6f4e0798cbc6 md5: 68f68355000ec3f1d6f26ea13e8f525f depends: - __glibc >=2.17,<3.0.a0 - libgcc 15.2.0 he0feb66_16 constrains: - libstdcxx-ng ==15.2.0=*_16 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 5856456 timestamp: 1765256838573 - conda: https://prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_16.conda sha256: 81f2f246c7533b41c5e0c274172d607829019621c4a0823b5c0b4a8c7028ee84 md5: 1b3152694d236cf233b76b8c56bf0eae depends: - libstdcxx 15.2.0 h934c35e_16 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] size: 27300 timestamp: 1765256885128 - conda: https://prefix.dev/conda-forge/linux-64/libthrift-0.22.0-h454ac66_1.conda sha256: 4888b9ea2593c36ca587a5ebe38d0a56a0e6d6a9e4bb7da7d9a326aaaca7c336 md5: 8ed82d90e6b1686f5e98f8b7825a15ef depends: - __glibc >=2.17,<3.0.a0 - libevent >=2.1.12,<2.1.13.0a0 - libgcc >=14 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.1,<4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 424208 timestamp: 1753277183984 - conda: https://prefix.dev/conda-forge/osx-64/libthrift-0.22.0-h687e942_1.conda sha256: a0f9fdc663db089fde4136a0bd6c819d7f8daf869fc3ca8582201412e47f298c md5: 69251ed374b31a5664bf5ba58626f3b7 depends: - __osx >=10.13 - libcxx >=19 - libevent >=2.1.12,<2.1.13.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.1,<4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 331822 timestamp: 1753277335578 - conda: https://prefix.dev/conda-forge/osx-arm64/libthrift-0.22.0-h14a376c_1.conda sha256: 8b703f2c6e47ed5886d7298601b9416b59e823fc8d1a8fa867192c94c5911aac md5: 3161023bb2f8c152e4c9aa59bdd40975 depends: - __osx >=11.0 - libcxx >=19 - libevent >=2.1.12,<2.1.13.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.1,<4.0a0 license: Apache-2.0 license_family: APACHE purls: [] size: 323360 timestamp: 1753277264380 - conda: https://prefix.dev/conda-forge/win-64/libthrift-0.22.0-h23985f6_1.conda sha256: 87516b128ffa497fc607d5da0cc0366dbee1dbcc14c962bf9ea951d480c7698b md5: 556d49ad5c2ad553c2844cc570bb71c7 depends: - libevent >=2.1.12,<2.1.13.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.1,<4.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: APACHE purls: [] size: 636513 timestamp: 1753277481158 - conda: https://prefix.dev/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 md5: cd5a90476766d53e901500df9215e927 depends: - __glibc >=2.17,<3.0.a0 - lerc >=4.0.0,<5.0a0 - libdeflate >=1.25,<1.26.0a0 - libgcc >=14 - libjpeg-turbo >=3.1.0,<4.0a0 - liblzma >=5.8.1,<6.0a0 - libstdcxx >=14 - libwebp-base >=1.6.0,<2.0a0 - libzlib >=1.3.1,<2.0a0 - zstd >=1.5.7,<1.6.0a0 license: HPND purls: [] size: 435273 timestamp: 1762022005702 - conda: https://prefix.dev/conda-forge/osx-64/libtiff-4.7.1-ha0a348c_1.conda sha256: e53424c34147301beae2cd9223ebf593720d94c038b3f03cacd0535e12c9668e md5: 9d4344f94de4ab1330cdc41c40152ea6 depends: - __osx >=10.13 - lerc >=4.0.0,<5.0a0 - libcxx >=19 - libdeflate >=1.25,<1.26.0a0 - libjpeg-turbo >=3.1.0,<4.0a0 - liblzma >=5.8.1,<6.0a0 - libwebp-base >=1.6.0,<2.0a0 - libzlib >=1.3.1,<2.0a0 - zstd >=1.5.7,<1.6.0a0 license: HPND purls: [] size: 404591 timestamp: 1762022511178 - conda: https://prefix.dev/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda sha256: e9248077b3fa63db94caca42c8dbc6949c6f32f94d1cafad127f9005d9b1507f md5: e2a72ab2fa54ecb6abab2b26cde93500 depends: - __osx >=11.0 - lerc >=4.0.0,<5.0a0 - libcxx >=19 - libdeflate >=1.25,<1.26.0a0 - libjpeg-turbo >=3.1.0,<4.0a0 - liblzma >=5.8.1,<6.0a0 - libwebp-base >=1.6.0,<2.0a0 - libzlib >=1.3.1,<2.0a0 - zstd >=1.5.7,<1.6.0a0 license: HPND purls: [] size: 373892 timestamp: 1762022345545 - conda: https://prefix.dev/conda-forge/win-64/libtiff-4.7.1-h8f73337_1.conda sha256: f1b8cccaaeea38a28b9cd496694b2e3d372bb5be0e9377c9e3d14b330d1cba8a md5: 549845d5133100142452812feb9ba2e8 depends: - lerc >=4.0.0,<5.0a0 - libdeflate >=1.25,<1.26.0a0 - libjpeg-turbo >=3.1.0,<4.0a0 - liblzma >=5.8.1,<6.0a0 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - zstd >=1.5.7,<1.6.0a0 license: HPND purls: [] size: 993166 timestamp: 1762022118895 - conda: https://prefix.dev/conda-forge/linux-64/libutf8proc-2.11.3-hfe17d71_0.conda sha256: ecbf4b7520296ed580498dc66a72508b8a79da5126e1d6dc650a7087171288f9 md5: 1247168fe4a0b8912e3336bccdbf98a5 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 85969 timestamp: 1768735071295 - conda: https://prefix.dev/conda-forge/osx-64/libutf8proc-2.11.3-hc282952_0.conda sha256: 626db214208e8da6aa9a904518a0442e5bff7b4602cc295dd5ce1f4a98844c1d md5: 2c49b6f6ec9a510bbb75ecbd2a572697 depends: - __osx >=10.13 license: MIT license_family: MIT purls: [] size: 84535 timestamp: 1768735249136 - conda: https://prefix.dev/conda-forge/osx-arm64/libutf8proc-2.11.3-h2431656_0.conda sha256: ae1a82e62cd4e3c18e005ae7ff4358ed72b2bfbfe990d5a6a5587f81e9a100dc md5: 2255add2f6ae77d0a96624a5cbde6d45 depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 87916 timestamp: 1768735311947 - conda: https://prefix.dev/conda-forge/win-64/libutf8proc-2.11.3-hb980946_0.conda sha256: 5d82af0779eab283416240da792a0d2fe4f8213c447e9f04aeaab1801468a90c md5: 5f34fcb6578ea9bdbfd53cc2cfb88200 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 89061 timestamp: 1768735187639 - conda: https://prefix.dev/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee md5: db409b7c1720428638e7c0d509d3e1b5 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: BSD-3-Clause license_family: BSD purls: [] size: 40311 timestamp: 1766271528534 - conda: https://prefix.dev/conda-forge/linux-64/libvulkan-loader-1.4.328.1-h5279c79_0.conda sha256: bbabc5c48b63ff03f440940a11d4648296f5af81bb7630d98485405cd32ac1ce md5: 372a62464d47d9e966b630ffae3abe73 depends: - __glibc >=2.17,<3.0.a0 - libstdcxx >=14 - libgcc >=14 - xorg-libx11 >=1.8.12,<2.0a0 - xorg-libxrandr >=1.5.4,<2.0a0 constrains: - libvulkan-headers 1.4.328.1.* license: Apache-2.0 license_family: APACHE purls: [] size: 197672 timestamp: 1759972155030 - conda: https://prefix.dev/conda-forge/win-64/libvulkan-loader-1.4.328.1-h477610d_0.conda sha256: 934d676c445c1ea010753dfa98680b36a72f28bec87d15652f013c91a1d8d171 md5: 4403eae6c81f448d63a7f66c0b330536 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 constrains: - libvulkan-headers 1.4.328.1.* license: Apache-2.0 license_family: APACHE purls: [] size: 280488 timestamp: 1759972163692 - conda: https://prefix.dev/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b md5: aea31d2e5b1091feca96fcfe945c3cf9 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 constrains: - libwebp 1.6.0 license: BSD-3-Clause license_family: BSD purls: [] size: 429011 timestamp: 1752159441324 - conda: https://prefix.dev/conda-forge/osx-64/libwebp-base-1.6.0-hb807250_0.conda sha256: 00dbfe574b5d9b9b2b519acb07545380a6bc98d1f76a02695be4995d4ec91391 md5: 7bb6608cf1f83578587297a158a6630b depends: - __osx >=10.13 constrains: - libwebp 1.6.0 license: BSD-3-Clause license_family: BSD purls: [] size: 365086 timestamp: 1752159528504 - conda: https://prefix.dev/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda sha256: a4de3f371bb7ada325e1f27a4ef7bcc81b2b6a330e46fac9c2f78ac0755ea3dd md5: e5e7d467f80da752be17796b87fe6385 depends: - __osx >=11.0 constrains: - libwebp 1.6.0 license: BSD-3-Clause license_family: BSD purls: [] size: 294974 timestamp: 1752159906788 - conda: https://prefix.dev/conda-forge/win-64/libwebp-base-1.6.0-h4d5522a_0.conda sha256: 7b6316abfea1007e100922760e9b8c820d6fc19df3f42fb5aca684cfacb31843 md5: f9bbae5e2537e3b06e0f7310ba76c893 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - libwebp 1.6.0 license: BSD-3-Clause license_family: BSD purls: [] size: 279176 timestamp: 1752159543911 - conda: https://prefix.dev/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda sha256: 0fccf2d17026255b6e10ace1f191d0a2a18f2d65088fd02430be17c701f8ffe0 md5: 8a86073cf3b343b87d03f41790d8b4e5 depends: - ucrt constrains: - pthreads-win32 <0.0a0 - msys2-conda-epoch <0.0a0 license: MIT AND BSD-3-Clause-Clear purls: [] size: 36621 timestamp: 1759768399557 - conda: https://prefix.dev/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa md5: 92ed62436b625154323d40d5f2f11dd7 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - pthread-stubs - xorg-libxau >=1.0.11,<2.0a0 - xorg-libxdmcp license: MIT license_family: MIT purls: [] size: 395888 timestamp: 1727278577118 - conda: https://prefix.dev/conda-forge/osx-64/libxcb-1.17.0-hf1f96e2_0.conda sha256: 8896cd5deff6f57d102734f3e672bc17120613647288f9122bec69098e839af7 md5: bbeca862892e2898bdb45792a61c4afc depends: - __osx >=10.13 - pthread-stubs - xorg-libxau >=1.0.11,<2.0a0 - xorg-libxdmcp license: MIT license_family: MIT purls: [] size: 323770 timestamp: 1727278927545 - conda: https://prefix.dev/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda sha256: bd3816218924b1e43b275863e21a3e13a5db4a6da74cca8e60bc3c213eb62f71 md5: af523aae2eca6dfa1c8eec693f5b9a79 depends: - __osx >=11.0 - pthread-stubs - xorg-libxau >=1.0.11,<2.0a0 - xorg-libxdmcp license: MIT license_family: MIT purls: [] size: 323658 timestamp: 1727278733917 - conda: https://prefix.dev/conda-forge/win-64/libxcb-1.17.0-h0e4246c_0.conda sha256: 08dec73df0e161c96765468847298a420933a36bc4f09b50e062df8793290737 md5: a69bbf778a462da324489976c84cfc8c depends: - libgcc >=13 - libwinpthread >=12.0.0.r4.gg4f2fc60ca - pthread-stubs - ucrt >=10.0.20348.0 - xorg-libxau >=1.0.11,<2.0a0 - xorg-libxdmcp license: MIT license_family: MIT purls: [] size: 1208687 timestamp: 1727279378819 - conda: https://prefix.dev/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c md5: 5aa797f8787fe7a17d1b0821485b5adc depends: - libgcc-ng >=12 license: LGPL-2.1-or-later purls: [] size: 100393 timestamp: 1702724383534 - conda: https://prefix.dev/conda-forge/linux-64/libxkbcommon-1.13.1-hca5e8e5_0.conda sha256: d2195b5fbcb0af1ff7b345efdf89290c279b8d1d74f325ae0ac98148c375863c md5: 2bca1fbb221d9c3c8e3a155784bbc2e9 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - libxcb >=1.17.0,<2.0a0 - libxml2 - libxml2-16 >=2.14.6 - xkeyboard-config - xorg-libxau >=1.0.12,<2.0a0 license: MIT/X11 Derivative license_family: MIT purls: [] size: 837922 timestamp: 1764794163823 - conda: https://prefix.dev/conda-forge/linux-64/libxml2-2.15.1-he237659_1.conda sha256: 047be059033c394bd32ae5de66ce389824352120b3a7c0eff980195f7ed80357 md5: 417955234eccd8f252b86a265ccdab7f depends: - __glibc >=2.17,<3.0.a0 - icu >=78.1,<79.0a0 - libgcc >=14 - libiconv >=1.18,<2.0a0 - liblzma >=5.8.1,<6.0a0 - libxml2-16 2.15.1 hca6bf5a_1 - libzlib >=1.3.1,<2.0a0 license: MIT license_family: MIT purls: [] size: 45402 timestamp: 1766327161688 - conda: https://prefix.dev/conda-forge/osx-64/libxml2-2.15.1-h745d5cb_1.conda sha256: 96fe14f775ae1bd9a3c464898fbc3fa6d784b867eadcf7d58a2d510d80a6fbfb md5: 1fd2c75a8a9adc629983ed629dec42e1 depends: - __osx >=10.13 - libiconv >=1.18,<2.0a0 - liblzma >=5.8.1,<6.0a0 - libxml2-16 2.15.1 hd57b93d_1 - libzlib >=1.3.1,<2.0a0 constrains: - icu <0.0a0 license: MIT license_family: MIT purls: [] size: 40460 timestamp: 1766327727478 - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-2.15.1-h8d039ee_1.conda sha256: 59f96fa27cce6a9a27414c5bb301eedda1a1b85cd0d8f5d68f77e46b86e7c95f md5: fd804ee851e20faca4fecc7df0901d07 depends: - __osx >=11.0 - icu >=78.1,<79.0a0 - libiconv >=1.18,<2.0a0 - liblzma >=5.8.1,<6.0a0 - libxml2-16 2.15.1 h5ef1a60_1 - libzlib >=1.3.1,<2.0a0 license: MIT license_family: MIT purls: [] size: 40607 timestamp: 1766327501392 - conda: https://prefix.dev/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda sha256: 8b47d5fb00a6ccc0f495d16787ab5f37a434d51965584d6000966252efecf56d md5: 68dc154b8d415176c07b6995bd3a65d9 depends: - icu >=78.1,<79.0a0 - libiconv >=1.18,<2.0a0 - liblzma >=5.8.1,<6.0a0 - libxml2-16 2.15.1 h3cfd58e_1 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 43387 timestamp: 1766327259710 - conda: https://prefix.dev/conda-forge/linux-64/libxml2-16-2.15.1-hca6bf5a_1.conda sha256: 8331284bf9ae641b70cdc0e5866502dd80055fc3b9350979c74bb1d192e8e09e md5: 3fdd8d99683da9fe279c2f4cecd1e048 depends: - __glibc >=2.17,<3.0.a0 - icu >=78.1,<79.0a0 - libgcc >=14 - libiconv >=1.18,<2.0a0 - liblzma >=5.8.1,<6.0a0 - libzlib >=1.3.1,<2.0a0 constrains: - libxml2 2.15.1 license: MIT license_family: MIT purls: [] size: 555747 timestamp: 1766327145986 - conda: https://prefix.dev/conda-forge/osx-64/libxml2-16-2.15.1-hd57b93d_1.conda sha256: abdeaea43d0e882679942cc2385342d701873e18669828e40637a70a140ce614 md5: 060f6892620dc862f3b54b9b2da8f177 depends: - __osx >=10.13 - libiconv >=1.18,<2.0a0 - liblzma >=5.8.1,<6.0a0 - libzlib >=1.3.1,<2.0a0 constrains: - libxml2 2.15.1 - icu <0.0a0 license: MIT license_family: MIT purls: [] size: 493505 timestamp: 1766327696842 - conda: https://prefix.dev/conda-forge/osx-arm64/libxml2-16-2.15.1-h5ef1a60_1.conda sha256: 2d5ab15113b0ba21f4656d387d26ab59e4fbaf3027f5e58a2a4fe370821eb106 md5: 7eed1026708e26ee512f43a04d9d0027 depends: - __osx >=11.0 - icu >=78.1,<79.0a0 - libiconv >=1.18,<2.0a0 - liblzma >=5.8.1,<6.0a0 - libzlib >=1.3.1,<2.0a0 constrains: - libxml2 2.15.1 license: MIT license_family: MIT purls: [] size: 464886 timestamp: 1766327479416 - conda: https://prefix.dev/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda sha256: a857e941156b7f462063e34e086d212c6ccbc1521ebdf75b9ed66bd90add57dc md5: 07d73826fde28e7dbaec52a3297d7d26 depends: - icu >=78.1,<79.0a0 - libiconv >=1.18,<2.0a0 - liblzma >=5.8.1,<6.0a0 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - libxml2 2.15.1 license: MIT license_family: MIT purls: [] size: 518964 timestamp: 1766327232819 - conda: https://prefix.dev/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda sha256: 0694760a3e62bdc659d90a14ae9c6e132b525a7900e59785b18a08bb52a5d7e5 md5: 87e6096ec6d542d1c1f8b33245fe8300 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libxml2 - libxml2-16 >=2.14.6 license: MIT license_family: MIT purls: [] size: 245434 timestamp: 1757963724977 - conda: https://prefix.dev/conda-forge/win-64/libxslt-1.1.43-h0fbe4c1_1.conda sha256: 13da38939c2c20e7112d683ab6c9f304bfaf06230a2c6a7cf00359da1a003ec7 md5: 46034d9d983edc21e84c0b36f1b4ba61 depends: - libxml2 - libxml2-16 >=2.14.6 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] size: 420223 timestamp: 1757963935611 - conda: https://prefix.dev/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4 md5: edb0dca6bc32e4f4789199455a1dbeb8 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 constrains: - zlib 1.3.1 *_2 license: Zlib license_family: Other purls: [] size: 60963 timestamp: 1727963148474 - conda: https://prefix.dev/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda sha256: 8412f96504fc5993a63edf1e211d042a1fd5b1d51dedec755d2058948fcced09 md5: 003a54a4e32b02f7355b50a837e699da depends: - __osx >=10.13 constrains: - zlib 1.3.1 *_2 license: Zlib license_family: Other purls: [] size: 57133 timestamp: 1727963183990 - conda: https://prefix.dev/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b md5: 369964e85dc26bfe78f41399b366c435 depends: - __osx >=11.0 constrains: - zlib 1.3.1 *_2 license: Zlib license_family: Other purls: [] size: 46438 timestamp: 1727963202283 - conda: https://prefix.dev/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda sha256: ba945c6493449bed0e6e29883c4943817f7c79cbff52b83360f7b341277c6402 md5: 41fbfac52c601159df6c01f875de31b9 depends: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 constrains: - zlib 1.3.1 *_2 license: Zlib license_family: Other purls: [] size: 55476 timestamp: 1727963768015 - conda: https://prefix.dev/conda-forge/linux-64/llvm-openmp-21.1.8-h4922eb0_0.conda sha256: a5a7ad16eecbe35cac63e529ea9c261bef4ccdd68cb1db247409f04529423989 md5: f8640b709b37dc7758ddce45ea18d000 depends: - __glibc >=2.17,<3.0.a0 constrains: - intel-openmp <0.0a0 - openmp 21.1.8|21.1.8.* license: Apache-2.0 WITH LLVM-exception license_family: APACHE purls: [] size: 6127279 timestamp: 1765964409311 - conda: https://prefix.dev/conda-forge/osx-64/llvm-openmp-21.1.8-h472b3d1_0.conda sha256: 2a41885f44cbc1546ff26369924b981efa37a29d20dc5445b64539ba240739e6 md5: e2d811e9f464dd67398b4ce1f9c7c872 depends: - __osx >=10.13 constrains: - openmp 21.1.8|21.1.8.* - intel-openmp <0.0a0 license: Apache-2.0 WITH LLVM-exception license_family: APACHE purls: [] size: 311405 timestamp: 1765965194247 - conda: https://prefix.dev/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda sha256: 56bcd20a0a44ddd143b6ce605700fdf876bcf5c509adc50bf27e76673407a070 md5: 206ad2df1b5550526e386087bef543c7 depends: - __osx >=11.0 constrains: - openmp 21.1.8|21.1.8.* - intel-openmp <0.0a0 license: Apache-2.0 WITH LLVM-exception license_family: APACHE purls: [] size: 285974 timestamp: 1765964756583 - conda: https://prefix.dev/conda-forge/win-64/llvm-openmp-21.1.8-h4fa8253_0.conda sha256: 145c4370abe870f10987efa9fc15a8383f1dab09abbc9ad4ff15a55d45658f7b md5: 0d8b425ac862bcf17e4b28802c9351cb depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - intel-openmp <0.0a0 - openmp 21.1.8|21.1.8.* license: Apache-2.0 WITH LLVM-exception license_family: APACHE purls: [] size: 347566 timestamp: 1765964942856 - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py311h41a00d4_0.conda sha256: d33d455c85366f409f26a4186bdf9c08ccc2f068d3cf5da48e9daa31457707a7 md5: cc330c606421fa13d1139e9766259ae3 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/llvmlite?source=hash-mapping size: 34122298 timestamp: 1765280000806 - conda: https://prefix.dev/conda-forge/linux-64/llvmlite-0.46.0-py313hdd307be_0.conda sha256: 0e1bc6ee1c7885cc26c37fcd1a2095169a4e4e148860c600d3f685b6a4f32322 md5: d99ac09b331711fd12e16323ca8d96e4 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/llvmlite?source=hash-mapping size: 34130706 timestamp: 1765280056189 - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py311hb26b958_0.conda sha256: 2146071a51d9a798e39fc3a73b4eaede9a8af984f1460922331c2c739bc88656 md5: 52b906dd9165022aca24a9e709a3eaec depends: - __osx >=10.13 - libcxx >=19 - libzlib >=1.3.1,<2.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/llvmlite?source=hash-mapping size: 26027825 timestamp: 1765280531363 - conda: https://prefix.dev/conda-forge/osx-64/llvmlite-0.46.0-py313h590e1ab_0.conda sha256: f1549261f0f2f24c2dd2c7a613b465c0c3e4e1158c43a72224c228aa0b5cb76f md5: ab9fe8b3937e90b22a18554c3d961e97 depends: - __osx >=10.13 - libcxx >=19 - libzlib >=1.3.1,<2.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/llvmlite?source=hash-mapping size: 26010458 timestamp: 1765280511277 - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py311h27de090_0.conda sha256: 985922b7446257024a5d2b6590daa5244089ad990328b7fda30c878d786f3a1b md5: 2d29e8972651bb3cb593586becb090bc depends: - __osx >=11.0 - libcxx >=19 - libzlib >=1.3.1,<2.0a0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/llvmlite?source=hash-mapping size: 24342987 timestamp: 1765280427548 - conda: https://prefix.dev/conda-forge/osx-arm64/llvmlite-0.46.0-py313he297ed2_0.conda sha256: d59fdc5a5682e3f6c17f1c8dc73019afaf6724f4ecd10878515438ca35683269 md5: 81f05ab2abc842253505133ffa652bf5 depends: - __osx >=11.0 - libcxx >=19 - libzlib >=1.3.1,<2.0a0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/llvmlite?source=hash-mapping size: 24338921 timestamp: 1765280468997 - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py311h4f568be_0.conda sha256: 96ee4c055b01c924a7b5c1878d69cab4d5d75d087f9bdfca29d48e8f8b9a2cee md5: 87e10015dba9f19bd31bea6ce3ad0a90 depends: - libzlib >=1.3.1,<2.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/llvmlite?source=hash-mapping size: 22905780 timestamp: 1765280200948 - conda: https://prefix.dev/conda-forge/win-64/llvmlite-0.46.0-py313h5c49287_0.conda sha256: e0da49a4388c6a906a498766b4636a38d8173aee919d12843ae448c44d78384d md5: e0908ac3f4ae20a4957fe1898644f42a depends: - libzlib >=1.3.1,<2.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/llvmlite?source=hash-mapping size: 22885319 timestamp: 1765280139042 - conda: https://prefix.dev/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 sha256: 9afe0b5cfa418e8bdb30d8917c5a6cec10372b037924916f1f85b9f4899a67a6 md5: 91e27ef3d05cc772ce627e51cff111c4 depends: - python >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/locket?source=hash-mapping size: 8250 timestamp: 1650660473123 - conda: https://prefix.dev/conda-forge/linux-64/lz4-4.4.5-py311h1c460e0_1.conda sha256: a3c5fc64083cd168a65b0e5f8866e46edaeded85ed75f85a6c4dec9071447d5a md5: 987c0686ab1d618850db2fb0f837a88d depends: - python - lz4-c - libgcc >=14 - __glibc >=2.17,<3.0.a0 - python_abi 3.11.* *_cp311 - lz4-c >=1.10.0,<1.11.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/lz4?source=hash-mapping size: 44524 timestamp: 1765026393198 - conda: https://prefix.dev/conda-forge/linux-64/lz4-4.4.5-py313h28739b2_1.conda sha256: cbc82f4fa7587376c038d2f0471a73efa7ade4439857b04a0cc839262f1de6e5 md5: e69ad33075938ba81e43311da86b809c depends: - python - lz4-c - libgcc >=14 - __glibc >=2.17,<3.0.a0 - python_abi 3.13.* *_cp313 - lz4-c >=1.10.0,<1.11.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/lz4?source=hash-mapping size: 44861 timestamp: 1765026393230 - conda: https://prefix.dev/conda-forge/osx-64/lz4-4.4.5-py311h14c9969_1.conda sha256: 19c210ec7daea8a550b26810e3ea319e35b121fbf7b3527a8653c4d480b03038 md5: 642519b502f1a539b6f71c9a19795f48 depends: - python - lz4-c - __osx >=10.13 - python_abi 3.11.* *_cp311 - lz4-c >=1.10.0,<1.11.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/lz4?source=hash-mapping size: 42366 timestamp: 1765026420002 - conda: https://prefix.dev/conda-forge/osx-64/lz4-4.4.5-py313hab77a93_1.conda sha256: a35f5d5225d4c6dd13e229881d3013e18f0e3a372bb6e3d9bf299fc832309143 md5: 6838efa78f5071775a7766062cfc85d2 depends: - python - lz4-c - __osx >=10.13 - python_abi 3.13.* *_cp313 - lz4-c >=1.10.0,<1.11.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/lz4?source=hash-mapping size: 42939 timestamp: 1765026491273 - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-4.4.5-py311h3f5a5ee_1.conda sha256: 173811f8706951db03a11f1548c3c89d4bd7a6a1d29cfc7fbfa4430b564ab3be md5: b653c160eba83c3e2b41127e90defb3e depends: - python - lz4-c - __osx >=11.0 - python 3.11.* *_cpython - python_abi 3.11.* *_cp311 - lz4-c >=1.10.0,<1.11.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/lz4?source=hash-mapping size: 126356 timestamp: 1765026418242 - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-4.4.5-py313hd065f0a_1.conda sha256: 71dfac3971dcd134c8a31b3f670d00b8d551e275fb386568ec11ab68d95fe540 md5: ece4dab2afb98b065b69ce769a5c6c42 depends: - python - lz4-c - python 3.13.* *_cp313 - __osx >=11.0 - lz4-c >=1.10.0,<1.11.0a0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/lz4?source=hash-mapping size: 126950 timestamp: 1765026420116 - conda: https://prefix.dev/conda-forge/win-64/lz4-4.4.5-py311ha034993_1.conda sha256: 2185e2c0425d5da5bc1b7b7637165f5f6011c8de59a99ee27ed575a4fda1e305 md5: 26fe9645973d644884ac1859da2f2d2e depends: - python - lz4-c - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.11.* *_cp311 - lz4-c >=1.10.0,<1.11.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/lz4?source=hash-mapping size: 45928 timestamp: 1765026435684 - conda: https://prefix.dev/conda-forge/win-64/lz4-4.4.5-py313h4bbca4b_1.conda sha256: c00d35e5228ac375658495e86d33e1daa819ed11161034a5799dcb07bfa328c9 md5: e8df314d3f3fa27e935b6cb449d754f3 depends: - python - lz4-c - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - lz4-c >=1.10.0,<1.11.0a0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/lz4?source=hash-mapping size: 46606 timestamp: 1765026422655 - conda: https://prefix.dev/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda sha256: 47326f811392a5fd3055f0f773036c392d26fdb32e4d8e7a8197eed951489346 md5: 9de5350a85c4a20c685259b889aa6393 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - libstdcxx >=13 license: BSD-2-Clause license_family: BSD purls: [] size: 167055 timestamp: 1733741040117 - conda: https://prefix.dev/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda sha256: 8da3c9d4b596e481750440c0250a7e18521e7f69a47e1c8415d568c847c08a1c md5: d6b9bd7e356abd7e3a633d59b753495a depends: - __osx >=10.13 - libcxx >=18 license: BSD-2-Clause license_family: BSD purls: [] size: 159500 timestamp: 1733741074747 - conda: https://prefix.dev/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda sha256: 94d3e2a485dab8bdfdd4837880bde3dd0d701e2b97d6134b8806b7c8e69c8652 md5: 01511afc6cc1909c5303cf31be17b44f depends: - __osx >=11.0 - libcxx >=18 license: BSD-2-Clause license_family: BSD purls: [] size: 148824 timestamp: 1733741047892 - conda: https://prefix.dev/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda sha256: 632cf3bdaf7a7aeb846de310b6044d90917728c73c77f138f08aa9438fc4d6b5 md5: 0b69331897a92fac3d8923549d48d092 depends: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: BSD-2-Clause license_family: BSD purls: [] size: 139891 timestamp: 1733741168264 - conda: https://prefix.dev/conda-forge/noarch/markdown-3.10.1-pyhcf101f3_0.conda sha256: 40e45b3e57a6b3c61e9ca0bf8526fec9814dca2be4115245966946e1192983ef md5: 8a5f9a177a2ea05c66237e6f2eaece60 depends: - importlib-metadata >=4.4 - python >=3.10 - python license: BSD-3-Clause license_family: BSD size: 85359 timestamp: 1769079901411 - conda: https://prefix.dev/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda sha256: 7b1da4b5c40385791dbc3cc85ceea9fad5da680a27d5d3cb8bfaa185e304a89e md5: 5b5203189eb668f042ac2b0826244964 depends: - mdurl >=0.1,<1 - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/markdown-it-py?source=hash-mapping size: 64736 timestamp: 1754951288511 - conda: https://prefix.dev/conda-forge/linux-64/markupsafe-3.0.3-py311h3778330_0.conda sha256: 66c072c37aefa046f3fd4ca69978429421ef9e8a8572e19de534272a6482e997 md5: 0954f1a6a26df4a510b54f73b2a0345c depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 constrains: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping size: 26016 timestamp: 1759055312513 - conda: https://prefix.dev/conda-forge/linux-64/markupsafe-3.0.3-py313h3dea7bd_0.conda sha256: a530a411bdaaf0b1e4de8869dfaca46cb07407bc7dc0702a9e231b0e5ce7ca85 md5: c14389156310b8ed3520d84f854be1ee depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping size: 25909 timestamp: 1759055357045 - conda: https://prefix.dev/conda-forge/noarch/markupsafe-3.0.3-pyh7db6752_0.conda sha256: e0cbfea51a19b3055ca19428bd9233a25adca956c208abb9d00b21e7259c7e03 md5: fab1be106a50e20f10fe5228fd1d1651 depends: - python >=3.10 constrains: - jinja2 >=3.0.0 track_features: - markupsafe_no_compile license: BSD-3-Clause license_family: BSD size: 15499 timestamp: 1759055275624 - conda: https://prefix.dev/conda-forge/osx-64/markupsafe-3.0.3-py311he13f9b5_0.conda sha256: 28c82f7087027a72989cd030d1bb75da289da07ca2a17fe8db1d495fd6ee01f1 md5: 37b12b2523c1ef48318330b33410567b depends: - __osx >=10.13 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 constrains: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping size: 25452 timestamp: 1759055544260 - conda: https://prefix.dev/conda-forge/osx-64/markupsafe-3.0.3-py313h0f4d31d_0.conda sha256: 9c698da56e3bdae80be2a7bc0d19565971b36060155374d16fce14271c8b695c md5: 884a82dc80ecd251e38d647808c424b3 depends: - __osx >=10.13 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping size: 25105 timestamp: 1759055575973 - conda: https://prefix.dev/conda-forge/osx-arm64/markupsafe-3.0.3-py311ha9b3269_0.conda sha256: c6b20ca60d739f78525dff778292f7011454befda2cc3e1a725ded897fbf9b33 md5: df124303925c7ad5d7eb15179d38c4e3 depends: - __osx >=11.0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 constrains: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping size: 26326 timestamp: 1759055494628 - conda: https://prefix.dev/conda-forge/osx-arm64/markupsafe-3.0.3-py313h7d74516_0.conda sha256: e06902a1bf370fdd4ada0a8c81c504868fdb7e9971b72c6bd395aa4e5a497bd2 md5: 3df5979cc0b761dda0053ffdb0bca3ea depends: - __osx >=11.0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 constrains: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping size: 25778 timestamp: 1759055530601 - conda: https://prefix.dev/conda-forge/win-64/markupsafe-3.0.3-py311h3f79411_0.conda sha256: 975a1dcbdc0ced5af5bab681ec50406cf46f04e99c2aecc2f6b684497287cd7e md5: f04c6970b6cce548de53b43f6be06586 depends: - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping size: 29243 timestamp: 1759055454856 - conda: https://prefix.dev/conda-forge/win-64/markupsafe-3.0.3-py313hd650c13_0.conda sha256: 988d14095c1392e055fd75e24544da2db01ade73b0c2f99ddc8e2b8678ead4cc md5: 47eaaa4405741beb171ea6edc6eaf874 depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping size: 28959 timestamp: 1759055685616 - conda: https://prefix.dev/conda-forge/linux-64/matplotlib-3.10.8-py313h78bf25f_0.conda sha256: ad3eb40a91d456620936c88ea4eb2700ca24e474acd9498fdad831a87771399e md5: 85bce686dd57910d533807562204e16b depends: - matplotlib-base >=3.10.8,<3.10.9.0a0 - pyside6 >=6.7.2 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - tornado >=5 license: PSF-2.0 license_family: PSF purls: [] size: 17429 timestamp: 1763055377972 - conda: https://prefix.dev/conda-forge/osx-64/matplotlib-3.10.8-py313habf4b1d_0.conda sha256: cea48c750f812eaf7c8b1edaff9d4b30bdad99f28f4421f1ab49e24c74db360d md5: 37dffad2937d7c8b7fc47003ddd31eac depends: - matplotlib-base >=3.10.8,<3.10.9.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - tornado >=5 license: PSF-2.0 license_family: PSF purls: [] size: 17433 timestamp: 1763055798218 - conda: https://prefix.dev/conda-forge/osx-arm64/matplotlib-3.10.8-py313h39782a4_0.conda sha256: bdbac057835e29adeb32c4e937455f7caefd7723909b11cb9dc1d7675d1cdc4f md5: bae471007cbebf097a19e851c219d56a depends: - matplotlib-base >=3.10.8,<3.10.9.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - tornado >=5 license: PSF-2.0 license_family: PSF purls: [] size: 17522 timestamp: 1763056165099 - conda: https://prefix.dev/conda-forge/win-64/matplotlib-3.10.8-py313hfa70ccb_0.conda sha256: a431c82ccdf9dd494612784eaacc90bbac652187f40f330e6c5b02d701337e5a md5: b77085d92d9de0c4a8bcc88011985292 depends: - matplotlib-base >=3.10.8,<3.10.9.0a0 - pyside6 >=6.7.2 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - tornado >=5 license: PSF-2.0 license_family: PSF purls: [] size: 17887 timestamp: 1763055549597 - conda: https://prefix.dev/conda-forge/linux-64/matplotlib-base-3.10.8-py313h683a580_0.conda sha256: b1117aa2c1d11ca70d1704054cdc8801cbcf2dfb846c565531edd417ddd82559 md5: ffe67570e1a9192d2f4c189b27f75f89 depends: - __glibc >=2.17,<3.0.a0 - contourpy >=1.0.1 - cycler >=0.10 - fonttools >=4.22.0 - freetype - kiwisolver >=1.3.1 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - libgcc >=14 - libstdcxx >=14 - numpy >=1.23 - numpy >=1.23,<3 - packaging >=20.0 - pillow >=8 - pyparsing >=2.3.1 - python >=3.13,<3.14.0a0 - python-dateutil >=2.7 - python_abi 3.13.* *_cp313 - qhull >=2020.2,<2020.3.0a0 - tk >=8.6.13,<8.7.0a0 license: PSF-2.0 license_family: PSF purls: - pkg:pypi/matplotlib?source=compressed-mapping size: 8405862 timestamp: 1763055358671 - conda: https://prefix.dev/conda-forge/osx-64/matplotlib-base-3.10.8-py313h4ad75b8_0.conda sha256: d25d81b6022b6d012ea13f3feb41792e3b7de058e73bce05066a72acd0ce77ef md5: 5a0ed440de10c49cfed0178d3e59d994 depends: - __osx >=10.13 - contourpy >=1.0.1 - cycler >=0.10 - fonttools >=4.22.0 - freetype - kiwisolver >=1.3.1 - libcxx >=19 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - numpy >=1.23 - numpy >=1.23,<3 - packaging >=20.0 - pillow >=8 - pyparsing >=2.3.1 - python >=3.13,<3.14.0a0 - python-dateutil >=2.7 - python_abi 3.13.* *_cp313 - qhull >=2020.2,<2020.3.0a0 license: PSF-2.0 license_family: PSF purls: - pkg:pypi/matplotlib?source=hash-mapping size: 8305842 timestamp: 1763055757075 - conda: https://prefix.dev/conda-forge/osx-arm64/matplotlib-base-3.10.8-py313h58042b9_0.conda sha256: 24767ca32ea9db74a4a5965d2df8c69c83c82583e8ba32b683123d406092e205 md5: 745c18472bc6d3dc9146c3dec18bb740 depends: - __osx >=11.0 - contourpy >=1.0.1 - cycler >=0.10 - fonttools >=4.22.0 - freetype - kiwisolver >=1.3.1 - libcxx >=19 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - numpy >=1.23 - numpy >=1.23,<3 - packaging >=20.0 - pillow >=8 - pyparsing >=2.3.1 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python-dateutil >=2.7 - python_abi 3.13.* *_cp313 - qhull >=2020.2,<2020.3.0a0 license: PSF-2.0 license_family: PSF purls: - pkg:pypi/matplotlib?source=hash-mapping size: 8197793 timestamp: 1763056104477 - conda: https://prefix.dev/conda-forge/win-64/matplotlib-base-3.10.8-py313he1ded55_0.conda sha256: f63c4a5ded62cfb216c9d107a3c4527940036eef19cf481418080a0bd9bc11d8 md5: 05f96c429201a64ea752decf4b910a7c depends: - contourpy >=1.0.1 - cycler >=0.10 - fonttools >=4.22.0 - freetype - kiwisolver >=1.3.1 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - numpy >=1.23 - numpy >=1.23,<3 - packaging >=20.0 - pillow >=8 - pyparsing >=2.3.1 - python >=3.13,<3.14.0a0 - python-dateutil >=2.7 - python_abi 3.13.* *_cp313 - qhull >=2020.2,<2020.3.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: PSF-2.0 license_family: PSF purls: - pkg:pypi/matplotlib?source=hash-mapping size: 8007333 timestamp: 1763055517579 - conda: https://prefix.dev/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda sha256: 9d690334de0cd1d22c51bc28420663f4277cfa60d34fa5cad1ce284a13f1d603 md5: 00e120ce3e40bad7bfc78861ce3c4a25 depends: - python >=3.10 - traitlets license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/matplotlib-inline?source=hash-mapping size: 15175 timestamp: 1761214578417 - conda: https://prefix.dev/conda-forge/noarch/matrepr-1.0.1-pyh4f8845f_0.conda sha256: f3e0fa8bc35e67c1857582387bb6bc4ed06a5993352cf8eb45195fe24bf96391 md5: 48641ba3634705c8d8836add89045c09 depends: - python >=3.7 - tabulate license: BSD-2-Clause license_family: BSD size: 39711 timestamp: 1719851287353 - conda: https://prefix.dev/conda-forge/noarch/mdit-py-plugins-0.5.0-pyhd8ed1ab_0.conda sha256: 123cc004e2946879708cdb6a9eff24acbbb054990d6131bb94bca7a374ebebfc md5: 1997a083ef0b4c9331f9191564be275e depends: - markdown-it-py >=2.0.0,<5.0.0 - python >=3.10 license: MIT license_family: MIT size: 43805 timestamp: 1754946862113 - conda: https://prefix.dev/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 md5: 592132998493b3ff25fd7479396e8351 depends: - python >=3.9 license: MIT license_family: MIT purls: - pkg:pypi/mdurl?source=hash-mapping size: 14465 timestamp: 1733255681319 - conda: https://prefix.dev/conda-forge/noarch/mergedeep-1.3.4-pyhd8ed1ab_1.conda sha256: e5b555fd638334a253d83df14e3c913ef8ce10100090e17fd6fb8e752d36f95d md5: d9a8fc1f01deae61735c88ec242e855c depends: - python >=3.9 license: MIT license_family: MIT size: 11676 timestamp: 1734157119152 - conda: https://prefix.dev/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda sha256: d3fb4beb5e0a52b6cc33852c558e077e1bfe44df1159eb98332d69a264b14bae md5: b11e360fc4de2b0035fc8aaa74f17fd6 depends: - python >=3.10 - typing_extensions - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/mistune?source=hash-mapping size: 74250 timestamp: 1766504456031 - conda: https://prefix.dev/conda-forge/noarch/mkdocs-1.6.1-pyhd8ed1ab_1.conda sha256: 902d2e251f9a7ffa7d86a3e62be5b2395e28614bd4dbe5f50acf921fd64a8c35 md5: 14661160be39d78f2b210f2cc2766059 depends: - click >=7.0 - colorama >=0.4 - ghp-import >=1.0 - importlib-metadata >=4.4 - jinja2 >=2.11.1 - markdown >=3.3.6 - markupsafe >=2.0.1 - mergedeep >=1.3.4 - mkdocs-get-deps >=0.2.0 - packaging >=20.5 - pathspec >=0.11.1 - python >=3.9 - pyyaml >=5.1 - pyyaml-env-tag >=0.1 - watchdog >=2.0 constrains: - babel >=2.9.0 license: BSD-2-Clause license_family: BSD size: 3524754 timestamp: 1734344673481 - conda: https://prefix.dev/conda-forge/noarch/mkdocs-autorefs-1.4.3-pyhd8ed1ab_0.conda sha256: 1631568d0d36bc182ec20c5b4c58cc053cdd77698b4741977776f592996d345b md5: 1c024504ac97f1199023327a69066a8f depends: - markdown >=3.3 - markupsafe >=2.0.1 - mkdocs >=1.1 - pymdown-extensions - python >=3.10 license: ISC size: 35016 timestamp: 1756236211878 - conda: https://prefix.dev/conda-forge/noarch/mkdocs-gen-files-0.6.0-pyhcf101f3_0.conda sha256: 64c802b733adcc3fd1435f4b180706defd968a5fe9959c678f8f54452b85e2fa md5: 30eab90072aa47828d5374be23ff714d depends: - python >=3.10 - mkdocs >=1.4.1 - python license: MIT license_family: MIT size: 16356 timestamp: 1763934948991 - conda: https://prefix.dev/conda-forge/noarch/mkdocs-get-deps-0.2.0-pyhd8ed1ab_1.conda sha256: e0b501b96f7e393757fb2a61d042015966f6c5e9ac825925e43f9a6eafa907b6 md5: 84382acddb26c27c70f2de8d4c830830 depends: - importlib-metadata >=4.3 - mergedeep >=1.3.4 - platformdirs >=2.2.0 - python >=3.9 - pyyaml >=5.1 license: MIT license_family: MIT size: 14757 timestamp: 1734353035244 - conda: https://prefix.dev/conda-forge/noarch/mkdocs-jupyter-0.25.1-pyhd8ed1ab_1.conda sha256: 93aaa753dfac659af41a9639bc1e36be87220484032f33f1418c164d94aad248 md5: 4d9e2d9a321015013b2782969284047d depends: - ipykernel <7.0.0,>6.0.0 - jupytext <2,>1.13.8 - mkdocs <2,>=1.4.0 - mkdocs-material >9.0.0 - nbconvert <8,>=7.2.9 - pygments >2.12.0 - python >=3.9 license: Apache-2.0 license_family: APACHE size: 1193541 timestamp: 1736802171415 - conda: https://prefix.dev/conda-forge/noarch/mkdocs-literate-nav-0.6.2-pyhd8ed1ab_0.conda sha256: ff9ee7059a1ca1ca8480c827fa2de432049a40910193cbe3956a83bac2f5f7af md5: cf98ee24777947d5934e225aecccebbc depends: - mkdocs >=1.4.1 - python >=3.9 license: MIT license_family: MIT size: 18602 timestamp: 1742369304752 - conda: https://prefix.dev/conda-forge/noarch/mkdocs-material-9.7.1-pyhcf101f3_0.conda sha256: e3c9ad7beece49540a4de5a9a3136081af64ceae0745336819a8c40a9e25f336 md5: ab5cf0f1cd513e87bbd5736bdc13a399 depends: - python >=3.10 - jinja2 >=3.0,<4.dev0 - markdown >=3.2,<4.dev0 - mkdocs >=1.6,<2.dev0 - mkdocs-material-extensions >=1.3,<2.dev0 - pygments >=2.16,<3.dev0 - pymdown-extensions >=10.2,<11.dev0 - babel >=2.10,<3.dev0 - colorama >=0.4,<1.dev0 - paginate >=0.5,<1.dev0 - backrefs >=5.7.post1,<6.dev0 - requests >=2.26,<3.dev0 - python license: MIT license_family: MIT size: 4795211 timestamp: 1766061978730 - conda: https://prefix.dev/conda-forge/noarch/mkdocs-material-extensions-1.3.1-pyhd8ed1ab_1.conda sha256: f62955d40926770ab65cc54f7db5fde6c073a3ba36a0787a7a5767017da50aa3 md5: de8af4000a4872e16fb784c649679c8e depends: - python >=3.9 constrains: - mkdocs-material >=5.0.0 license: MIT license_family: MIT size: 16122 timestamp: 1734641109286 - conda: https://prefix.dev/conda-forge/noarch/mkdocs-section-index-0.3.10-pyhd8ed1ab_0.conda sha256: 5c07d14a62d8e139e4f337155d57196a6be0c6b86811350335777dc1bb86b208 md5: 6a8ea0da39a13c34ee14786579bafdeb depends: - mkdocs >=1.2 - python >=3.10 license: MIT license_family: MIT size: 14598 timestamp: 1756462483682 - conda: https://prefix.dev/conda-forge/noarch/mkdocstrings-1.0.2-pyhd8ed1ab_0.conda sha256: fab2631edd28edb7dcc4d95981e5864229206f5b287173b4bd3f623567e66e5c md5: c5ae381fcc4c236f5790e45d4b6ed952 depends: - click >=7.0 - importlib-metadata >=4.6 - jinja2 >=3.1 - markdown >=3.6 - markupsafe >=1.1 - mkdocs >=1.6 - mkdocs-autorefs >=1.4 - pymdown-extensions >=6.3 - python >=3.10,<4.0 - typing-extensions >=4.1 license: ISC size: 36268 timestamp: 1769350161953 - conda: https://prefix.dev/conda-forge/noarch/mkdocstrings-python-2.0.1-pyh332efcf_0.conda sha256: d0bc1c036bc47028c6a52184a54df21aaa30eb4dbe1a47fb011d0834bc588ea1 md5: ba61f0f35d5938db303a2174f52f4307 depends: - griffe >=1.13 - mkdocs-autorefs >=1.4 - mkdocstrings >=0.30 - python >=3.10 - typing_extensions >=4.0 license: ISC size: 57172 timestamp: 1764784251344 - conda: https://prefix.dev/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda sha256: b2b4c84b95210760e4d12319416c60ab66e03674ccdcbd14aeb59f82ebb1318d md5: fd05d1e894497b012d05a804232254ed depends: - llvm-openmp >=21.1.8 - tbb >=2022.3.0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: LicenseRef-IntelSimplifiedSoftwareOct2022 license_family: Proprietary purls: [] size: 100224829 timestamp: 1767634557029 - conda: https://prefix.dev/conda-forge/linux-64/msgpack-python-1.1.2-py311hdf67eae_1.conda sha256: 8c81a6208def64afc3e208326d78d7af60bcbc32d44afe1269b332df84084f29 md5: c1153b2cb3318889ce624a3b4f0db7f7 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/msgpack?source=hash-mapping size: 102979 timestamp: 1762504186626 - conda: https://prefix.dev/conda-forge/linux-64/msgpack-python-1.1.2-py313h7037e92_1.conda sha256: fac37e267dd1d07527f0b078ffe000916e80e8c89cfe69d466f5775b88e93df2 md5: cd1cfde0ea3bca6c805c73ffa988b12a depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/msgpack?source=hash-mapping size: 103129 timestamp: 1762504205590 - conda: https://prefix.dev/conda-forge/osx-64/msgpack-python-1.1.2-py311haec20ae_1.conda sha256: 841eb48c3b3d4ca2d84b836a9cb63d5d752a630697829f944183260547fc8cea md5: 7496bce5e71b8c6c71aef95c1feaeee5 depends: - __osx >=10.13 - libcxx >=19 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/msgpack?source=hash-mapping size: 90578 timestamp: 1762504498634 - conda: https://prefix.dev/conda-forge/osx-64/msgpack-python-1.1.2-py313h5eff275_1.conda sha256: ac8d0cd48aace3fe3129e21ec0f1f37dd9548b048b04db492a5b7fddb1dea20c md5: 44f1e465412acc4aeb8290acd756fb58 depends: - __osx >=10.13 - libcxx >=19 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/msgpack?source=hash-mapping size: 91891 timestamp: 1762504487164 - conda: https://prefix.dev/conda-forge/osx-arm64/msgpack-python-1.1.2-py311h5a5e7c7_1.conda sha256: 4da7ec2bf4b7bf1cc5d394f7b44265538a78a8f0fac52483c288a69d2032aabd md5: 123b3c15746ccfbfd8bf1c30c79f2ba6 depends: - __osx >=11.0 - libcxx >=19 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/msgpack?source=hash-mapping size: 91099 timestamp: 1762504394543 - conda: https://prefix.dev/conda-forge/osx-arm64/msgpack-python-1.1.2-py313ha61f8ec_1.conda sha256: b4a7557abb838de3890ceee6c61f78540b4b8ce74f2a03c334d7df5d476f7faa md5: 78bc73f3c5e84b432cdea463ea4e953e depends: - __osx >=11.0 - libcxx >=19 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/msgpack?source=hash-mapping size: 91725 timestamp: 1762504404391 - conda: https://prefix.dev/conda-forge/win-64/msgpack-python-1.1.2-py311h3fd045d_1.conda sha256: 9883b64dea87c50e98fabc05719ff0fdc347f57d7bacda19bcd69b80d8c436d4 md5: b0f2fb2eadce667ad09ca7d3ff868c71 depends: - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/msgpack?source=hash-mapping size: 87848 timestamp: 1762504210288 - conda: https://prefix.dev/conda-forge/win-64/msgpack-python-1.1.2-py313hf069bd2_1.conda sha256: 657fc62639dd638077f4d5e0bede9ed1bf4f4d018b395042bc36c9330e2c80fc md5: 0013c110d17d569ce560b7fae6aee0d3 depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/msgpack?source=hash-mapping size: 88214 timestamp: 1762504204957 - conda: https://prefix.dev/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda sha256: d09c47c2cf456de5c09fa66d2c3c5035aa1fa228a1983a433c47b876aa16ce90 md5: 37293a85a0f4f77bbd9cf7aaefc62609 depends: - python >=3.9 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/munkres?source=hash-mapping size: 15851 timestamp: 1749895533014 - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda sha256: 2e64699401c6170ce9a0916461ff4686f8d10b076f6abe1d887cbcb7061c0e85 md5: 37926bb0db8b04b8b99945076e1442d0 depends: - python >=3.10 - python license: MIT license_family: MIT purls: - pkg:pypi/narwhals?source=compressed-mapping size: 272452 timestamp: 1767693390284 - conda: https://prefix.dev/conda-forge/noarch/narwhals-2.16.0-pyhcf101f3_0.conda sha256: d9d358fb992938dc4ba292c4afa6677aac2b16464c9a4f35d69a6d6a923ad8f9 md5: 648a62e4e4cf1605abf73e7f48b87d5e depends: - python >=3.10 - python license: MIT license_family: MIT purls: - pkg:pypi/narwhals?source=compressed-mapping size: 279863 timestamp: 1770040381392 - conda: https://prefix.dev/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda sha256: 1b66960ee06874ddceeebe375d5f17fb5f393d025a09e15b830ad0c4fffb585b md5: 00f5b8dafa842e0c27c1cd7296aa4875 depends: - jupyter_client >=6.1.12 - jupyter_core >=4.12,!=5.0.* - nbformat >=5.1 - python >=3.8 - traitlets >=5.4 license: BSD-3-Clause license_family: BSD size: 28473 timestamp: 1766485646962 - conda: https://prefix.dev/conda-forge/noarch/nbclient-0.6.8-pyhd8ed1ab_0.tar.bz2 sha256: 883760e3cd82b143424ddda0ef784b788c7eec937c4aad15d9ad241531aa3533 md5: f052376c70c9d6a8e783e8e7c56b5f82 depends: - jupyter_client >=6.1.5 - nbformat >=5.0 - nest-asyncio - python >=3.7 - traitlets >=5.2.2 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/nbclient?source=hash-mapping size: 66640 timestamp: 1662750682431 - conda: https://prefix.dev/conda-forge/noarch/nbconvert-7.17.0-h14065e2_0.conda sha256: 3ed26e517968d16c8d6e52b20d9fbfc321d08975293e0ea27272e90c20797278 md5: b591fa5e68163b7f384ec58e8b319ace depends: - nbconvert-core ==7.17.0 pyhcf101f3_0 - nbconvert-pandoc ==7.17.0 hc3985f0_0 license: BSD-3-Clause license_family: BSD size: 5298 timestamp: 1769709543558 - conda: https://prefix.dev/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda sha256: 628fea99108df8e33396bb0b88658ec3d58edf245df224f57c0dce09615cbed2 md5: b14079a39ae60ac7ad2ec3d9eab075ca depends: - beautifulsoup4 - bleach-with-css !=5.0.0 - defusedxml - importlib-metadata >=3.6 - jinja2 >=3.0 - jupyter_core >=4.7 - jupyterlab_pygments - markupsafe >=2.0 - mistune >=2.0.3,<4 - nbclient >=0.5.0 - nbformat >=5.7 - packaging - pandocfilters >=1.4.1 - pygments >=2.4.1 - python >=3.10 - traitlets >=5.1 - python constrains: - pandoc >=2.9.2,<4.0.0 - nbconvert ==7.17.0 *_0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/nbconvert?source=compressed-mapping size: 202284 timestamp: 1769709543555 - conda: https://prefix.dev/conda-forge/noarch/nbconvert-pandoc-7.17.0-hc3985f0_0.conda sha256: 79cb6a9089b3f15ebbd6a1520b2dcf83115cb2f61beaf9755ae21c38263c391f md5: c9f0737797df2446be07b340c7992d5e depends: - nbconvert-core ==7.17.0 pyhcf101f3_0 - pandoc license: BSD-3-Clause license_family: BSD size: 5765 timestamp: 1769709543558 - conda: https://prefix.dev/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda sha256: 7a5bd30a2e7ddd7b85031a5e2e14f290898098dc85bea5b3a5bf147c25122838 md5: bbe1963f1e47f594070ffe87cdf612ea depends: - jsonschema >=2.6 - jupyter_core >=4.12,!=5.0.* - python >=3.9 - python-fastjsonschema >=2.15 - traitlets >=5.1 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/nbformat?source=hash-mapping size: 100945 timestamp: 1733402844974 - conda: https://prefix.dev/conda-forge/noarch/nbmake-1.5.5-pyhd8ed1ab_0.conda sha256: d996c332f6c8fea4b3420c613405692b37ea369e73f03d1d3f76a466f24fdf7b md5: 17b69c555fa9bdcf135306b20c554092 depends: - ipykernel >=5.4.0 - nbclient >=0.6.6,<0.7.0 - nbformat >=5.0.8,<6.0.0 - pygments >=2.7.3,<3.0.0 - pytest >=6.1.0 - python >=3.9,<4.0 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/nbmake?source=hash-mapping size: 19018 timestamp: 1746106473981 - conda: https://prefix.dev/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 md5: 47e340acb35de30501a76c7c799c41d7 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 license: X11 AND BSD-3-Clause purls: [] size: 891641 timestamp: 1738195959188 - conda: https://prefix.dev/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda sha256: ea4a5d27ded18443749aefa49dc79f6356da8506d508b5296f60b8d51e0c4bd9 md5: ced34dd9929f491ca6dab6a2927aff25 depends: - __osx >=10.13 license: X11 AND BSD-3-Clause purls: [] size: 822259 timestamp: 1738196181298 - conda: https://prefix.dev/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733 md5: 068d497125e4bf8a66bf707254fff5ae depends: - __osx >=11.0 license: X11 AND BSD-3-Clause purls: [] size: 797030 timestamp: 1738196177597 - conda: https://prefix.dev/conda-forge/linux-64/ndindex-1.10.1-py313h7033f15_0.conda sha256: 7ac6a3718f39bcde66486346b8f2f78b449de1f69dee98ada9aafafc011c358c md5: f0db808169f9f10e25c6ca4a9a79583f depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/ndindex?source=hash-mapping size: 245194 timestamp: 1763658106189 - conda: https://prefix.dev/conda-forge/noarch/ndindex-1.8-pyhd8ed1ab_1.conda sha256: 9d1d9a97dffc08878582644ac36a58a58ab6fd3007829632422eecbf6c9c69ae md5: 34cd9589f4124ff0016f100dc044180a depends: - python >=3.8 license: MIT license_family: MIT purls: - pkg:pypi/ndindex?source=hash-mapping size: 70642 timestamp: 1717010437985 - conda: https://prefix.dev/conda-forge/osx-64/ndindex-1.10.1-py313hc4a83b5_0.conda sha256: 6f163cd8f418d1657885b42e86099c31bbfa9801a65f9530e3f546f092c62ce2 md5: 682a418f8fa5c3fdbc83bff5bb98b5fe depends: - __osx >=10.13 - libcxx >=19 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/ndindex?source=hash-mapping size: 240539 timestamp: 1763658314313 - conda: https://prefix.dev/conda-forge/win-64/ndindex-1.10.1-py313hfe59770_0.conda sha256: 9d48736f3c3fcf02248fef7dfd64bb32f98ca18ab7aa3ae3707cb21a66a3ba97 md5: b0cdfededceca172280836b67f7c970b depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: - pkg:pypi/ndindex?source=hash-mapping size: 233618 timestamp: 1763658172645 - conda: https://prefix.dev/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda sha256: bb7b21d7fd0445ddc0631f64e66d91a179de4ba920b8381f29b9d006a42788c0 md5: 598fd7d4d0de2455fb74f56063969a97 depends: - python >=3.9 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/nest-asyncio?source=hash-mapping size: 11543 timestamp: 1733325673691 - conda: https://prefix.dev/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 md5: a2c1eeadae7a309daed9d62c96012a2b depends: - python >=3.11 - python constrains: - numpy >=1.25 - scipy >=1.11.2 - matplotlib-base >=3.8 - pandas >=2.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/networkx?source=compressed-mapping size: 1587439 timestamp: 1765215107045 - conda: https://prefix.dev/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda sha256: fd2cbd8dfc006c72f45843672664a8e4b99b2f8137654eaae8c3d46dca776f63 md5: 16c2a0e9c4a166e53632cfca4f68d020 constrains: - nlohmann_json-abi ==3.12.0 license: MIT license_family: MIT purls: [] size: 136216 timestamp: 1758194284857 - conda: https://prefix.dev/conda-forge/osx-64/nlohmann_json-3.12.0-h06076ce_1.conda sha256: 8e1b8ac88e07da2910c72466a94d1fc77aa13c722f8ddbc7ae3beb7c19b41fc7 md5: 97d7a1cda5546cb0bbdefa3777cb9897 constrains: - nlohmann_json-abi ==3.12.0 license: MIT license_family: MIT purls: [] size: 137081 timestamp: 1768670842725 - conda: https://prefix.dev/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda sha256: 1945fd5b64b74ef3d57926156fb0bfe88ee637c49f3273067f7231b224f1d26d md5: 755cfa6c08ed7b7acbee20ccbf15a47c constrains: - nlohmann_json-abi ==3.12.0 license: MIT license_family: MIT purls: [] size: 137595 timestamp: 1768670878127 - conda: https://prefix.dev/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda sha256: 7b920e46b9f7a2d2aa6434222e5c8d739021dbc5cc75f32d124a8191d86f9056 md5: e7f89ea5f7ea9401642758ff50a2d9c1 depends: - jupyter_server >=1.8,<3 - python >=3.9 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/notebook-shim?source=hash-mapping size: 16817 timestamp: 1733408419340 - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py311h3c884d5_0.conda sha256: d096edd82d702ab98ff13bedee05d4ffadf208ad7a3ed3a748b59b976d2ba3b0 md5: 3d05eaf5e34f383eec6ded1cac922bac depends: - __glibc >=2.17,<3.0.a0 - _openmp_mutex >=4.5 - libgcc >=14 - libstdcxx >=14 - llvmlite >=0.46.0,<0.47.0a0 - numpy >=1.22.3,<2.4 - numpy >=1.23,<3 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 constrains: - cuda-python >=11.6 - cuda-version >=11.2 - libopenblas !=0.3.6 - cudatoolkit >=11.2 - tbb >=2021.6.0 - scipy >=1.0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/numba?source=hash-mapping size: 5845064 timestamp: 1765466695252 - conda: https://prefix.dev/conda-forge/linux-64/numba-0.63.1-py313h5dce7c4_0.conda sha256: 3ceba93570814df69969edff3156097dc0e86ccefa2ea2bdfe08f84b2023cf04 md5: dbdae1a85bb346d57fae63269def955a depends: - __glibc >=2.17,<3.0.a0 - _openmp_mutex >=4.5 - libgcc >=14 - libstdcxx >=14 - llvmlite >=0.46.0,<0.47.0a0 - numpy >=1.22.3,<2.4 - numpy >=1.23,<3 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: - cudatoolkit >=11.2 - cuda-python >=11.6 - libopenblas !=0.3.6 - tbb >=2021.6.0 - cuda-version >=11.2 - scipy >=1.0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/numba?source=hash-mapping size: 5761715 timestamp: 1765466811957 - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py311hfe9595b_0.conda sha256: 9e92fc6f4d9d8d0069dcf9450a1cc0145f004504eaf568bce371a0b6785e15b4 md5: ab1fa59c3dedec55d54664060d4b6ce6 depends: - __osx >=10.13 - libcxx >=19 - llvm-openmp >=19.1.7 - llvm-openmp >=21.1.7 - llvmlite >=0.46.0,<0.47.0a0 - numpy >=1.22.3,<2.4 - numpy >=1.23,<3 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 constrains: - tbb >=2021.6.0 - cuda-version >=11.2 - cudatoolkit >=11.2 - cuda-python >=11.6 - libopenblas !=0.3.6 - scipy >=1.0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/numba?source=hash-mapping size: 5830478 timestamp: 1765467304368 - conda: https://prefix.dev/conda-forge/osx-64/numba-0.63.1-py313hd3f9b42_0.conda sha256: 5d883cbc0147fc460219750f248221839f31ae66f5eeaacac9903753dc018c60 md5: 6f4b1341edb126722ece084e2c382c6a depends: - __osx >=10.13 - libcxx >=19 - llvm-openmp >=19.1.7 - llvm-openmp >=21.1.7 - llvmlite >=0.46.0,<0.47.0a0 - numpy >=1.22.3,<2.4 - numpy >=1.23,<3 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: - cudatoolkit >=11.2 - cuda-version >=11.2 - tbb >=2021.6.0 - scipy >=1.0 - cuda-python >=11.6 - libopenblas !=0.3.6 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/numba?source=hash-mapping size: 5724311 timestamp: 1765466972923 - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py311had9367a_0.conda sha256: 320c3aa34ff7a069a29e7c129282a855535a56a24f968ba909a4b0093e0ddda9 md5: c05f68b104c8a09823bc2b4b32e9d523 depends: - __osx >=11.0 - libcxx >=19 - llvm-openmp >=19.1.7 - llvm-openmp >=21.1.7 - llvmlite >=0.46.0,<0.47.0a0 - numpy >=1.22.3,<2.4 - numpy >=1.23,<3 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 constrains: - libopenblas >=0.3.18,!=0.3.20 - tbb >=2021.6.0 - cuda-version >=11.2 - cudatoolkit >=11.2 - cuda-python >=11.6 - scipy >=1.0 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/numba?source=hash-mapping size: 5836264 timestamp: 1765808829293 - conda: https://prefix.dev/conda-forge/osx-arm64/numba-0.63.1-py313ha873477_0.conda sha256: 6f5d51434275240db065c9a57599b0fde3d117115b79466422dc5e01f355e2f1 md5: 2d0abc39aee6824aa5cb982ee6eb82ae depends: - __osx >=11.0 - libcxx >=19 - llvm-openmp >=19.1.7 - llvm-openmp >=21.1.7 - llvmlite >=0.46.0,<0.47.0a0 - numpy >=1.22.3,<2.4 - numpy >=1.23,<3 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 constrains: - tbb >=2021.6.0 - scipy >=1.0 - cuda-python >=11.6 - cuda-version >=11.2 - cudatoolkit >=11.2 - libopenblas >=0.3.18,!=0.3.20 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/numba?source=hash-mapping size: 5739440 timestamp: 1765467363361 - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py311h34437f8_0.conda sha256: 070dd5102c13ee3423ce495db9cce6ca0200233e121347a0e079a51124b2c0a6 md5: a0b14b4e9033182c656cbea6df7ab6dc depends: - llvmlite >=0.46.0,<0.47.0a0 - numpy >=1.22.3,<2.4 - numpy >=1.23,<3 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - cuda-version >=11.2 - libopenblas !=0.3.6 - cuda-python >=11.6 - scipy >=1.0 - tbb >=2021.6.0 - cudatoolkit >=11.2 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/numba?source=hash-mapping size: 5852456 timestamp: 1765467424730 - conda: https://prefix.dev/conda-forge/win-64/numba-0.63.1-py313h2da9318_0.conda sha256: 93fa3a044429298b5437dfca0b30b5834a8ebcbcae9abadba8c7f4fb83b453e5 md5: 43901612a748ce58c05f2d68a6e0bf46 depends: - llvmlite >=0.46.0,<0.47.0a0 - numpy >=1.22.3,<2.4 - numpy >=1.23,<3 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - cuda-python >=11.6 - cuda-version >=11.2 - tbb >=2021.6.0 - scipy >=1.0 - libopenblas !=0.3.6 - cudatoolkit >=11.2 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/numba?source=hash-mapping size: 5720859 timestamp: 1765808477325 - conda: https://prefix.dev/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda sha256: 3f4365e11b28e244c95ba8579942b0802761ba7bb31c026f50d1a9ea9c728149 md5: a502d7aad449a1206efb366d6a12c52d depends: - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - libgcc-ng >=12 - liblapack >=3.9.0,<4.0a0 - libstdcxx-ng >=12 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping size: 8065890 timestamp: 1707225944355 - conda: https://prefix.dev/conda-forge/linux-64/numpy-2.3.5-py313hf6604e3_1.conda sha256: 2f8aff2a17e4d43012e9863ef4392e6d5de3ae9da0c3e322831f8c5c3d86df71 md5: dce261869f78ba9b81b9091b084d328d depends: - python - libgcc >=14 - libstdcxx >=14 - __glibc >=2.17,<3.0.a0 - python_abi 3.13.* *_cp313 - libcblas >=3.9.0,<4.0a0 - liblapack >=3.9.0,<4.0a0 - libblas >=3.9.0,<4.0a0 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping size: 8919234 timestamp: 1766383469748 - conda: https://prefix.dev/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda sha256: dc9628197125ee1d02b2e7a859a769d26291d747ed79337309b8a9e67a8b8e00 md5: bb02b8801d17265160e466cf8bbf28da depends: - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - libcxx >=16 - liblapack >=3.9.0,<4.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping size: 7504319 timestamp: 1707226235372 - conda: https://prefix.dev/conda-forge/osx-64/numpy-2.3.5-py313hf1665ba_1.conda sha256: 7878ba3143d53638a39b702f0d55af1d4dcbb123eda09d98ca4e3637ef6d151b md5: 90fa3a86c16cfb708e35733b731ad5fd depends: - python - libcxx >=19 - __osx >=10.13 - libcblas >=3.9.0,<4.0a0 - libblas >=3.9.0,<4.0a0 - liblapack >=3.9.0,<4.0a0 - python_abi 3.13.* *_cp313 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping size: 8083480 timestamp: 1766383286176 - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda sha256: 160a52a01fea44fe9753a2ed22cf13d7b55c8a89ea0b8738546fdbf4795d6514 md5: 3160b93669a0def35a7a8158ebb33816 depends: - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - libcxx >=16 - liblapack >=3.9.0,<4.0a0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping size: 6652352 timestamp: 1707226297967 - conda: https://prefix.dev/conda-forge/osx-arm64/numpy-2.3.5-py313h16eae64_1.conda sha256: d759e7fee853d8e18709a15b8fc8a6db90c96986cb9d316c4d5ccdf5a1d3f61f md5: c72599556b49dc853839f4439c1eea32 depends: - python - libcxx >=19 - __osx >=11.0 - python 3.13.* *_cp313 - liblapack >=3.9.0,<4.0a0 - python_abi 3.13.* *_cp313 - libcblas >=3.9.0,<4.0a0 - libblas >=3.9.0,<4.0a0 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping size: 6792353 timestamp: 1766383288679 - conda: https://prefix.dev/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda sha256: 14116e72107de3089cc58119a5ce5905c22abf9a715c9fe41f8ac14db0992326 md5: 7b240edd44fd7a0991aa409b07cee776 depends: - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - liblapack >=3.9.0,<4.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping size: 7104093 timestamp: 1707226459646 - conda: https://prefix.dev/conda-forge/win-64/numpy-2.3.5-py313hce7ae62_1.conda sha256: c02d9587864174146bf0024051c76d368b2de18c94421e2f4e611fbb18576dd1 md5: 78749843445581c6dcc0cb80d146982d depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - liblapack >=3.9.0,<4.0a0 - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - python_abi 3.13.* *_cp313 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping size: 7524105 timestamp: 1766383318405 - conda: https://prefix.dev/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda sha256: 3900f9f2dbbf4129cf3ad6acf4e4b6f7101390b53843591c53b00f034343bc4d md5: 11b3379b191f63139e29c0d19dee24cd depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libpng >=1.6.50,<1.7.0a0 - libstdcxx >=14 - libtiff >=4.7.1,<4.8.0a0 - libzlib >=1.3.1,<2.0a0 license: BSD-2-Clause license_family: BSD purls: [] size: 355400 timestamp: 1758489294972 - conda: https://prefix.dev/conda-forge/osx-64/openjpeg-2.5.4-h87e8dc5_0.conda sha256: fdf4708a4e45b5fd9868646dd0c0a78429f4c0b8be490196c975e06403a841d0 md5: a67d3517ebbf615b91ef9fdc99934e0c depends: - __osx >=10.13 - libcxx >=19 - libpng >=1.6.50,<1.7.0a0 - libtiff >=4.7.1,<4.8.0a0 - libzlib >=1.3.1,<2.0a0 license: BSD-2-Clause license_family: BSD purls: [] size: 334875 timestamp: 1758489493148 - conda: https://prefix.dev/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda sha256: dd73e8f1da7dd6a5494c5586b835cbe2ec68bace55610b1c4bf927400fe9c0d7 md5: 6bf3d24692c157a41c01ce0bd17daeea depends: - __osx >=11.0 - libcxx >=19 - libpng >=1.6.50,<1.7.0a0 - libtiff >=4.7.1,<4.8.0a0 - libzlib >=1.3.1,<2.0a0 license: BSD-2-Clause license_family: BSD purls: [] size: 319967 timestamp: 1758489514651 - conda: https://prefix.dev/conda-forge/win-64/openjpeg-2.5.4-h24db6dd_0.conda sha256: 226c270a7e3644448954c47959c00a9bf7845f6d600c2a643db187118d028eee md5: 5af852046226bb3cb15c7f61c2ac020a depends: - libpng >=1.6.50,<1.7.0a0 - libtiff >=4.7.1,<4.8.0a0 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-2-Clause license_family: BSD purls: [] size: 244860 timestamp: 1758489556249 - conda: https://prefix.dev/conda-forge/linux-64/openldap-2.6.10-he970967_0.conda sha256: cb0b07db15e303e6f0a19646807715d28f1264c6350309a559702f4f34f37892 md5: 2e5bf4f1da39c0b32778561c3c4e5878 depends: - __glibc >=2.17,<3.0.a0 - cyrus-sasl >=2.1.27,<3.0a0 - krb5 >=1.21.3,<1.22.0a0 - libgcc >=13 - libstdcxx >=13 - openssl >=3.5.0,<4.0a0 license: OLDAP-2.8 license_family: BSD purls: [] size: 780253 timestamp: 1748010165522 - conda: https://prefix.dev/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c md5: f61eb8cd60ff9057122a3d338b99c00f depends: - __glibc >=2.17,<3.0.a0 - ca-certificates - libgcc >=14 license: Apache-2.0 license_family: Apache purls: [] size: 3164551 timestamp: 1769555830639 - conda: https://prefix.dev/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda sha256: e02e5639b0e4d6d4fcf0f3b082642844fb5a37316f5b0a1126c6271347462e90 md5: 30bb8d08b99b9a7600d39efb3559fff0 depends: - __osx >=10.13 - ca-certificates license: Apache-2.0 license_family: Apache purls: [] size: 2777136 timestamp: 1769557662405 - conda: https://prefix.dev/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda sha256: 361f5c5e60052abc12bdd1b50d7a1a43e6a6653aab99a2263bf2288d709dcf67 md5: f4f6ad63f98f64191c3e77c5f5f29d76 depends: - __osx >=11.0 - ca-certificates license: Apache-2.0 license_family: Apache purls: [] size: 3104268 timestamp: 1769556384749 - conda: https://prefix.dev/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda sha256: 53a5ad2e5553b8157a91bb8aa375f78c5958f77cb80e9d2ce59471ea8e5c0bd6 md5: eb585509b815415bc964b2c7e11c7eb3 depends: - ca-certificates - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: Apache purls: [] size: 9343023 timestamp: 1769557547888 - conda: https://prefix.dev/conda-forge/linux-64/orc-2.2.2-h19cb568_0.conda sha256: 84cfe4e11d3186c0c369f111700e978c849fb9e4ab7ed031acbe3663daacd141 md5: a98b8d7cfdd20004f1bdd1a51cb22c58 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libprotobuf >=6.31.1,<6.31.2.0a0 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - snappy >=1.2.2,<1.3.0a0 - tzdata - zstd >=1.5.7,<1.6.0a0 license: Apache-2.0 license_family: Apache purls: [] size: 1317120 timestamp: 1768247825733 - conda: https://prefix.dev/conda-forge/osx-64/orc-2.2.2-h3073fbf_0.conda sha256: 6c7048ba82eea4c92c1dc8bdf0a6989609367ffef9ff719cf86066bab046e0d0 md5: 7323bc020618321c05afaf23f78460c0 depends: - __osx >=11.0 - libcxx >=19 - libprotobuf >=6.31.1,<6.31.2.0a0 - libzlib >=1.3.1,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - snappy >=1.2.2,<1.3.0a0 - tzdata - zstd >=1.5.7,<1.6.0a0 license: Apache-2.0 license_family: Apache purls: [] size: 522041 timestamp: 1768248087348 - conda: https://prefix.dev/conda-forge/osx-arm64/orc-2.2.2-hac85105_0.conda sha256: 9de7956c90c513e5e3ae4a637bf67ea1a09235151bad6fa266a3c24311d7fe1c md5: 1c52effb297c8287cc79c383428e43c4 depends: - __osx >=11.0 - libcxx >=19 - libprotobuf >=6.31.1,<6.31.2.0a0 - libzlib >=1.3.1,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - snappy >=1.2.2,<1.3.0a0 - tzdata - zstd >=1.5.7,<1.6.0a0 license: Apache-2.0 license_family: Apache purls: [] size: 487454 timestamp: 1768248123539 - conda: https://prefix.dev/conda-forge/win-64/orc-2.2.2-hbd3206f_0.conda sha256: 86549f63b4b30764e70fd3edc2df4d69e17880b317afa9fa93318a83f9213807 md5: e20393ad8ebe534f3937e0a5da44e287 depends: - libprotobuf >=6.31.1,<6.31.2.0a0 - libzlib >=1.3.1,<2.0a0 - lz4-c >=1.10.0,<1.11.0a0 - snappy >=1.2.2,<1.3.0a0 - tzdata - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - zstd >=1.5.7,<1.6.0a0 license: Apache-2.0 license_family: Apache purls: [] size: 1164012 timestamp: 1768247969345 - conda: https://prefix.dev/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda sha256: 1840bd90d25d4930d60f57b4f38d4e0ae3f5b8db2819638709c36098c6ba770c md5: e51f1e4089cad105b6cac64bd8166587 depends: - python >=3.9 - typing_utils license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/overrides?source=hash-mapping size: 30139 timestamp: 1734587755455 - conda: https://prefix.dev/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 md5: b76541e68fea4d511b1ac46a28dcd2c6 depends: - python >=3.8 - python license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/packaging?source=compressed-mapping size: 72010 timestamp: 1769093650580 - conda: https://prefix.dev/conda-forge/noarch/paginate-0.5.7-pyhd8ed1ab_1.conda sha256: f6fef1b43b0d3d92476e1870c08d7b9c229aebab9a0556b073a5e1641cf453bd md5: c3f35453097faf911fd3f6023fc2ab24 depends: - python >=3.9 license: MIT license_family: MIT size: 18865 timestamp: 1734618649164 - conda: https://prefix.dev/conda-forge/linux-64/pandas-3.0.0-py311h8032f78_0.conda sha256: 19df168c25f2201b577e3b1f2ca8aec9b8ee1f7b5aeda9b5354a8b330a790a75 md5: 78d3e3073a999e662385c9a80d84ecec depends: - python - numpy >=1.26.0 - python-dateutil >=2.8.2 - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 - numpy >=1.23,<3 - python_abi 3.11.* *_cp311 constrains: - adbc-driver-postgresql >=1.2.0 - adbc-driver-sqlite >=1.2.0 - beautifulsoup4 >=4.12.3 - blosc >=1.21.3 - bottleneck >=1.4.2 - fastparquet >=2024.11.0 - fsspec >=2024.10.0 - gcsfs >=2024.10.0 - html5lib >=1.1 - hypothesis >=6.116.0 - jinja2 >=3.1.5 - lxml >=5.3.0 - matplotlib >=3.9.3 - numba >=0.60.0 - numexpr >=2.10.2 - odfpy >=1.4.1 - openpyxl >=3.1.5 - psycopg2 >=2.9.10 - pyarrow >=13.0.0 - pyiceberg >=0.8.1 - pymysql >=1.1.1 - pyqt5 >=5.15.9 - pyreadstat >=1.2.8 - pytables >=3.10.1 - pytest >=8.3.4 - pytest-xdist >=3.6.1 - python-calamine >=0.3.0 - pytz >=2024.2 - pyxlsb >=1.0.10 - qtpy >=2.4.2 - scipy >=1.14.1 - s3fs >=2024.10.0 - sqlalchemy >=2.0.36 - tabulate >=0.9.0 - xarray >=2024.10.0 - xlrd >=2.0.1 - xlsxwriter >=3.2.0 - zstandard >=0.23.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pandas?source=hash-mapping size: 15121146 timestamp: 1769076306940 - conda: https://prefix.dev/conda-forge/linux-64/pandas-3.0.0-py313hbfd7664_0.conda sha256: 05719fdfacdf97206a901621d79ab103c34905973ec8a18627825d5adab7a1b0 md5: ab6d05e915ab2ae4c41d275b14592151 depends: - python - numpy >=1.26.0 - python-dateutil >=2.8.2 - __glibc >=2.17,<3.0.a0 - libstdcxx >=14 - libgcc >=14 - python_abi 3.13.* *_cp313 - numpy >=1.23,<3 constrains: - adbc-driver-postgresql >=1.2.0 - adbc-driver-sqlite >=1.2.0 - beautifulsoup4 >=4.12.3 - blosc >=1.21.3 - bottleneck >=1.4.2 - fastparquet >=2024.11.0 - fsspec >=2024.10.0 - gcsfs >=2024.10.0 - html5lib >=1.1 - hypothesis >=6.116.0 - jinja2 >=3.1.5 - lxml >=5.3.0 - matplotlib >=3.9.3 - numba >=0.60.0 - numexpr >=2.10.2 - odfpy >=1.4.1 - openpyxl >=3.1.5 - psycopg2 >=2.9.10 - pyarrow >=13.0.0 - pyiceberg >=0.8.1 - pymysql >=1.1.1 - pyqt5 >=5.15.9 - pyreadstat >=1.2.8 - pytables >=3.10.1 - pytest >=8.3.4 - pytest-xdist >=3.6.1 - python-calamine >=0.3.0 - pytz >=2024.2 - pyxlsb >=1.0.10 - qtpy >=2.4.2 - scipy >=1.14.1 - s3fs >=2024.10.0 - sqlalchemy >=2.0.36 - tabulate >=0.9.0 - xarray >=2024.10.0 - xlrd >=2.0.1 - xlsxwriter >=3.2.0 - zstandard >=0.23.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pandas?source=hash-mapping size: 14952243 timestamp: 1769076307505 - conda: https://prefix.dev/conda-forge/osx-64/pandas-3.0.0-py311hfbd1ee4_0.conda sha256: ecc57fdb044cd9c727ee34d87fc823ca8eaf9474e984741f148f5a418e585918 md5: 707f0eee37a392f8aa578ef2bb43d0ce depends: - python - numpy >=1.26.0 - python-dateutil >=2.8.2 - __osx >=10.13 - libcxx >=19 - numpy >=1.23,<3 - python_abi 3.11.* *_cp311 constrains: - adbc-driver-postgresql >=1.2.0 - adbc-driver-sqlite >=1.2.0 - beautifulsoup4 >=4.12.3 - blosc >=1.21.3 - bottleneck >=1.4.2 - fastparquet >=2024.11.0 - fsspec >=2024.10.0 - gcsfs >=2024.10.0 - html5lib >=1.1 - hypothesis >=6.116.0 - jinja2 >=3.1.5 - lxml >=5.3.0 - matplotlib >=3.9.3 - numba >=0.60.0 - numexpr >=2.10.2 - odfpy >=1.4.1 - openpyxl >=3.1.5 - psycopg2 >=2.9.10 - pyarrow >=13.0.0 - pyiceberg >=0.8.1 - pymysql >=1.1.1 - pyqt5 >=5.15.9 - pyreadstat >=1.2.8 - pytables >=3.10.1 - pytest >=8.3.4 - pytest-xdist >=3.6.1 - python-calamine >=0.3.0 - pytz >=2024.2 - pyxlsb >=1.0.10 - qtpy >=2.4.2 - scipy >=1.14.1 - s3fs >=2024.10.0 - sqlalchemy >=2.0.36 - tabulate >=0.9.0 - xarray >=2024.10.0 - xlrd >=2.0.1 - xlsxwriter >=3.2.0 - zstandard >=0.23.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pandas?source=hash-mapping size: 14507964 timestamp: 1769076486373 - conda: https://prefix.dev/conda-forge/osx-64/pandas-3.0.0-py313h4810d26_0.conda sha256: 87694301760b22b76cac17253bd579c65962d553be05a98718614f296b16d605 md5: c23196474aa5d19c20d37d03ef8a5973 depends: - python - numpy >=1.26.0 - python-dateutil >=2.8.2 - __osx >=10.13 - libcxx >=19 - python_abi 3.13.* *_cp313 - numpy >=1.23,<3 constrains: - adbc-driver-postgresql >=1.2.0 - adbc-driver-sqlite >=1.2.0 - beautifulsoup4 >=4.12.3 - blosc >=1.21.3 - bottleneck >=1.4.2 - fastparquet >=2024.11.0 - fsspec >=2024.10.0 - gcsfs >=2024.10.0 - html5lib >=1.1 - hypothesis >=6.116.0 - jinja2 >=3.1.5 - lxml >=5.3.0 - matplotlib >=3.9.3 - numba >=0.60.0 - numexpr >=2.10.2 - odfpy >=1.4.1 - openpyxl >=3.1.5 - psycopg2 >=2.9.10 - pyarrow >=13.0.0 - pyiceberg >=0.8.1 - pymysql >=1.1.1 - pyqt5 >=5.15.9 - pyreadstat >=1.2.8 - pytables >=3.10.1 - pytest >=8.3.4 - pytest-xdist >=3.6.1 - python-calamine >=0.3.0 - pytz >=2024.2 - pyxlsb >=1.0.10 - qtpy >=2.4.2 - scipy >=1.14.1 - s3fs >=2024.10.0 - sqlalchemy >=2.0.36 - tabulate >=0.9.0 - xarray >=2024.10.0 - xlrd >=2.0.1 - xlsxwriter >=3.2.0 - zstandard >=0.23.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pandas?source=hash-mapping size: 14233411 timestamp: 1769076449135 - conda: https://prefix.dev/conda-forge/osx-arm64/pandas-3.0.0-py311h4a068b9_0.conda sha256: 889db92466ef36844f67c9bc62ebf2a286700a5f3ae4f1a1702d5417796e3ece md5: 3e7fee680868f65316804dc9eeb387fd depends: - python - numpy >=1.26.0 - python-dateutil >=2.8.2 - __osx >=11.0 - libcxx >=19 - python 3.11.* *_cpython - numpy >=1.23,<3 - python_abi 3.11.* *_cp311 constrains: - adbc-driver-postgresql >=1.2.0 - adbc-driver-sqlite >=1.2.0 - beautifulsoup4 >=4.12.3 - blosc >=1.21.3 - bottleneck >=1.4.2 - fastparquet >=2024.11.0 - fsspec >=2024.10.0 - gcsfs >=2024.10.0 - html5lib >=1.1 - hypothesis >=6.116.0 - jinja2 >=3.1.5 - lxml >=5.3.0 - matplotlib >=3.9.3 - numba >=0.60.0 - numexpr >=2.10.2 - odfpy >=1.4.1 - openpyxl >=3.1.5 - psycopg2 >=2.9.10 - pyarrow >=13.0.0 - pyiceberg >=0.8.1 - pymysql >=1.1.1 - pyqt5 >=5.15.9 - pyreadstat >=1.2.8 - pytables >=3.10.1 - pytest >=8.3.4 - pytest-xdist >=3.6.1 - python-calamine >=0.3.0 - pytz >=2024.2 - pyxlsb >=1.0.10 - qtpy >=2.4.2 - scipy >=1.14.1 - s3fs >=2024.10.0 - sqlalchemy >=2.0.36 - tabulate >=0.9.0 - xarray >=2024.10.0 - xlrd >=2.0.1 - xlsxwriter >=3.2.0 - zstandard >=0.23.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pandas?source=hash-mapping size: 14275946 timestamp: 1769076395577 - conda: https://prefix.dev/conda-forge/osx-arm64/pandas-3.0.0-py313h6974306_0.conda sha256: 9a43b0b6a6be447c180a69704e16dcdab1afffe8f37bc501ed1bf1fd99e67e14 md5: ae2e72c47ce95ec8c489cffa0592f492 depends: - python - numpy >=1.26.0 - python-dateutil >=2.8.2 - python 3.13.* *_cp313 - libcxx >=19 - __osx >=11.0 - python_abi 3.13.* *_cp313 - numpy >=1.23,<3 constrains: - adbc-driver-postgresql >=1.2.0 - adbc-driver-sqlite >=1.2.0 - beautifulsoup4 >=4.12.3 - blosc >=1.21.3 - bottleneck >=1.4.2 - fastparquet >=2024.11.0 - fsspec >=2024.10.0 - gcsfs >=2024.10.0 - html5lib >=1.1 - hypothesis >=6.116.0 - jinja2 >=3.1.5 - lxml >=5.3.0 - matplotlib >=3.9.3 - numba >=0.60.0 - numexpr >=2.10.2 - odfpy >=1.4.1 - openpyxl >=3.1.5 - psycopg2 >=2.9.10 - pyarrow >=13.0.0 - pyiceberg >=0.8.1 - pymysql >=1.1.1 - pyqt5 >=5.15.9 - pyreadstat >=1.2.8 - pytables >=3.10.1 - pytest >=8.3.4 - pytest-xdist >=3.6.1 - python-calamine >=0.3.0 - pytz >=2024.2 - pyxlsb >=1.0.10 - qtpy >=2.4.2 - scipy >=1.14.1 - s3fs >=2024.10.0 - sqlalchemy >=2.0.36 - tabulate >=0.9.0 - xarray >=2024.10.0 - xlrd >=2.0.1 - xlsxwriter >=3.2.0 - zstandard >=0.23.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pandas?source=compressed-mapping size: 14002529 timestamp: 1769076505757 - conda: https://prefix.dev/conda-forge/win-64/pandas-3.0.0-py311h0610301_0.conda sha256: 2790793389a779899db76b8e1e66493e7a7f703e69022c941843702412fb6fda md5: 35cc74cfc8cf3824a9ae45ee706b3fe0 depends: - python - numpy >=1.26.0 - python-dateutil >=2.8.2 - python-tzdata - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.11.* *_cp311 - numpy >=1.23,<3 constrains: - adbc-driver-postgresql >=1.2.0 - adbc-driver-sqlite >=1.2.0 - beautifulsoup4 >=4.12.3 - blosc >=1.21.3 - bottleneck >=1.4.2 - fastparquet >=2024.11.0 - fsspec >=2024.10.0 - gcsfs >=2024.10.0 - html5lib >=1.1 - hypothesis >=6.116.0 - jinja2 >=3.1.5 - lxml >=5.3.0 - matplotlib >=3.9.3 - numba >=0.60.0 - numexpr >=2.10.2 - odfpy >=1.4.1 - openpyxl >=3.1.5 - psycopg2 >=2.9.10 - pyarrow >=13.0.0 - pyiceberg >=0.8.1 - pymysql >=1.1.1 - pyqt5 >=5.15.9 - pyreadstat >=1.2.8 - pytables >=3.10.1 - pytest >=8.3.4 - pytest-xdist >=3.6.1 - python-calamine >=0.3.0 - pytz >=2024.2 - pyxlsb >=1.0.10 - qtpy >=2.4.2 - scipy >=1.14.1 - s3fs >=2024.10.0 - sqlalchemy >=2.0.36 - tabulate >=0.9.0 - xarray >=2024.10.0 - xlrd >=2.0.1 - xlsxwriter >=3.2.0 - zstandard >=0.23.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pandas?source=hash-mapping size: 14025090 timestamp: 1769076324125 - conda: https://prefix.dev/conda-forge/win-64/pandas-3.0.0-py313h26f5e95_0.conda sha256: cc009318202a19e78c7be1e8d8147ea678ebb73f89438040d73619bd29004f20 md5: fd6e35ea1658e107cd81ec1403d5ffd7 depends: - python - numpy >=1.26.0 - python-dateutil >=2.8.2 - python-tzdata - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - numpy >=1.23,<3 - python_abi 3.13.* *_cp313 constrains: - adbc-driver-postgresql >=1.2.0 - adbc-driver-sqlite >=1.2.0 - beautifulsoup4 >=4.12.3 - blosc >=1.21.3 - bottleneck >=1.4.2 - fastparquet >=2024.11.0 - fsspec >=2024.10.0 - gcsfs >=2024.10.0 - html5lib >=1.1 - hypothesis >=6.116.0 - jinja2 >=3.1.5 - lxml >=5.3.0 - matplotlib >=3.9.3 - numba >=0.60.0 - numexpr >=2.10.2 - odfpy >=1.4.1 - openpyxl >=3.1.5 - psycopg2 >=2.9.10 - pyarrow >=13.0.0 - pyiceberg >=0.8.1 - pymysql >=1.1.1 - pyqt5 >=5.15.9 - pyreadstat >=1.2.8 - pytables >=3.10.1 - pytest >=8.3.4 - pytest-xdist >=3.6.1 - python-calamine >=0.3.0 - pytz >=2024.2 - pyxlsb >=1.0.10 - qtpy >=2.4.2 - scipy >=1.14.1 - s3fs >=2024.10.0 - sqlalchemy >=2.0.36 - tabulate >=0.9.0 - xarray >=2024.10.0 - xlrd >=2.0.1 - xlsxwriter >=3.2.0 - zstandard >=0.23.0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pandas?source=hash-mapping size: 13742616 timestamp: 1769076326138 - conda: https://prefix.dev/conda-forge/linux-64/pandoc-3.8.3-ha770c72_0.conda sha256: 87ec986d1e0d16d9d2aa149653abeb73d1ac4bd9e6d7dc13ba33ec00134c8a7a md5: 0e4aa34e44a68aeb850349fe51a6a3d0 license: GPL-2.0-or-later license_family: GPL size: 22458834 timestamp: 1764589637843 - conda: https://prefix.dev/conda-forge/osx-64/pandoc-3.8.3-h694c41f_0.conda sha256: 763c07427762e3e1d524c4e4e7343225de6af2be432d1136a0fa26b863450c9e md5: ea4f844424717e24a69c05f16ff30ffa license: GPL-2.0-or-later license_family: GPL size: 16948053 timestamp: 1764589819568 - conda: https://prefix.dev/conda-forge/osx-arm64/pandoc-3.8.3-hce30654_0.conda sha256: 39af2080d16088c0b9c19db5d0f8b2c845e70c428126a4773d0e54b609d8af91 md5: 68bc0f4209fe5cbb03a401177f3a36c2 license: GPL-2.0-or-later license_family: GPL size: 28522262 timestamp: 1764589967786 - conda: https://prefix.dev/conda-forge/win-64/pandoc-3.8.3-h57928b3_0.conda sha256: b3d37c502e405e7d1997a028e7eae246acd52436eacdd4f053cb345bde0da8a9 md5: 904ca93f4f00a75ee3c49147cb00f14d license: GPL-2.0-or-later license_family: GPL size: 26699611 timestamp: 1764589773519 - conda: https://prefix.dev/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 sha256: 2bb9ba9857f4774b85900c2562f7e711d08dd48e2add9bee4e1612fbee27e16f md5: 457c2c8c08e54905d6954e79cb5b5db9 depends: - python !=3.0,!=3.1,!=3.2,!=3.3 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pandocfilters?source=hash-mapping size: 11627 timestamp: 1631603397334 - conda: https://prefix.dev/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda sha256: 30de7b4d15fbe53ffe052feccde31223a236dae0495bab54ab2479de30b2990f md5: a110716cdb11cf51482ff4000dc253d7 depends: - python >=3.10 - python license: MIT license_family: MIT purls: - pkg:pypi/parso?source=hash-mapping size: 81562 timestamp: 1755974222274 - conda: https://prefix.dev/conda-forge/noarch/partd-1.4.2-pyhd8ed1ab_0.conda sha256: 472fc587c63ec4f6eba0cc0b06008a6371e0a08a5986de3cf4e8024a47b4fe6c md5: 0badf9c54e24cecfb0ad2f99d680c163 depends: - locket - python >=3.9 - toolz license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/partd?source=hash-mapping size: 20884 timestamp: 1715026639309 - conda: https://prefix.dev/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda sha256: 29ea20d0faf20374fcd61c25f6d32fb8e9a2c786a7f1473a0c3ead359470fbe1 md5: 2908273ac396d2cd210a8127f5f1c0d6 depends: - python >=3.10 license: MPL-2.0 license_family: MOZILLA size: 53739 timestamp: 1769677743677 - conda: https://prefix.dev/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda sha256: 5e6f7d161356fefd981948bea5139c5aa0436767751a6930cb1ca801ebb113ff md5: 7a3bff861a6583f1889021facefc08b1 depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - libgcc >=14 - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 1222481 timestamp: 1763655398280 - conda: https://prefix.dev/conda-forge/win-64/pcre2-10.47-hd2b5f0e_0.conda sha256: 3e9e02174edf02cb4bcdd75668ad7b74b8061791a3bc8bdb8a52ae336761ba3e md5: 77eaf2336f3ae749e712f63e36b0f0a1 depends: - bzip2 >=1.0.8,<2.0a0 - libzlib >=1.3.1,<2.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-3-Clause license_family: BSD purls: [] size: 995992 timestamp: 1763655708300 - conda: https://prefix.dev/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda sha256: 202af1de83b585d36445dc1fda94266697341994d1a3328fabde4989e1b3d07a md5: d0d408b1f18883a944376da5cf8101ea depends: - ptyprocess >=0.5 - python >=3.9 license: ISC purls: - pkg:pypi/pexpect?source=hash-mapping size: 53561 timestamp: 1733302019362 - conda: https://prefix.dev/conda-forge/linux-64/pillow-12.1.0-py311hf88fc01_0.conda sha256: 218cfe38c3cb00a3246e01a30e03b1e4ef9afc6d3a20dc62ea1bcc3d96741343 md5: ce51a1258d127e1c72bad676235b9d6c depends: - python - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libjpeg-turbo >=3.1.2,<4.0a0 - zlib-ng >=2.3.2,<2.4.0a0 - tk >=8.6.13,<8.7.0a0 - openjpeg >=2.5.4,<3.0a0 - lcms2 >=2.17,<3.0a0 - python_abi 3.11.* *_cp311 - libtiff >=4.7.1,<4.8.0a0 - libwebp-base >=1.6.0,<2.0a0 - libxcb >=1.17.0,<2.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 license: HPND purls: - pkg:pypi/pillow?source=hash-mapping size: 1046274 timestamp: 1767353193447 - conda: https://prefix.dev/conda-forge/linux-64/pillow-12.1.0-py313h80991f8_0.conda sha256: bdad1e21cadd64154c45fa554247dd672288ad51982ca7d54b3fab63e40938df md5: 183fe6b9e99e5c2b464c1573ec78eac8 depends: - python - libgcc >=14 - __glibc >=2.17,<3.0.a0 - tk >=8.6.13,<8.7.0a0 - python_abi 3.13.* *_cp313 - libtiff >=4.7.1,<4.8.0a0 - libjpeg-turbo >=3.1.2,<4.0a0 - lcms2 >=2.17,<3.0a0 - libxcb >=1.17.0,<2.0a0 - zlib-ng >=2.3.2,<2.4.0a0 - libwebp-base >=1.6.0,<2.0a0 - openjpeg >=2.5.4,<3.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 license: HPND purls: - pkg:pypi/pillow?source=hash-mapping size: 1043309 timestamp: 1767353193450 - conda: https://prefix.dev/conda-forge/osx-64/pillow-12.1.0-py311h127dec8_0.conda sha256: 319a255cf8f57985875d79c698be4ec7a2b2990e9e005515498b7cfe699900f5 md5: b16e08d57bfca26b9a5cec144e27b4d4 depends: - python - __osx >=10.13 - python_abi 3.11.* *_cp311 - libtiff >=4.7.1,<4.8.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - zlib-ng >=2.3.2,<2.4.0a0 - libjpeg-turbo >=3.1.2,<4.0a0 - libxcb >=1.17.0,<2.0a0 - openjpeg >=2.5.4,<3.0a0 - tk >=8.6.13,<8.7.0a0 - lcms2 >=2.17,<3.0a0 - libwebp-base >=1.6.0,<2.0a0 license: HPND purls: - pkg:pypi/pillow?source=hash-mapping size: 978248 timestamp: 1767353261549 - conda: https://prefix.dev/conda-forge/osx-64/pillow-12.1.0-py313h16bb925_0.conda sha256: 2e428848bde27506936329303144a889a9e168e797053e25943973d25560e9c7 md5: bc8c5b5215ba393b44040e5cdb4b4a58 depends: - python - __osx >=10.13 - libwebp-base >=1.6.0,<2.0a0 - lcms2 >=2.17,<3.0a0 - libxcb >=1.17.0,<2.0a0 - zlib-ng >=2.3.2,<2.4.0a0 - libjpeg-turbo >=3.1.2,<4.0a0 - tk >=8.6.13,<8.7.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - python_abi 3.13.* *_cp313 - libtiff >=4.7.1,<4.8.0a0 - openjpeg >=2.5.4,<3.0a0 license: HPND purls: - pkg:pypi/pillow?source=hash-mapping size: 977098 timestamp: 1767353261551 - conda: https://prefix.dev/conda-forge/osx-arm64/pillow-12.1.0-py311hd37aea2_0.conda sha256: 8ec1086d40b18c4dcd66afcccb1e5ab5f7920575ef4b5447cb1b55e3d5f3d50e md5: 245db56489068c5a9fc9448129828604 depends: - python - python 3.11.* *_cpython - __osx >=11.0 - openjpeg >=2.5.4,<3.0a0 - libjpeg-turbo >=3.1.2,<4.0a0 - libtiff >=4.7.1,<4.8.0a0 - libxcb >=1.17.0,<2.0a0 - libwebp-base >=1.6.0,<2.0a0 - lcms2 >=2.17,<3.0a0 - zlib-ng >=2.3.2,<2.4.0a0 - tk >=8.6.13,<8.7.0a0 - python_abi 3.11.* *_cp311 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 license: HPND purls: - pkg:pypi/pillow?source=hash-mapping size: 969696 timestamp: 1767353279677 - conda: https://prefix.dev/conda-forge/osx-arm64/pillow-12.1.0-py313h45e5a15_0.conda sha256: e5eaa7f00fca189848a0454303c56cc4edefd3e58a70bfd490d2cfe0d0aa525d md5: 78a39731fd50dbd511de305934fe7e62 depends: - python - __osx >=11.0 - python 3.13.* *_cp313 - libxcb >=1.17.0,<2.0a0 - openjpeg >=2.5.4,<3.0a0 - libtiff >=4.7.1,<4.8.0a0 - zlib-ng >=2.3.2,<2.4.0a0 - tk >=8.6.13,<8.7.0a0 - libjpeg-turbo >=3.1.2,<4.0a0 - python_abi 3.13.* *_cp313 - lcms2 >=2.17,<3.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - libwebp-base >=1.6.0,<2.0a0 license: HPND purls: - pkg:pypi/pillow?source=hash-mapping size: 966296 timestamp: 1767353279679 - conda: https://prefix.dev/conda-forge/win-64/pillow-12.1.0-py311h17b8079_0.conda sha256: 689c7edaaab74f1318f0cac8f333bc5147a16f4632d0136003363824c301dc27 md5: da30e4de83b61f936f73660eb4fa3cd5 depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - zlib-ng >=2.3.2,<2.4.0a0 - libwebp-base >=1.6.0,<2.0a0 - python_abi 3.11.* *_cp311 - openjpeg >=2.5.4,<3.0a0 - lcms2 >=2.17,<3.0a0 - libtiff >=4.7.1,<4.8.0a0 - tk >=8.6.13,<8.7.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - libjpeg-turbo >=3.1.2,<4.0a0 - libxcb >=1.17.0,<2.0a0 license: HPND purls: - pkg:pypi/pillow?source=hash-mapping size: 951008 timestamp: 1767353195060 - conda: https://prefix.dev/conda-forge/win-64/pillow-12.1.0-py313h38f99e1_0.conda sha256: 181b4d169e7a671c387427ceb398d931802adace8808836b44295b07c3484abd md5: 1927a42726a4ca0e94d5e8cb94c7a06d depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - lcms2 >=2.17,<3.0a0 - libwebp-base >=1.6.0,<2.0a0 - python_abi 3.13.* *_cp313 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - openjpeg >=2.5.4,<3.0a0 - zlib-ng >=2.3.2,<2.4.0a0 - libjpeg-turbo >=3.1.2,<4.0a0 - libtiff >=4.7.1,<4.8.0a0 - libxcb >=1.17.0,<2.0a0 - tk >=8.6.13,<8.7.0a0 license: HPND purls: - pkg:pypi/pillow?source=hash-mapping size: 946833 timestamp: 1767353195062 - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh145f28c_0.conda sha256: 4d5e2faca810459724f11f78d19a0feee27a7be2b3fc5f7abbbec4c9fdcae93d md5: bf47878473e5ab9fdb4115735230e191 depends: - python >=3.13.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pip?source=hash-mapping size: 1177084 timestamp: 1762776338614 - conda: https://prefix.dev/conda-forge/noarch/pip-25.3-pyh8b19718_0.conda sha256: b67692da1c0084516ac1c9ada4d55eaf3c5891b54980f30f3f444541c2706f1e md5: c55515ca43c6444d2572e0f0d93cb6b9 depends: - python >=3.10,<3.13.0a0 - setuptools - wheel license: MIT license_family: MIT purls: - pkg:pypi/pip?source=hash-mapping size: 1177534 timestamp: 1762776258783 - conda: https://prefix.dev/conda-forge/noarch/pip-26.0-pyh145f28c_0.conda sha256: 4349de61caaa05e19be38a20a084e001d325b9c70ac10e3c88d8743d3fc9aefb md5: f08a17c938eb6bc1b928bd8cdd37e20f depends: - python >=3.13.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pip?source=compressed-mapping size: 1181224 timestamp: 1769850913286 - conda: https://prefix.dev/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda sha256: 43d37bc9ca3b257c5dd7bf76a8426addbdec381f6786ff441dc90b1a49143b6a md5: c01af13bdc553d1a8fbfff6e8db075f0 depends: - libgcc >=14 - libstdcxx >=14 - libgcc >=14 - __glibc >=2.17,<3.0.a0 license: MIT license_family: MIT purls: [] size: 450960 timestamp: 1754665235234 - conda: https://prefix.dev/conda-forge/win-64/pixman-0.46.4-h5112557_1.conda sha256: 246fce4706b3f8b247a7d6142ba8d732c95263d3c96e212b9d63d6a4ab4aff35 md5: 08c8fa3b419df480d985e304f7884d35 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 license: MIT license_family: MIT purls: [] size: 542795 timestamp: 1754665193489 - conda: https://prefix.dev/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda sha256: 04c64fb78c520e5c396b6e07bc9082735a5cc28175dbe23138201d0a9441800b md5: 1bd2e65c8c7ef24f4639ae6e850dacc2 depends: - python >=3.10 - python license: MIT license_family: MIT purls: - pkg:pypi/platformdirs?source=hash-mapping size: 23922 timestamp: 1764950726246 - conda: https://prefix.dev/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda sha256: e14aafa63efa0528ca99ba568eaf506eb55a0371d12e6250aaaa61718d2eb62e md5: d7585b6550ad04c8c5e21097ada2888e depends: - python >=3.9 - python license: MIT license_family: MIT purls: - pkg:pypi/pluggy?source=compressed-mapping size: 25877 timestamp: 1764896838868 - conda: https://prefix.dev/conda-forge/linux-64/prometheus-cpp-1.3.0-ha5d0236_0.conda sha256: 013669433eb447548f21c3c6b16b2ed64356f726b5f77c1b39d5ba17a8a4b8bc md5: a83f6a2fdc079e643237887a37460668 depends: - __glibc >=2.17,<3.0.a0 - libcurl >=8.10.1,<9.0a0 - libgcc >=13 - libstdcxx >=13 - libzlib >=1.3.1,<2.0a0 - zlib license: MIT license_family: MIT purls: [] size: 199544 timestamp: 1730769112346 - conda: https://prefix.dev/conda-forge/osx-64/prometheus-cpp-1.3.0-h7802330_0.conda sha256: af754a477ee2681cb7d5d77c621bd590d25fe1caf16741841fc2d176815fc7de md5: f36107fa2557e63421a46676371c4226 depends: - __osx >=10.13 - libcurl >=8.10.1,<9.0a0 - libcxx >=18 - libzlib >=1.3.1,<2.0a0 - zlib license: MIT license_family: MIT purls: [] size: 179103 timestamp: 1730769223221 - conda: https://prefix.dev/conda-forge/osx-arm64/prometheus-cpp-1.3.0-h0967b3e_0.conda sha256: 851a77ae1a8e90db9b9f3c4466abea7afb52713c3d98ceb0d37ba6ff27df2eff md5: 7172339b49c94275ba42fec3eaeda34f depends: - __osx >=11.0 - libcurl >=8.10.1,<9.0a0 - libcxx >=18 - libzlib >=1.3.1,<2.0a0 - zlib license: MIT license_family: MIT purls: [] size: 173220 timestamp: 1730769371051 - conda: https://prefix.dev/conda-forge/noarch/prometheus_client-0.24.1-pyhd8ed1ab_0.conda sha256: 75b2589159d04b3fb92db16d9970b396b9124652c784ab05b66f584edc97f283 md5: 7526d20621b53440b0aae45d4797847e depends: - python >=3.10 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/prometheus-client?source=compressed-mapping size: 56634 timestamp: 1768476602855 - conda: https://prefix.dev/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda sha256: 4817651a276016f3838957bfdf963386438c70761e9faec7749d411635979bae md5: edb16f14d920fb3faf17f5ce582942d6 depends: - python >=3.10 - wcwidth constrains: - prompt_toolkit 3.0.52 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/prompt-toolkit?source=hash-mapping size: 273927 timestamp: 1756321848365 - conda: https://prefix.dev/conda-forge/linux-64/psutil-7.2.2-py311haee01d2_0.conda sha256: 8d9325af538a8f56013e42bbb91a4dc6935aece34476e20bafacf6007b571e86 md5: 2ed8f6fe8b51d8e19f7621941f7bb95f depends: - python - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=compressed-mapping size: 231786 timestamp: 1769678156460 - conda: https://prefix.dev/conda-forge/linux-64/psutil-7.2.2-py313h54dd161_0.conda sha256: f19fd682d874689dfde20bf46d7ec1a28084af34583e0405685981363af47c91 md5: 25fe6e02c2083497b3239e21b49d8093 depends: - python - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=compressed-mapping size: 228663 timestamp: 1769678153829 - conda: https://prefix.dev/conda-forge/osx-64/psutil-7.2.2-py311ha332486_0.conda sha256: 374933b76115cd0946f3c47f20a7934ee0ce7bd4b667d14f7a704db1e85ee459 md5: 29d06d0775445ec3f42f3a1be72b3f02 depends: - python - __osx >=10.13 - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping size: 242642 timestamp: 1769678292465 - conda: https://prefix.dev/conda-forge/osx-64/psutil-7.2.2-py313h16366db_0.conda sha256: b50a9d64aabd30c05e405cc1166f21fd7dee8d1b42ef38116701883d3bd4d5fa md5: c8185e1891ace76e565b4c28dd50ed5d depends: - python - __osx >=10.13 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping size: 239894 timestamp: 1769678319684 - conda: https://prefix.dev/conda-forge/osx-arm64/psutil-7.2.2-py311he363849_0.conda sha256: 2b774e8f4ccaac8783d1908f281e4bb20b7036d6708dc913ee7811b070f5b4b5 md5: 7cff50265141513c960f00ba586780ea depends: - python - python 3.11.* *_cpython - __osx >=11.0 - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=compressed-mapping size: 245203 timestamp: 1769678306347 - conda: https://prefix.dev/conda-forge/osx-arm64/psutil-7.2.2-py313h6688731_0.conda sha256: 1d2a6039fb71d61134b1d6816202529f2f6286c83b59bc1491fd288f5c08046e md5: ba2d89e51a855963c767648f44c03871 depends: - python - __osx >=11.0 - python 3.13.* *_cp313 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping size: 242596 timestamp: 1769678288893 - conda: https://prefix.dev/conda-forge/win-64/psutil-7.2.2-py311hf893f09_0.conda sha256: 32da17824abadd1f5b46faedfa4964c7b1817b11887c2e8bb4e48628da51b93a md5: fd968cdacc7967efd0ff5ef1805b812c depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=compressed-mapping size: 249478 timestamp: 1769678166841 - conda: https://prefix.dev/conda-forge/win-64/psutil-7.2.2-py313h5fd188c_0.conda sha256: 3ec3373748f83069bef93b540de416e637ee30231b222d5df8f712e93f2f9195 md5: 761b299a6289c77459defea3563f8fc0 depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=compressed-mapping size: 246062 timestamp: 1769678176886 - conda: https://prefix.dev/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 md5: b3c17d95b5a10c6e64a21fa17573e70e depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 license: MIT license_family: MIT purls: [] size: 8252 timestamp: 1726802366959 - conda: https://prefix.dev/conda-forge/osx-64/pthread-stubs-0.4-h00291cd_1002.conda sha256: 05944ca3445f31614f8c674c560bca02ff05cb51637a96f665cb2bbe496099e5 md5: 8bcf980d2c6b17094961198284b8e862 depends: - __osx >=10.13 license: MIT license_family: MIT purls: [] size: 8364 timestamp: 1726802331537 - conda: https://prefix.dev/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda sha256: 8ed65e17fbb0ca944bfb8093b60086e3f9dd678c3448b5de212017394c247ee3 md5: 415816daf82e0b23a736a069a75e9da7 depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 8381 timestamp: 1726802424786 - conda: https://prefix.dev/conda-forge/win-64/pthread-stubs-0.4-h0e40799_1002.conda sha256: 7e446bafb4d692792310ed022fe284e848c6a868c861655a92435af7368bae7b md5: 3c8f2573569bb816483e5cf57efbbe29 depends: - libgcc >=13 - libwinpthread >=12.0.0.r4.gg4f2fc60ca - ucrt >=10.0.20348.0 license: MIT license_family: MIT purls: [] size: 9389 timestamp: 1726802555076 - conda: https://prefix.dev/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda sha256: a7713dfe30faf17508ec359e0bc7e0983f5d94682492469bd462cdaae9c64d83 md5: 7d9daffbb8d8e0af0f769dbbcd173a54 depends: - python >=3.9 license: ISC purls: - pkg:pypi/ptyprocess?source=hash-mapping size: 19457 timestamp: 1733302371990 - conda: https://prefix.dev/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda sha256: 71bd24600d14bb171a6321d523486f6a06f855e75e547fa0cb2a0953b02047f0 md5: 3bfdfb8dbcdc4af1ae3f9a8eb3948f04 depends: - python >=3.9 license: MIT license_family: MIT purls: - pkg:pypi/pure-eval?source=hash-mapping size: 16668 timestamp: 1733569518868 - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-23.0.0-py311h38be061_0.conda sha256: f09158e5e71c3f4811567bb4b1b9f4e9cb9b81d46d3d9b7dc2ba74518af3dfd4 md5: d5d93e5f974929ce53711a5987084b6a depends: - libarrow-acero 23.0.0.* - libarrow-dataset 23.0.0.* - libarrow-substrait 23.0.0.* - libparquet 23.0.0.* - pyarrow-core 23.0.0 *_0_* - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: Apache-2.0 license_family: APACHE purls: [] size: 27282 timestamp: 1769291524210 - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-23.0.0-py313h78bf25f_0.conda sha256: 43636b4ce58c57f3aeab182238b47cb8b860d2cc0544c184612c15ee294be154 md5: a6e89cb214f318db9548b791ba27f862 depends: - libarrow-acero 23.0.0.* - libarrow-dataset 23.0.0.* - libarrow-substrait 23.0.0.* - libparquet 23.0.0.* - pyarrow-core 23.0.0 *_0_* - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: APACHE purls: [] size: 27332 timestamp: 1769291558903 - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-23.0.0-py311h6eed73b_0.conda sha256: cdf3babbd44f9054442fb3777e3d79492b11af68031da5b99d67f381c8f48719 md5: 5d9d243e8482b06cb74d96b10c53d25e depends: - libarrow-acero 23.0.0.* - libarrow-dataset 23.0.0.* - libarrow-substrait 23.0.0.* - libparquet 23.0.0.* - pyarrow-core 23.0.0 *_0_* - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: Apache-2.0 license_family: APACHE purls: [] size: 27270 timestamp: 1769291519463 - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-23.0.0-py313habf4b1d_0.conda sha256: f7be5632510f97483e89e296d2929006fb3b741cffa89a872a09a09cedd3bb97 md5: 5a1b0ff8d04d3343edda66e26425523a depends: - libarrow-acero 23.0.0.* - libarrow-dataset 23.0.0.* - libarrow-substrait 23.0.0.* - libparquet 23.0.0.* - pyarrow-core 23.0.0 *_0_* - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: APACHE purls: [] size: 27296 timestamp: 1769291600131 - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-23.0.0-py311ha1ab1f8_0.conda sha256: d7e98688335fff0cd8b70f9603ca15e7aac1fb7688dbf95a074b9f08d54a879b md5: a2ffc52baddc78db2a82464822ab8949 depends: - libarrow-acero 23.0.0.* - libarrow-dataset 23.0.0.* - libarrow-substrait 23.0.0.* - libparquet 23.0.0.* - pyarrow-core 23.0.0 *_0_* - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: Apache-2.0 license_family: APACHE purls: [] size: 27332 timestamp: 1769291583924 - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-23.0.0-py313h39782a4_0.conda sha256: 9af37dec78650b05f6dd71d59253ad6d698ec13bd306e3297647220cbbac3185 md5: fc6e7ad12d5282ee9388a77857efb7d9 depends: - libarrow-acero 23.0.0.* - libarrow-dataset 23.0.0.* - libarrow-substrait 23.0.0.* - libparquet 23.0.0.* - pyarrow-core 23.0.0 *_0_* - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/pyarrow?source=compressed-mapping size: 27364 timestamp: 1769291809290 - conda: https://prefix.dev/conda-forge/win-64/pyarrow-23.0.0-py311h1ea47a8_0.conda sha256: 0e20ed578538cae31afa69ead04305b59268a684a32b3a25f658a9270dfe2ff4 md5: efe9e26c8fd63fc6d2fdd2b1c2c2baa1 depends: - libarrow-acero 23.0.0.* - libarrow-dataset 23.0.0.* - libarrow-substrait 23.0.0.* - libparquet 23.0.0.* - pyarrow-core 23.0.0 *_0_* - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: Apache-2.0 license_family: APACHE purls: [] size: 27680 timestamp: 1769291926028 - conda: https://prefix.dev/conda-forge/win-64/pyarrow-23.0.0-py313hfa70ccb_0.conda sha256: 81c6b479098eca295fa3dec6a55e4bc3a25ea2851a3a73b78d9ed2eabe10bdd2 md5: 8b80b54f9b732e3165cedad435dc70ab depends: - libarrow-acero 23.0.0.* - libarrow-dataset 23.0.0.* - libarrow-substrait 23.0.0.* - libparquet 23.0.0.* - pyarrow-core 23.0.0 *_0_* - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: APACHE purls: [] size: 27654 timestamp: 1769292053888 - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-core-23.0.0-py311h342b5a4_0_cpu.conda sha256: 41da00406d130653849bb9a3a1c3046213ea5b4ceedf3abd2f0144b5b2bc84e0 md5: 4985c9e042760316abf918989fb35551 depends: - __glibc >=2.17,<3.0.a0 - libarrow 23.0.0.* *cpu - libarrow-compute 23.0.0.* *cpu - libgcc >=14 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 constrains: - apache-arrow-proc * cpu - numpy >=1.21,<3 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/pyarrow?source=hash-mapping size: 4800500 timestamp: 1769291364477 - conda: https://prefix.dev/conda-forge/linux-64/pyarrow-core-23.0.0-py313he109ebe_0_cpu.conda sha256: 1914b79fe640a60b7ab240d90548f601c43513ef39bc6bc8517d73f259acfce1 md5: 9120bf253ebbdb0015069b9a25cf4d36 depends: - __glibc >=2.17,<3.0.a0 - libarrow 23.0.0.* *cpu - libarrow-compute 23.0.0.* *cpu - libgcc >=14 - libstdcxx >=14 - libzlib >=1.3.1,<2.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: - numpy >=1.21,<3 - apache-arrow-proc * cpu license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/pyarrow?source=hash-mapping size: 4751647 timestamp: 1769291378117 - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-core-23.0.0-py311hb7850dc_0_cpu.conda sha256: 3f38120f71960bed5a3c443848934c3c44ee52856018e6a7d8a2d6b477924fd4 md5: da769040dbaf7416253eb8e840b10446 depends: - __osx >=10.13 - libarrow 23.0.0.* *cpu - libarrow-compute 23.0.0.* *cpu - libcxx >=21 - libzlib >=1.3.1,<2.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 constrains: - apache-arrow-proc * cpu - numpy >=1.21,<3 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/pyarrow?source=hash-mapping size: 4052384 timestamp: 1769291481411 - conda: https://prefix.dev/conda-forge/osx-64/pyarrow-core-23.0.0-py313h7c712a9_0_cpu.conda sha256: f6ec4f8de08c0212501675555954a8f5f203d63cdd4eca2f034541619bb7fbb5 md5: 8c51b7be069b1faa48981caa133f440b depends: - __osx >=10.13 - libarrow 23.0.0.* *cpu - libarrow-compute 23.0.0.* *cpu - libcxx >=21 - libzlib >=1.3.1,<2.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: - apache-arrow-proc * cpu - numpy >=1.21,<3 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/pyarrow?source=hash-mapping size: 4423383 timestamp: 1769291556104 - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-core-23.0.0-py311h311f44d_0_cpu.conda sha256: 92773c3e6e2b8a197f02ac117dffa25e66af6b87c76a7f3a9612c4868693abfd md5: 3312e4cd2e5937479d009a02fb172808 depends: - __osx >=11.0 - libarrow 23.0.0.* *cpu - libarrow-compute 23.0.0.* *cpu - libcxx >=21 - libzlib >=1.3.1,<2.0a0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 constrains: - numpy >=1.21,<3 - apache-arrow-proc * cpu license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/pyarrow?source=hash-mapping size: 4303470 timestamp: 1769291542117 - conda: https://prefix.dev/conda-forge/osx-arm64/pyarrow-core-23.0.0-py313hfb690af_0_cpu.conda sha256: 59f1452c5274f5bef0872ddacaf1c4891c0a7a0d1f51de4342b0fc637a456eca md5: 17395366e9516f9663f0c1a9342feb2a depends: - __osx >=11.0 - libarrow 23.0.0.* *cpu - libarrow-compute 23.0.0.* *cpu - libcxx >=21 - libzlib >=1.3.1,<2.0a0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 constrains: - apache-arrow-proc * cpu - numpy >=1.21,<3 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/pyarrow?source=compressed-mapping size: 3895121 timestamp: 1769291764471 - conda: https://prefix.dev/conda-forge/win-64/pyarrow-core-23.0.0-py311ha836b3b_0_cpu.conda sha256: fca59cb950e9338b4d1d2cdc4913a84133ea6fad2f35067786257a94d3e5beba md5: 13ab2a3ea12be25a0d36fbaa4393a832 depends: - libarrow 23.0.0.* *cpu - libarrow-compute 23.0.0.* *cpu - libzlib >=1.3.1,<2.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - apache-arrow-proc * cpu - numpy >=1.21,<3 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/pyarrow?source=hash-mapping size: 3648531 timestamp: 1769291508341 - conda: https://prefix.dev/conda-forge/win-64/pyarrow-core-23.0.0-py313h5921983_0_cpu.conda sha256: d73caf8cf1f46d455402bfc2cf0fd2df6a6708f8c5ba801adee7d3b48a05d88c md5: 21e4e6043a16516491070395dcb716e1 depends: - libarrow 23.0.0.* *cpu - libarrow-compute 23.0.0.* *cpu - libzlib >=1.3.1,<2.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - apache-arrow-proc * cpu - numpy >=1.21,<3 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/pyarrow?source=hash-mapping size: 3571913 timestamp: 1769291508255 - conda: https://prefix.dev/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda sha256: 79db7928d13fab2d892592223d7570f5061c192f27b9febd1a418427b719acc6 md5: 12c566707c80111f9799308d9e265aef depends: - python >=3.9 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pycparser?source=hash-mapping size: 110100 timestamp: 1733195786147 - conda: https://prefix.dev/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a md5: 6b6ece66ebcae2d5f326c77ef2c5a066 depends: - python >=3.9 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/pygments?source=hash-mapping size: 889287 timestamp: 1750615908735 - conda: https://prefix.dev/conda-forge/noarch/pymdown-extensions-10.21.1-pyhd8ed1ab_0.conda sha256: 405e0a5e43ccf7c1cd084932e97291c3cf934036e8569e9cc0ccc91371aae93b md5: d08476fd9134bf9a37edb06c4d65f441 depends: - markdown >=3.6 - python >=3.10 - pyyaml license: MIT license_family: MIT size: 171234 timestamp: 1769322477196 - conda: https://prefix.dev/conda-forge/osx-64/pyobjc-core-12.1-py313h07bcf3a_0.conda sha256: 1e0edd34b804e20ba064dcebcfce3066d841ec812f29ed65902da7192af617d1 md5: 6a2c3a617a70f97ca53b7b88461b1c27 depends: - __osx >=10.13 - libffi >=3.5.2,<3.6.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - setuptools license: MIT license_family: MIT purls: - pkg:pypi/pyobjc-core?source=hash-mapping size: 491157 timestamp: 1763151415674 - conda: https://prefix.dev/conda-forge/osx-arm64/pyobjc-core-12.1-py313h40b429f_0.conda sha256: 307ca29ebf2317bd2561639b1ee0290fd8c03c3450fa302b9f9437d8df6a5280 md5: 31a0a72f3466682d0ea2ebcbd7d319b8 depends: - __osx >=11.0 - libffi >=3.5.2,<3.6.0a0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 - setuptools license: MIT license_family: MIT purls: - pkg:pypi/pyobjc-core?source=hash-mapping size: 481508 timestamp: 1763152124940 - conda: https://prefix.dev/conda-forge/osx-64/pyobjc-framework-cocoa-12.1-py313hf669bc3_0.conda sha256: 4761b8448bb9ecfcd9636a506104e6474e0f4cb73d108f2088997702ae984a00 md5: 628b5ad83d6140fe4bfa937e2f357ed7 depends: - __osx >=10.13 - libffi >=3.5.2,<3.6.0a0 - pyobjc-core 12.1.* - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/pyobjc-framework-cocoa?source=hash-mapping size: 374120 timestamp: 1763160397755 - conda: https://prefix.dev/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py313hcc5defa_0.conda sha256: 194e188d8119befc952d04157079733e2041a7a502d50340ddde632658799fdc md5: a6d28c8fc266a3d3c3dae183e25c4d31 depends: - __osx >=11.0 - libffi >=3.5.2,<3.6.0a0 - pyobjc-core 12.1.* - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/pyobjc-framework-cocoa?source=hash-mapping size: 376136 timestamp: 1763160678792 - conda: https://prefix.dev/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda sha256: 417fba4783e528ee732afa82999300859b065dc59927344b4859c64aae7182de md5: 3687cc0b82a8b4c17e1f0eb7e47163d5 depends: - python >=3.10 - python license: MIT license_family: MIT purls: - pkg:pypi/pyparsing?source=compressed-mapping size: 110893 timestamp: 1769003998136 - conda: https://prefix.dev/conda-forge/linux-64/pyside6-6.10.1-py313h85046ba_0.conda sha256: da92b567be00f47f805f2d58a0f91611b7df73c3b7aa49f903436aec7dc4cae7 md5: 2c5d21d466ef1ff0c0a98cfdbaf5c64b depends: - __glibc >=2.17,<3.0.a0 - libclang13 >=21.1.7 - libegl >=1.7.0,<2.0a0 - libgcc >=14 - libgl >=1.7.0,<2.0a0 - libopengl >=1.7.0,<2.0a0 - libstdcxx >=14 - libvulkan-loader >=1.4.328.1,<2.0a0 - libxml2 - libxml2-16 >=2.14.6 - libxslt >=1.1.43,<2.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - qt6-main 6.10.1.* - qt6-main >=6.10.1,<6.11.0a0 license: LGPL-3.0-only license_family: LGPL purls: - pkg:pypi/pyside6?source=hash-mapping - pkg:pypi/shiboken6?source=hash-mapping size: 11629969 timestamp: 1765811902254 - conda: https://prefix.dev/conda-forge/win-64/pyside6-6.10.1-py313h475ba69_0.conda sha256: 7520efebc256983aa64778d5198f3e8ea1bbc370a0cd9d3f4760bda4d4dd06e8 md5: 1b3404ee1a66ab0205db2a19096efbc2 depends: - libclang13 >=21.1.7 - libvulkan-loader >=1.4.328.1,<2.0a0 - libxml2 - libxml2-16 >=2.14.6 - libxslt >=1.1.43,<2.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - qt6-main 6.10.1.* - qt6-main >=6.10.1,<6.11.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: LGPL-3.0-only license_family: LGPL purls: - pkg:pypi/pyside6?source=hash-mapping - pkg:pypi/shiboken6?source=hash-mapping size: 9044031 timestamp: 1765812223474 - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda sha256: d016e04b0e12063fbee4a2d5fbb9b39a8d191b5a0042f0b8459188aedeabb0ca md5: e2fd202833c4a981ce8a65974fe4abd1 depends: - __win - python >=3.9 - win_inet_pton license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pysocks?source=hash-mapping size: 21784 timestamp: 1733217448189 - conda: https://prefix.dev/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 md5: 461219d1a5bd61342293efa2c0c90eac depends: - __unix - python >=3.9 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pysocks?source=hash-mapping size: 21085 timestamp: 1733217331982 - conda: https://prefix.dev/conda-forge/noarch/pytest-9.0.2-pyhcf101f3_0.conda sha256: 9e749fb465a8bedf0184d8b8996992a38de351f7c64e967031944978de03a520 md5: 2b694bad8a50dc2f712f5368de866480 depends: - pygments >=2.7.2 - python >=3.10 - iniconfig >=1.0.1 - packaging >=22 - pluggy >=1.5,<2 - tomli >=1 - colorama >=0.4 - exceptiongroup >=1 - python constrains: - pytest-faulthandler >=2 license: MIT license_family: MIT purls: - pkg:pypi/pytest?source=hash-mapping size: 299581 timestamp: 1765062031645 - conda: https://prefix.dev/conda-forge/linux-64/pytest-codspeed-4.2.0-py311haee01d2_1.conda sha256: 75d8ae0fcabf91b8bb35df8f277fde71f67f2cdfb4155195caf9bc476966371b md5: f6dca9b7bd75e70f0fe9e5bbf3272446 depends: - python - cffi >=1.17.1 - setuptools - pytest >=3.8 - rich >=13.8.1 - importlib-metadata >=8.5.0 - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python_abi 3.11.* *_cp311 license: MIT license_family: MIT purls: - pkg:pypi/pytest-codspeed?source=hash-mapping size: 140152 timestamp: 1761906225486 - conda: https://prefix.dev/conda-forge/linux-64/pytest-codspeed-4.2.0-py313h54dd161_1.conda sha256: c2b1efd5e2aaf53332427ca721cc4e2279f7955b6e2de9a3e4bfa4328698e34b md5: 32995b46c043930720d33214db571000 depends: - python - cffi >=1.17.1 - setuptools - pytest >=3.8 - rich >=13.8.1 - importlib-metadata >=8.5.0 - libgcc >=14 - __glibc >=2.17,<3.0.a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/pytest-codspeed?source=hash-mapping size: 138589 timestamp: 1761906223406 - conda: https://prefix.dev/conda-forge/osx-64/pytest-codspeed-4.2.0-py311h62e9434_1.conda sha256: 6f2c9f69d04375600faa645373ddf9ef1d0221e82b6df282a5a12d5a47a8dd5b md5: 576383ac6a4e1c52db23aba497045ace depends: - python - cffi >=1.17.1 - setuptools - pytest >=3.8 - rich >=13.8.1 - importlib-metadata >=8.5.0 - python_abi 3.11.* *_cp311 license: MIT license_family: MIT purls: - pkg:pypi/pytest-codspeed?source=hash-mapping size: 120708 timestamp: 1761906291849 - conda: https://prefix.dev/conda-forge/osx-64/pytest-codspeed-4.2.0-py313hcb05632_1.conda sha256: 6ba8bb62131ffbfa428d865ff54d1b7e79f0dd4f10b15eaac410ad48e5e22bb3 md5: a06930408ae963aae3b49912606205e2 depends: - python - cffi >=1.17.1 - setuptools - pytest >=3.8 - rich >=13.8.1 - importlib-metadata >=8.5.0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/pytest-codspeed?source=hash-mapping size: 119764 timestamp: 1761906287800 - conda: https://prefix.dev/conda-forge/osx-arm64/pytest-codspeed-4.2.0-py311h5bb9006_1.conda sha256: 7fa449f1cbf73f2374500f988a17edcce9832f792046d7ef3327e98b2130dc95 md5: e13433c00f022527b990ae75245cd3b5 depends: - python - cffi >=1.17.1 - setuptools - pytest >=3.8 - rich >=13.8.1 - importlib-metadata >=8.5.0 - python 3.11.* *_cpython - python_abi 3.11.* *_cp311 license: MIT license_family: MIT purls: - pkg:pypi/pytest-codspeed?source=hash-mapping size: 127281 timestamp: 1761906299237 - conda: https://prefix.dev/conda-forge/osx-arm64/pytest-codspeed-4.2.0-py313h9734d34_1.conda sha256: 009fefd6067a822cfdf1e9e3694d843a2461017fd976a1c84406acbbd6729acc md5: 0ed85b986dd0994e39f40c7e827f6731 depends: - python - cffi >=1.17.1 - setuptools - pytest >=3.8 - rich >=13.8.1 - importlib-metadata >=8.5.0 - python 3.13.* *_cp313 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/pytest-codspeed?source=hash-mapping size: 126429 timestamp: 1761906282923 - conda: https://prefix.dev/conda-forge/win-64/pytest-codspeed-4.2.0-py311hf893f09_1.conda sha256: 235f7d89bbda0e76b1e972e4ccee6507c01fa45a4d185a39c1c38a8a69f077ca md5: b13865f8e62bf72a8df83e01993879a7 depends: - python - cffi >=1.17.1 - setuptools - pytest >=3.8 - rich >=13.8.1 - importlib-metadata >=8.5.0 - python_abi 3.11.* *_cp311 license: MIT license_family: MIT purls: - pkg:pypi/pytest-codspeed?source=hash-mapping size: 120852 timestamp: 1761906266245 - conda: https://prefix.dev/conda-forge/win-64/pytest-codspeed-4.2.0-py313h5fd188c_1.conda sha256: 22c041fe60bce99575fe22373b447f16adf924d4baab182ed20e49f6616306d6 md5: 5a60e4b3b1889bd9a8469a37d7e528d3 depends: - python - cffi >=1.17.1 - setuptools - pytest >=3.8 - rich >=13.8.1 - importlib-metadata >=8.5.0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/pytest-codspeed?source=hash-mapping size: 119975 timestamp: 1761906284711 - conda: https://prefix.dev/conda-forge/noarch/pytest-cov-7.0.0-pyhcf101f3_1.conda sha256: d0f45586aad48ef604590188c33c83d76e4fc6370ac569ba0900906b24fd6a26 md5: 6891acad5e136cb62a8c2ed2679d6528 depends: - coverage >=7.10.6 - pluggy >=1.2 - pytest >=7 - python >=3.10 - python license: MIT license_family: MIT purls: - pkg:pypi/pytest-cov?source=hash-mapping size: 29016 timestamp: 1757612051022 - conda: https://prefix.dev/conda-forge/noarch/pytest-json-report-1.5.0-pyhd8ed1ab_0.tar.bz2 sha256: ed916397b9caec080b929d24c62a91654fd829b6d6569ccd573cb2aeb12e70aa md5: 837e335fa428cf7c784ee2e80594506c depends: - pytest >=3.8.0 - pytest-metadata - python >=3.6 license: MIT license_family: MIT purls: - pkg:pypi/pytest-json-report?source=hash-mapping size: 15397 timestamp: 1647447962029 - conda: https://prefix.dev/conda-forge/noarch/pytest-metadata-3.1.1-pyhd8ed1ab_1.conda sha256: 6ac0d0e0f5136bcacb1a168f220e7d4ad13a65b3aa3fec534c3a214f209be4f8 md5: c4b7295798eff80144dc4ca4551efa80 depends: - pytest >=7.0.0 - python >=3.9 license: MPL-2.0 license_family: OTHER purls: - pkg:pypi/pytest-metadata?source=hash-mapping size: 14532 timestamp: 1734146281190 - conda: https://prefix.dev/conda-forge/noarch/pytest-xdist-3.8.0-pyhd8ed1ab_0.conda sha256: b7b58a5be090883198411337b99afb6404127809c3d1c9f96e99b59f36177a96 md5: 8375cfbda7c57fbceeda18229be10417 depends: - execnet >=2.1 - pytest >=7.0.0 - python >=3.9 constrains: - psutil >=3.0 license: MIT license_family: MIT purls: - pkg:pypi/pytest-xdist?source=hash-mapping size: 39300 timestamp: 1751452761594 - conda: https://prefix.dev/conda-forge/linux-64/python-3.11.14-hd63d673_3_cpython.conda build_number: 3 sha256: 41b29c2d62f7028bb7bb05eef3ff55f81e3c1cb40e76ba95a890a058fbc2a896 md5: 26d8f4db8c578dedba9f2c11423e59e5 depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - ld_impl_linux-64 >=2.36.1 - libexpat >=2.7.3,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - liblzma >=5.8.2,<6.0a0 - libnsl >=2.0.1,<2.1.0a0 - libsqlite >=3.51.2,<4.0a0 - libuuid >=2.41.3,<3.0a0 - libxcrypt >=4.4.36 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - openssl >=3.5.4,<4.0a0 - readline >=8.3,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata constrains: - python_abi 3.11.* *_cp311 license: Python-2.0 purls: [] size: 30905206 timestamp: 1769472446175 - conda: https://prefix.dev/conda-forge/linux-64/python-3.13.11-hc97d973_101_cp313.conda build_number: 101 sha256: c9625638f32f4ee27a506e8cefc56a78110c4c54867663f56d91dc721df9dc7f md5: aa23b675b860f2566af2dfb3ffdf3b8c depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - ld_impl_linux-64 >=2.36.1 - libexpat >=2.7.3,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - liblzma >=5.8.2,<6.0a0 - libmpdec >=4.0.0,<5.0a0 - libsqlite >=3.51.2,<4.0a0 - libuuid >=2.41.3,<3.0a0 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - openssl >=3.5.4,<4.0a0 - python_abi 3.13.* *_cp313 - readline >=8.3,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata license: Python-2.0 purls: [] size: 37170676 timestamp: 1769473304794 python_site_packages_path: lib/python3.13/site-packages - conda: https://prefix.dev/conda-forge/osx-64/python-3.11.14-h74c2667_3_cpython.conda build_number: 3 sha256: 327d6c5eb61657d4b76e1024da9c790d3e7aacee84487403e9eef1b730982e63 md5: df79e5958af70212260d5e163e867d98 depends: - __osx >=10.13 - bzip2 >=1.0.8,<2.0a0 - libexpat >=2.7.3,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - liblzma >=5.8.2,<6.0a0 - libsqlite >=3.51.2,<4.0a0 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - openssl >=3.5.4,<4.0a0 - readline >=8.3,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata constrains: - python_abi 3.11.* *_cp311 license: Python-2.0 purls: [] size: 15666344 timestamp: 1769473006716 - conda: https://prefix.dev/conda-forge/osx-64/python-3.13.11-h17c18a5_101_cp313.conda build_number: 101 sha256: e4b1ce43f1bbe9bbda604fe465f07131e568ba1877ac2562c3148bb13c4bfe79 md5: aa0e1db83fc31e7c5281337b4207a5cb depends: - __osx >=10.13 - bzip2 >=1.0.8,<2.0a0 - libexpat >=2.7.3,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - liblzma >=5.8.2,<6.0a0 - libmpdec >=4.0.0,<5.0a0 - libsqlite >=3.51.2,<4.0a0 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - openssl >=3.5.4,<4.0a0 - python_abi 3.13.* *_cp313 - readline >=8.3,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata license: Python-2.0 purls: [] size: 17530878 timestamp: 1769473237113 python_site_packages_path: lib/python3.13/site-packages - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.11.14-h18782d2_3_cpython.conda build_number: 3 sha256: f862d544a455bedfa5d77305f0a42c8e3392956e364f8f92d6ca1c844fb3fbd1 md5: b8f6a28ffd3c97367d4e58e8793ff47c depends: - __osx >=11.0 - bzip2 >=1.0.8,<2.0a0 - libexpat >=2.7.3,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - liblzma >=5.8.2,<6.0a0 - libsqlite >=3.51.2,<4.0a0 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - openssl >=3.5.4,<4.0a0 - readline >=8.3,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata constrains: - python_abi 3.11.* *_cp311 license: Python-2.0 purls: [] size: 13707418 timestamp: 1769472290774 - conda: https://prefix.dev/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_101_cp313.conda build_number: 101 sha256: 8565d451dff3cda5e55fabdbae2751033c2b08b3fd3833526f8dbf3c08bcb3cf md5: 8f2ac152fe98c22af0f4b479cf11c845 depends: - __osx >=11.0 - bzip2 >=1.0.8,<2.0a0 - libexpat >=2.7.3,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - liblzma >=5.8.2,<6.0a0 - libmpdec >=4.0.0,<5.0a0 - libsqlite >=3.51.2,<4.0a0 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - openssl >=3.5.4,<4.0a0 - python_abi 3.13.* *_cp313 - readline >=8.3,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata license: Python-2.0 purls: [] size: 12806076 timestamp: 1769472806227 python_site_packages_path: lib/python3.13/site-packages - conda: https://prefix.dev/conda-forge/win-64/python-3.11.14-h0159041_3_cpython.conda build_number: 3 sha256: 5676dadd9d4fba1bce51bd7e5cf8fcf76f85b88b7baa15bd10ca00557e67f10e md5: 05ded1dca7befb66ec95a9ec6d34a71a depends: - bzip2 >=1.0.8,<2.0a0 - libexpat >=2.7.3,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - liblzma >=5.8.2,<6.0a0 - libsqlite >=3.51.2,<4.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 constrains: - python_abi 3.11.* *_cp311 license: Python-2.0 purls: [] size: 18353938 timestamp: 1769471078924 - conda: https://prefix.dev/conda-forge/win-64/python-3.13.11-h09917c8_101_cp313.conda build_number: 101 sha256: c1960ba5e6a53e18514693839a43442de9c6118180eeb1c97f91c93b8cd7e5de md5: 8e8704ea154373b4b1837087817b9991 depends: - bzip2 >=1.0.8,<2.0a0 - libexpat >=2.7.3,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - liblzma >=5.8.2,<6.0a0 - libmpdec >=4.0.0,<5.0a0 - libsqlite >=3.51.2,<4.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - python_abi 3.13.* *_cp313 - tk >=8.6.13,<8.7.0a0 - tzdata - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Python-2.0 purls: [] size: 16456375 timestamp: 1769471259247 python_site_packages_path: Lib/site-packages - conda: https://prefix.dev/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda sha256: d6a17ece93bbd5139e02d2bd7dbfa80bee1a4261dced63f65f679121686bf664 md5: 5b8d21249ff20967101ffa321cab24e8 depends: - python >=3.9 - six >=1.5 - python license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/python-dateutil?source=hash-mapping size: 233310 timestamp: 1751104122689 - conda: https://prefix.dev/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda sha256: df9aa74e9e28e8d1309274648aac08ec447a92512c33f61a8de0afa9ce32ebe8 md5: 23029aae904a2ba587daba708208012f depends: - python >=3.9 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/fastjsonschema?source=hash-mapping size: 244628 timestamp: 1755304154927 - conda: https://prefix.dev/conda-forge/noarch/python-gil-3.13.11-h4df99d1_101.conda sha256: c17676be5479d9032b54fea09024fc2cdeb689639070b25fa9bd85b32c531a7a md5: 4af7a72062bddcb57dea6b236e1b245e depends: - cpython 3.13.11.* - python_abi * *_cp313 license: Python-2.0 purls: [] size: 48231 timestamp: 1769471383908 - conda: https://prefix.dev/conda-forge/noarch/python-graphblas-2025.2.0-pyhff2d567_0.conda sha256: 6d6c0b006aa8e16c40bf64d529c16506d3772595c455d37df701a59fbb5f58df md5: f4a83fec243c00cd69e617b0e49c1178 depends: - donfig >=0.6 - numba >=0.55 - numpy >=1.23 - python >=3.10 - python-suitesparse-graphblas >=7.4.0.0,<10 - pyyaml >=5.4 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/python-graphblas?source=hash-mapping size: 231579 timestamp: 1739838960727 - conda: https://prefix.dev/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda sha256: 4790787fe1f4e8da616edca4acf6a4f8ed4e7c6967aa31b920208fc8f95efcca md5: a61bf9ec79426938ff785eb69dbb1960 depends: - python >=3.6 license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/python-json-logger?source=hash-mapping size: 13383 timestamp: 1677079727691 - conda: https://prefix.dev/conda-forge/linux-64/python-suitesparse-graphblas-9.4.5.0-py313h585d76f_0.conda sha256: a9218e99a56e11465108cca90022093377ae4b1d356c876bdc7d09fb6bf27bb1 md5: bbe24af91272a9b5974d26b77640657e depends: - __glibc >=2.17,<3.0.a0 - cffi - graphblas >=9.4.5,<9.5.0a0 - libgcc >=13 - numpy >=1.21,<3 - numpy >=1.23 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/suitesparse-graphblas?source=hash-mapping size: 395241 timestamp: 1740464435391 - conda: https://prefix.dev/conda-forge/osx-64/python-suitesparse-graphblas-9.4.5.0-py313hd5e51e8_0.conda sha256: 31d1aea18f1588eea4896494446ba1f14c5329fe2df24b8d33e0d504f993539f md5: 96878a9b36644439d318c7c3b4bd82de depends: - __osx >=10.13 - cffi - graphblas >=9.4.5,<9.5.0a0 - numpy >=1.21,<3 - numpy >=1.23 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/suitesparse-graphblas?source=hash-mapping size: 448612 timestamp: 1740464674789 - conda: https://prefix.dev/conda-forge/osx-arm64/python-suitesparse-graphblas-9.4.5.0-py313h44f8b29_0.conda sha256: 6d961124fac768a36c26a1aea557966aa8560e46a6080d257dc2aee92137dff8 md5: b8ed96f7a1eee563be193954e176a006 depends: - __osx >=11.0 - cffi - graphblas >=9.4.5,<9.5.0a0 - numpy >=1.21,<3 - numpy >=1.23 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/suitesparse-graphblas?source=hash-mapping size: 445171 timestamp: 1740464623468 - conda: https://prefix.dev/conda-forge/win-64/python-suitesparse-graphblas-9.4.5.0-py313ha04d1f9_0.conda sha256: 0ba5213f7248b71ddbd9906a945c017d3d3bd4c7615fd5a5db4d786de891a788 md5: 9efacd4361d57d275d5e6ff1fcf18786 depends: - cffi - graphblas >=9.4.5,<9.5.0a0 - numpy >=1.21,<3 - numpy >=1.23 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/suitesparse-graphblas?source=hash-mapping size: 442655 timestamp: 1740464973787 - conda: https://prefix.dev/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda sha256: 467134ef39f0af2dbb57d78cb3e4821f01003488d331a8dd7119334f4f47bfbd md5: 7ead57407430ba33f681738905278d03 depends: - python >=3.10 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/tzdata?source=compressed-mapping size: 143542 timestamp: 1765719982349 - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.11-8_cp311.conda build_number: 8 sha256: fddf123692aa4b1fc48f0471e346400d9852d96eeed77dbfdd746fa50a8ff894 md5: 8fcb6b0e2161850556231336dae58358 constrains: - python 3.11.* *_cpython license: BSD-3-Clause license_family: BSD purls: [] size: 7003 timestamp: 1752805919375 - conda: https://prefix.dev/conda-forge/noarch/python_abi-3.13-8_cp313.conda build_number: 8 sha256: 210bffe7b121e651419cb196a2a63687b087497595c9be9d20ebe97dd06060a7 md5: 94305520c52a4aa3f6c2b1ff6008d9f8 constrains: - python 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: [] size: 7002 timestamp: 1752805902938 - conda: https://prefix.dev/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda sha256: 8d2a8bf110cc1fc3df6904091dead158ba3e614d8402a83e51ed3a8aa93cdeb0 md5: bc8e3267d44011051f2eb14d22fb0960 depends: - python >=3.9 license: MIT license_family: MIT purls: - pkg:pypi/pytz?source=hash-mapping size: 189015 timestamp: 1742920947249 - conda: https://prefix.dev/conda-forge/win-64/pywin32-311-py313h40c08fc_1.conda sha256: 87eaeb79b5961e0f216aa840bc35d5f0b9b123acffaecc4fda4de48891901f20 md5: 1ce4f826332dca56c76a5b0cc89fb19e depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.13.* *_cp313 license: PSF-2.0 license_family: PSF purls: - pkg:pypi/pywin32?source=hash-mapping size: 6695114 timestamp: 1756487139550 - conda: https://prefix.dev/conda-forge/win-64/pywinpty-2.0.15-py313h5813708_1.conda sha256: d34a7cd0a4a7dc79662cb6005e01d630245d9a942e359eb4d94b2fb464ed2552 md5: 8f01ed27e2baa455e753301218e054fd depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 - winpty license: MIT license_family: MIT purls: - pkg:pypi/pywinpty?source=hash-mapping size: 216075 timestamp: 1759556799508 - conda: https://prefix.dev/conda-forge/linux-64/pyyaml-6.0.3-py311h3778330_0.conda sha256: 7dc5c27c0c23474a879ef5898ed80095d26de7f89f4720855603c324cca19355 md5: 707c3d23f2476d3bfde8345b4e7d7853 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping size: 211606 timestamp: 1758892088237 - conda: https://prefix.dev/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_0.conda sha256: 40dcd6718dce5fbee8aabdd0519f23d456d8feb2e15ac352eaa88bbfd3a881af md5: 4794ea0adaebd9f844414e594b142cb2 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping size: 207109 timestamp: 1758892173548 - conda: https://prefix.dev/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_1.conda sha256: ef7df29b38ef04ec67a8888a4aa039973eaa377e8c4b59a7be0a1c50cd7e4ac6 md5: f256753e840c3cd3766488c9437a8f8b depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=compressed-mapping size: 201616 timestamp: 1770223543730 - conda: https://prefix.dev/conda-forge/noarch/pyyaml-6.0.3-pyh7db6752_0.conda sha256: 828af2fd7bb66afc9ab1c564c2046be391aaf66c0215f05afaf6d7a9a270fe2a md5: b12f41c0d7fb5ab81709fcc86579688f depends: - python >=3.10.* - yaml track_features: - pyyaml_no_compile license: MIT license_family: MIT size: 45223 timestamp: 1758891992558 - conda: https://prefix.dev/conda-forge/osx-64/pyyaml-6.0.3-py311he13f9b5_0.conda sha256: be448cd6d759cd21d40bc9a3850672187a8d37fcd3abdc3f637abc0ca1ed2f44 md5: 2d9ba0ec796516a17d3c87efdb881aff depends: - __osx >=10.13 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping size: 196463 timestamp: 1758892069824 - conda: https://prefix.dev/conda-forge/osx-64/pyyaml-6.0.3-py313h0f4d31d_0.conda sha256: 8420815e10d455b012db39cb7dc0d86f0ac3a287d5a227892fa611fe3d467df9 md5: e0c9e257970870212c449106964a5ace depends: - __osx >=10.13 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping size: 193608 timestamp: 1758892017635 - conda: https://prefix.dev/conda-forge/osx-64/pyyaml-6.0.3-py313h7c6a591_1.conda sha256: ab5f6c27d24facd1832481ccd8f432c676472d57596a3feaa77880a1462cdb2a md5: 0eaf6cf9939bb465ee62b17d04254f9e depends: - __osx >=10.13 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=compressed-mapping size: 192051 timestamp: 1770223971430 - conda: https://prefix.dev/conda-forge/osx-arm64/pyyaml-6.0.3-py311ha9b3269_0.conda sha256: 747c1b94222481a727aeeb912407f862a93a1bb4e704be3a8236768182ac0290 md5: 109a9c326951cc9ab5df6a06cf5b930a depends: - __osx >=11.0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping size: 195537 timestamp: 1758892104856 - conda: https://prefix.dev/conda-forge/osx-arm64/pyyaml-6.0.3-py313h65a2061_1.conda sha256: 950725516f67c9691d81bb8dde8419581c5332c5da3da10c9ba8cbb1698b825d md5: 5d0c8b92128c93027632ca8f8dc1190f depends: - __osx >=11.0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=compressed-mapping size: 188763 timestamp: 1770224094408 - conda: https://prefix.dev/conda-forge/osx-arm64/pyyaml-6.0.3-py313h7d74516_0.conda sha256: f5be0d84f72a567b7333b9efa74a65bfa44a25658cf107ffa3fc65d3ae6660d7 md5: 0e8e3235217b4483a7461b63dca5826b depends: - __osx >=11.0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping size: 191630 timestamp: 1758892258120 - conda: https://prefix.dev/conda-forge/win-64/pyyaml-6.0.3-py311h3f79411_0.conda sha256: 22dcc6c6779e5bd970a7f5208b871c02bf4985cf4d827d479c4a492ced8ce577 md5: 4e9b677d70d641f233b29d5eab706e20 depends: - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping size: 188290 timestamp: 1758892467876 - conda: https://prefix.dev/conda-forge/win-64/pyyaml-6.0.3-py313hd650c13_0.conda sha256: 5d9fd32d318b9da615524589a372b33a6f3d07db2708de16570d70360bf638c2 md5: c067122d76f8dcbe0848822942ba07be depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping size: 182043 timestamp: 1758892011955 - conda: https://prefix.dev/conda-forge/win-64/pyyaml-6.0.3-py313hd650c13_1.conda sha256: dfaed50de8ee72a51096163b87631921688851001e38c78a841eba1ae8b35889 md5: c1bdb8dd255c79fb9c428ad25cc6ee54 depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - pkg:pypi/pyyaml?source=compressed-mapping size: 180992 timestamp: 1770223457761 - conda: https://prefix.dev/conda-forge/noarch/pyyaml-env-tag-1.1-pyhd8ed1ab_0.conda sha256: 69ab63bd45587406ae911811fc4d4c1bf972d643fa57a009de7c01ac978c4edd md5: e8e53c4150a1bba3b160eacf9d53a51b depends: - python >=3.9 - pyyaml license: MIT license_family: MIT size: 11137 timestamp: 1747237061448 - conda: https://prefix.dev/conda-forge/linux-64/pyzmq-27.1.0-py312hfb55c3c_0.conda noarch: python sha256: a00a41b66c12d9c60e66b391e9a4832b7e28743348cf4b48b410b91927cd7819 md5: 3399d43f564c905250c1aea268ebb935 depends: - python - __glibc >=2.17,<3.0.a0 - libstdcxx >=14 - libgcc >=14 - _python_abi3_support 1.* - cpython >=3.12 - zeromq >=4.3.5,<4.4.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pyzmq?source=hash-mapping size: 212218 timestamp: 1757387023399 - conda: https://prefix.dev/conda-forge/osx-64/pyzmq-27.1.0-py312hb7d603e_0.conda noarch: python sha256: 4e052fa3c4ed319e7bcc441fca09dee4ee4006ac6eb3d036a8d683fceda9304b md5: 81511d0be03be793c622c408c909d6f9 depends: - python - __osx >=10.13 - libcxx >=19 - _python_abi3_support 1.* - cpython >=3.12 - zeromq >=4.3.5,<4.4.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pyzmq?source=hash-mapping size: 191697 timestamp: 1757387104297 - conda: https://prefix.dev/conda-forge/osx-arm64/pyzmq-27.1.0-py312hd65ceae_0.conda noarch: python sha256: ef33812c71eccf62ea171906c3e7fc1c8921f31e9cc1fbc3f079f3f074702061 md5: bbd22b0f0454a5972f68a5f200643050 depends: - python - __osx >=11.0 - libcxx >=19 - _python_abi3_support 1.* - cpython >=3.12 - zeromq >=4.3.5,<4.4.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pyzmq?source=hash-mapping size: 191115 timestamp: 1757387128258 - conda: https://prefix.dev/conda-forge/win-64/pyzmq-27.1.0-py312hbb5da91_0.conda noarch: python sha256: fd46b30e6a1e4c129045e3174446de3ca90da917a595037d28595532ab915c5d md5: 808d263ec97bbd93b41ca01552b5fbd4 depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - zeromq >=4.3.5,<4.3.6.0a0 - _python_abi3_support 1.* - cpython >=3.12 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pyzmq?source=hash-mapping size: 185711 timestamp: 1757387025899 - conda: https://prefix.dev/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda sha256: 776363493bad83308ba30bcb88c2552632581b143e8ee25b1982c8c743e73abc md5: 353823361b1d27eb3960efb076dfcaf6 depends: - __glibc >=2.17,<3.0.a0 - libgcc-ng >=12 - libstdcxx-ng >=12 license: LicenseRef-Qhull purls: [] size: 552937 timestamp: 1720813982144 - conda: https://prefix.dev/conda-forge/osx-64/qhull-2020.2-h3c5361c_5.conda sha256: 79d804fa6af9c750e8b09482559814ae18cd8df549ecb80a4873537a5a31e06e md5: dd1ea9ff27c93db7c01a7b7656bd4ad4 depends: - __osx >=10.13 - libcxx >=16 license: LicenseRef-Qhull purls: [] size: 528122 timestamp: 1720814002588 - conda: https://prefix.dev/conda-forge/osx-arm64/qhull-2020.2-h420ef59_5.conda sha256: 873ac689484262a51fd79bc6103c1a1bedbf524924d7f0088fb80703042805e4 md5: 6483b1f59526e05d7d894e466b5b6924 depends: - __osx >=11.0 - libcxx >=16 license: LicenseRef-Qhull purls: [] size: 516376 timestamp: 1720814307311 - conda: https://prefix.dev/conda-forge/win-64/qhull-2020.2-hc790b64_5.conda sha256: 887d53486a37bd870da62b8fa2ebe3993f912ad04bd755e7ed7c47ced97cbaa8 md5: 854fbdff64b572b5c0b470f334d34c11 depends: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: LicenseRef-Qhull purls: [] size: 1377020 timestamp: 1720814433486 - conda: https://prefix.dev/conda-forge/linux-64/qt6-main-6.10.1-hb82b983_4.conda sha256: 9ff9eeae1f8331f04d6c19bbe53edd5ad10cc3f960376e3c35ad3875546569da md5: f4dfd61ec958d420bebdcefeb805d658 depends: - __glibc >=2.17,<3.0.a0 - alsa-lib >=1.2.15.1,<1.3.0a0 - dbus >=1.16.2,<2.0a0 - double-conversion >=3.4.0,<3.5.0a0 - fontconfig >=2.15.0,<3.0a0 - fonts-conda-ecosystem - harfbuzz >=12.2.0 - icu >=78.1,<79.0a0 - krb5 >=1.21.3,<1.22.0a0 - libclang-cpp21.1 >=21.1.7,<21.2.0a0 - libclang13 >=21.1.7 - libcups >=2.3.3,<2.4.0a0 - libdrm >=2.4.125,<2.5.0a0 - libegl >=1.7.0,<2.0a0 - libfreetype >=2.14.1 - libfreetype6 >=2.14.1 - libgcc >=14 - libgl >=1.7.0,<2.0a0 - libglib >=2.86.3,<3.0a0 - libjpeg-turbo >=3.1.2,<4.0a0 - libllvm21 >=21.1.7,<21.2.0a0 - libpng >=1.6.53,<1.7.0a0 - libpq >=18.1,<19.0a0 - libsqlite >=3.51.1,<4.0a0 - libstdcxx >=14 - libtiff >=4.7.1,<4.8.0a0 - libvulkan-loader >=1.4.328.1,<2.0a0 - libwebp-base >=1.6.0,<2.0a0 - libxcb >=1.17.0,<2.0a0 - libxkbcommon >=1.13.1,<2.0a0 - libxml2 - libxml2-16 >=2.14.6 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - pcre2 >=10.47,<10.48.0a0 - wayland >=1.24.0,<2.0a0 - xcb-util >=0.4.1,<0.5.0a0 - xcb-util-cursor >=0.1.6,<0.2.0a0 - xcb-util-image >=0.4.0,<0.5.0a0 - xcb-util-keysyms >=0.4.1,<0.5.0a0 - xcb-util-renderutil >=0.3.10,<0.4.0a0 - xcb-util-wm >=0.4.2,<0.5.0a0 - xorg-libice >=1.1.2,<2.0a0 - xorg-libsm >=1.2.6,<2.0a0 - xorg-libx11 >=1.8.12,<2.0a0 - xorg-libxcomposite >=0.4.6,<1.0a0 - xorg-libxcursor >=1.2.3,<2.0a0 - xorg-libxdamage >=1.1.6,<2.0a0 - xorg-libxext >=1.3.6,<2.0a0 - xorg-libxrandr >=1.5.4,<2.0a0 - xorg-libxtst >=1.2.5,<2.0a0 - xorg-libxxf86vm >=1.1.6,<2.0a0 - zstd >=1.5.7,<1.6.0a0 constrains: - qt 6.10.1 license: LGPL-3.0-only license_family: LGPL purls: [] size: 57241105 timestamp: 1766486406643 - conda: https://prefix.dev/conda-forge/win-64/qt6-main-6.10.1-h68b6638_4.conda sha256: d1f389aa0c0653d5af83e60da79ca6414d329707f236f110ff5e3329edb94f5a md5: c4a3cf4e79a59cb46ad2d56b74c89e57 depends: - double-conversion >=3.4.0,<3.5.0a0 - harfbuzz >=12.2.0 - icu >=78.1,<79.0a0 - krb5 >=1.21.3,<1.22.0a0 - libclang13 >=21.1.7 - libglib >=2.86.3,<3.0a0 - libjpeg-turbo >=3.1.2,<4.0a0 - libpng >=1.6.53,<1.7.0a0 - libsqlite >=3.51.1,<4.0a0 - libtiff >=4.7.1,<4.8.0a0 - libvulkan-loader >=1.4.328.1,<2.0a0 - libwebp-base >=1.6.0,<2.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.5.4,<4.0a0 - pcre2 >=10.47,<10.48.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - zstd >=1.5.7,<1.6.0a0 constrains: - qt 6.10.1 license: LGPL-3.0-only license_family: LGPL purls: [] size: 85571611 timestamp: 1766493849766 - conda: https://prefix.dev/conda-forge/linux-64/re2-2025.11.05-h5301d42_0.conda sha256: 2f225ddf4a274743045aded48053af65c31721e797a45beed6774fdc783febfb md5: 0227d04521bc3d28c7995c7e1f99a721 depends: - libre2-11 2025.11.05 h7b12aa8_0 license: BSD-3-Clause license_family: BSD purls: [] size: 27316 timestamp: 1762397780316 - conda: https://prefix.dev/conda-forge/osx-64/re2-2025.11.05-h7df6414_0.conda sha256: cd892b6b571fc6aaf9132a859e5ef0fae9e9ff980337ce7284798fa1d24bee5d md5: 13dc8eedbaa30b753546e3d716f51816 depends: - libre2-11 2025.11.05 h554ac88_0 license: BSD-3-Clause license_family: BSD purls: [] size: 27381 timestamp: 1762398153069 - conda: https://prefix.dev/conda-forge/osx-arm64/re2-2025.11.05-h64b956e_0.conda sha256: 29c4bceb6b4530bac6820c30ba5a2f53fd26ed3e7003831ecf394e915b975fbc md5: 1b35e663ed321840af65e7c5cde419f2 depends: - libre2-11 2025.11.05 h91c62da_0 license: BSD-3-Clause license_family: BSD purls: [] size: 27422 timestamp: 1762398340843 - conda: https://prefix.dev/conda-forge/win-64/re2-2025.11.05-ha104f34_0.conda sha256: 9d1bb3d15cdd3257baee5fc063221514482f91154cd1457af126e1ec460bbeac md5: 50746f61f199c4c00d42e33f5d6cfd0b depends: - libre2-11 2025.11.05 h0eb2380_0 license: BSD-3-Clause license_family: BSD purls: [] size: 216623 timestamp: 1762397986736 - conda: https://prefix.dev/conda-forge/linux-64/readline-8.3-h853b02a_0.conda sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 md5: d7d95fc8287ea7bf33e0e7116d2b95ec depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - ncurses >=6.5,<7.0a0 license: GPL-3.0-only license_family: GPL purls: [] size: 345073 timestamp: 1765813471974 - conda: https://prefix.dev/conda-forge/osx-64/readline-8.3-h68b038d_0.conda sha256: 4614af680aa0920e82b953fece85a03007e0719c3399f13d7de64176874b80d5 md5: eefd65452dfe7cce476a519bece46704 depends: - __osx >=10.13 - ncurses >=6.5,<7.0a0 license: GPL-3.0-only license_family: GPL purls: [] size: 317819 timestamp: 1765813692798 - conda: https://prefix.dev/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477 md5: f8381319127120ce51e081dce4865cf4 depends: - __osx >=11.0 - ncurses >=6.5,<7.0a0 license: GPL-3.0-only license_family: GPL purls: [] size: 313930 timestamp: 1765813902568 - conda: https://prefix.dev/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 md5: 870293df500ca7e18bedefa5838a22ab depends: - attrs >=22.2.0 - python >=3.10 - rpds-py >=0.7.0 - typing_extensions >=4.4.0 - python license: MIT license_family: MIT purls: - pkg:pypi/referencing?source=hash-mapping size: 51788 timestamp: 1760379115194 - conda: https://prefix.dev/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda sha256: 7813c38b79ae549504b2c57b3f33394cea4f2ad083f0994d2045c2e24cb538c5 md5: c65df89a0b2e321045a9e01d1337b182 depends: - python >=3.10 - certifi >=2017.4.17 - charset-normalizer >=2,<4 - idna >=2.5,<4 - urllib3 >=1.21.1,<3 - python constrains: - chardet >=3.0.2,<6 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/requests?source=compressed-mapping size: 63602 timestamp: 1766926974520 - conda: https://prefix.dev/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda sha256: 2e4372f600490a6e0b3bac60717278448e323cab1c0fecd5f43f7c56535a99c5 md5: 36de09a8d3e5d5e6f4ee63af49e59706 depends: - python >=3.9 - six license: MIT license_family: MIT purls: - pkg:pypi/rfc3339-validator?source=hash-mapping size: 10209 timestamp: 1733600040800 - conda: https://prefix.dev/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 sha256: 2a5b495a1de0f60f24d8a74578ebc23b24aa53279b1ad583755f223097c41c37 md5: 912a71cc01012ee38e6b90ddd561e36f depends: - python license: MIT license_family: MIT purls: - pkg:pypi/rfc3986-validator?source=hash-mapping size: 7818 timestamp: 1598024297745 - conda: https://prefix.dev/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda sha256: 70001ac24ee62058557783d9c5a7bbcfd97bd4911ef5440e3f7a576f9e43bc92 md5: 7234f99325263a5af6d4cd195035e8f2 depends: - python >=3.9 - lark >=1.2.2 - python license: MIT license_family: MIT purls: - pkg:pypi/rfc3987-syntax?source=hash-mapping size: 22913 timestamp: 1752876729969 - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.1-pyhcf101f3_0.conda sha256: 8d9c9c52bb4d3684d467a6e31814d8c9fccdacc8c50eb1e3e5025e88d6d57cb4 md5: 83d94f410444da5e2f96e5742b7a4973 depends: - markdown-it-py >=2.2.0 - pygments >=2.13.0,<3.0.0 - python >=3.10 - typing_extensions >=4.0.0,<5.0.0 - python license: MIT license_family: MIT purls: - pkg:pypi/rich?source=compressed-mapping size: 208244 timestamp: 1769302653091 - conda: https://prefix.dev/conda-forge/noarch/rich-14.3.2-pyhcf101f3_0.conda sha256: ed17985cec5a0540002c6cabe67848f7cc17e5f4019c0e2a40534e9b7c0b38de md5: 33950a076fd589a7655c6888cc3d2b34 depends: - markdown-it-py >=2.2.0 - pygments >=2.13.0,<3.0.0 - python >=3.10 - typing_extensions >=4.0.0,<5.0.0 - python license: MIT license_family: MIT purls: - pkg:pypi/rich?source=compressed-mapping size: 208269 timestamp: 1769971520792 - conda: https://prefix.dev/conda-forge/linux-64/rpds-py-0.30.0-py313h843e2db_0.conda sha256: 076d26e51c62c8ecfca6eb19e3c1febdd7632df1990a7aa53da5df5e54482b1c md5: 779e3307a0299518713765b83a36f4b1 depends: - python - libgcc >=14 - __glibc >=2.17,<3.0.a0 - python_abi 3.13.* *_cp313 constrains: - __glibc >=2.17 license: MIT license_family: MIT purls: - pkg:pypi/rpds-py?source=hash-mapping size: 383230 timestamp: 1764543223529 - conda: https://prefix.dev/conda-forge/osx-64/rpds-py-0.30.0-py313hcc225dc_0.conda sha256: 8955e67a30f44fbfd390374ba27f445b9e56818b023ccb8fe8f0cd00bec03caa md5: 7c8790b86262342a2c4f4c9709cf61ae depends: - python - __osx >=10.13 - python_abi 3.13.* *_cp313 constrains: - __osx >=10.13 license: MIT license_family: MIT purls: - pkg:pypi/rpds-py?source=hash-mapping size: 370868 timestamp: 1764543169321 - conda: https://prefix.dev/conda-forge/osx-arm64/rpds-py-0.30.0-py313h2c089d5_0.conda sha256: db63344f91e8bfe77703c6764aa9eeafb44d165e286053214722814eabda0264 md5: 190c2d0d4e98ec97df48cdb74caf44d8 depends: - python - __osx >=11.0 - python 3.13.* *_cp313 - python_abi 3.13.* *_cp313 constrains: - __osx >=11.0 license: MIT license_family: MIT purls: - pkg:pypi/rpds-py?source=hash-mapping size: 358961 timestamp: 1764543165314 - conda: https://prefix.dev/conda-forge/win-64/rpds-py-0.30.0-py313hfbe8231_0.conda sha256: 27bd383787c0df7a0a926b11014fd692d60d557398dcf1d50c55aa2378507114 md5: 58ae648b12cfa6df3923b5fd219931cb depends: - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/rpds-py?source=hash-mapping size: 243419 timestamp: 1764543047271 - conda: https://prefix.dev/conda-forge/linux-64/s2n-1.6.2-he8a4886_1.conda sha256: dec76e9faa3173579d34d226dbc91892417a80784911daf8e3f0eb9bad19d7a6 md5: bade189a194e66b93c03021bd36c337b depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - openssl >=3.5.4,<4.0a0 license: Apache-2.0 license_family: Apache purls: [] size: 394197 timestamp: 1765160261434 - conda: https://prefix.dev/conda-forge/linux-64/scikit-learn-1.8.0-np2py311ha15b03d_1.conda sha256: 1b28c914e59b0e346fef3574c192ea919c710784a9b5a4eff640fb81825a91a9 md5: 20166c092c5a5093bbaca59925d573a3 depends: - python - numpy >=1.24.1 - scipy >=1.10.0 - joblib >=1.3.0 - threadpoolctl >=3.2.0 - _openmp_mutex >=4.5 - libstdcxx >=14 - libgcc >=14 - __glibc >=2.17,<3.0.a0 - python_abi 3.11.* *_cp311 - numpy >=1.23,<3 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scikit-learn?source=hash-mapping size: 9975664 timestamp: 1765801236131 - conda: https://prefix.dev/conda-forge/linux-64/scikit-learn-1.8.0-np2py313h16d504d_1.conda sha256: 5195fa9172a31d9f0b643c608aa90fbef4e98a50dd0d896e7d25f2939123c72c md5: d43a148434f123b3e060780d84a05ddc depends: - python - numpy >=1.24.1 - scipy >=1.10.0 - joblib >=1.3.0 - threadpoolctl >=3.2.0 - libgcc >=14 - __glibc >=2.17,<3.0.a0 - _openmp_mutex >=4.5 - libstdcxx >=14 - python_abi 3.13.* *_cp313 - numpy >=1.23,<3 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scikit-learn?source=hash-mapping size: 9897583 timestamp: 1765801239271 - conda: https://prefix.dev/conda-forge/osx-64/scikit-learn-1.8.0-np2py311heeb2b4f_1.conda sha256: deb14afbb25dcdfe178937d2094ed0f1d6c135a67039a58db55da5c26f711802 md5: 325133e9fa12bbcdf2c6efe748cd117b depends: - python - numpy >=1.24.1 - scipy >=1.10.0 - joblib >=1.3.0 - threadpoolctl >=3.2.0 - __osx >=10.13 - libcxx >=19 - llvm-openmp >=19.1.7 - python_abi 3.11.* *_cp311 - numpy >=1.23,<3 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scikit-learn?source=hash-mapping size: 9538949 timestamp: 1766550874894 - conda: https://prefix.dev/conda-forge/osx-64/scikit-learn-1.8.0-np2py313he2891f2_1.conda sha256: 02374f108b175d6af04461ee82423527f6606a1ac5537b31374066ee9ca3d6c6 md5: f650ee53b81fcb9ab2d9433f071c6682 depends: - python - numpy >=1.24.1 - scipy >=1.10.0 - joblib >=1.3.0 - threadpoolctl >=3.2.0 - libcxx >=19 - llvm-openmp >=19.1.7 - __osx >=10.13 - python_abi 3.13.* *_cp313 - numpy >=1.23,<3 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scikit-learn?source=hash-mapping size: 9466389 timestamp: 1766550959465 - conda: https://prefix.dev/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py311hf1dd2ad_1.conda sha256: 976dadd9858202b6121062a4a5fe2c23e45ed37e700435a4463484aca4252bab md5: 24bb0e8dc548b8856bfc6a76724e6c15 depends: - python - numpy >=1.24.1 - scipy >=1.10.0 - joblib >=1.3.0 - threadpoolctl >=3.2.0 - libcxx >=19 - llvm-openmp >=19.1.7 - python 3.11.* *_cpython - __osx >=11.0 - python_abi 3.11.* *_cp311 - numpy >=1.23,<3 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scikit-learn?source=hash-mapping size: 9358565 timestamp: 1766550842874 - conda: https://prefix.dev/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py313h3b23316_1.conda sha256: 5191a32a082c9b86f84fd5672e61fdd600a41f7ba0d900226348fa5f71fbfaa0 md5: 4434adab69e6300db1e98aff4c3565f3 depends: - python - numpy >=1.24.1 - scipy >=1.10.0 - joblib >=1.3.0 - threadpoolctl >=3.2.0 - llvm-openmp >=19.1.7 - python 3.13.* *_cp313 - __osx >=11.0 - libcxx >=19 - python_abi 3.13.* *_cp313 - numpy >=1.23,<3 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scikit-learn?source=hash-mapping size: 9288788 timestamp: 1766550894420 - conda: https://prefix.dev/conda-forge/win-64/scikit-learn-1.8.0-np2py311hd01f973_1.conda sha256: 5899a0bd83d382025446fa8c1459c57e5cbb15a9e6db9fdcb35e4961717aa916 md5: e05096da659f628aadc0c95ec0c34123 depends: - python - numpy >=1.24.1 - scipy >=1.10.0 - joblib >=1.3.0 - threadpoolctl >=3.2.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - python_abi 3.11.* *_cp311 - numpy >=1.23,<3 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scikit-learn?source=hash-mapping size: 9133816 timestamp: 1765801251916 - conda: https://prefix.dev/conda-forge/win-64/scikit-learn-1.8.0-np2py313h4ce4a18_1.conda sha256: 8b69613ebb401fd80d00316b729950c0a1b0ee9d27c8848adf5f3e7619c4e50c md5: 1a636c8e6f5b92fca019972db0ed348e depends: - python - numpy >=1.24.1 - scipy >=1.10.0 - joblib >=1.3.0 - threadpoolctl >=3.2.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - numpy >=1.23,<3 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scikit-learn?source=hash-mapping size: 9043928 timestamp: 1765801249980 - conda: https://prefix.dev/conda-forge/linux-64/scipy-1.17.0-py311hbe70eeb_1.conda sha256: b9582e96d703b2f2f61efc7394c886aefa5ab44983818bfc4a1894afc099561c md5: f4dda6316cc4718cbcab7009b5d60c41 depends: - __glibc >=2.17,<3.0.a0 - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - libgcc >=14 - libgfortran - libgfortran5 >=14.3.0 - liblapack >=3.9.0,<4.0a0 - libstdcxx >=14 - numpy <2.7 - numpy >=1.23,<3 - numpy >=1.25.2 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scipy?source=compressed-mapping size: 16967163 timestamp: 1768800888207 - conda: https://prefix.dev/conda-forge/linux-64/scipy-1.17.0-py313h4b8bb8b_1.conda sha256: e812ebe8115f8daf005f5788ed8f05a0fdabe47eeb4c30bf0a190f2d1d1da0b6 md5: 2b18fe5b4b2d1611ddf8c2f080a46563 depends: - __glibc >=2.17,<3.0.a0 - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - libgcc >=14 - libgfortran - libgfortran5 >=14.3.0 - liblapack >=3.9.0,<4.0a0 - libstdcxx >=14 - numpy <2.7 - numpy >=1.23,<3 - numpy >=1.25.2 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scipy?source=hash-mapping size: 16857028 timestamp: 1768801011489 - conda: https://prefix.dev/conda-forge/osx-64/scipy-1.17.0-py311h553d447_1.conda sha256: a4e4940478c7e5a9a37fd87f49f6ef48ddf36355b66a67c85e660248b5eaf6d9 md5: 0572c8c33b1938b2e2fddefa5ebb31c5 depends: - __osx >=10.13 - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - libcxx >=19 - libgfortran - libgfortran5 >=14.3.0 - liblapack >=3.9.0,<4.0a0 - numpy <2.7 - numpy >=1.23,<3 - numpy >=1.25.2 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scipy?source=hash-mapping size: 15345091 timestamp: 1768801001271 - conda: https://prefix.dev/conda-forge/osx-64/scipy-1.17.0-py313h2bd7e7a_1.conda sha256: c30ec7d0e2571f6f2ddaddf3eb64e0e2e16e58c0a4f724f2ee2b894e0ce1a8e4 md5: 076afc646e5b800ab4adece0310795db depends: - __osx >=10.13 - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - libcxx >=19 - libgfortran - libgfortran5 >=14.3.0 - liblapack >=3.9.0,<4.0a0 - numpy <2.7 - numpy >=1.23,<3 - numpy >=1.25.2 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scipy?source=hash-mapping size: 15299524 timestamp: 1768800867425 - conda: https://prefix.dev/conda-forge/osx-arm64/scipy-1.17.0-py311he9931d0_1.conda sha256: d9f37c85cbf689be3672c8264eb81585ad8f6041a2fe545ec978f42e5da0202c md5: 9c5c9dbdaf090ba8be3beb34c01495d0 depends: - __osx >=11.0 - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - libcxx >=19 - libgfortran - libgfortran5 >=14.3.0 - liblapack >=3.9.0,<4.0a0 - numpy <2.7 - numpy >=1.23,<3 - numpy >=1.25.2 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scipy?source=compressed-mapping size: 14030449 timestamp: 1768801949072 - conda: https://prefix.dev/conda-forge/osx-arm64/scipy-1.17.0-py313hc753a45_1.conda sha256: 2ea17fc46533e8789881732f42265e32c7ae376344cc3d53683e7b2179d947bb md5: 5b73b1e6d191aac48960c50d65372f19 depends: - __osx >=11.0 - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - libcxx >=19 - libgfortran - libgfortran5 >=14.3.0 - liblapack >=3.9.0,<4.0a0 - numpy <2.7 - numpy >=1.23,<3 - numpy >=1.25.2 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scipy?source=compressed-mapping size: 13888560 timestamp: 1768801587965 - conda: https://prefix.dev/conda-forge/win-64/scipy-1.17.0-py311h9c22a71_1.conda sha256: c6896bbe8cb62b1743b86e4bae8c509233231412bf7ffd92bf0d5036a617dc8e md5: 0d03c857517a5db3c1af5b553a528fac depends: - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - liblapack >=3.9.0,<4.0a0 - numpy <2.7 - numpy >=1.23,<3 - numpy >=1.25.2 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scipy?source=compressed-mapping size: 14988880 timestamp: 1768801728977 - conda: https://prefix.dev/conda-forge/win-64/scipy-1.17.0-py313he51e9a2_1.conda sha256: 9da71fa94c2de66f5d1eb7d926f655efadf8c4e0a6b6e934a45adaeea0905e9b md5: b54fb98c96446df58e04957b6c98520e depends: - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 - liblapack >=3.9.0,<4.0a0 - numpy <2.7 - numpy >=1.23,<3 - numpy >=1.25.2 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/scipy?source=hash-mapping size: 14986564 timestamp: 1768801809920 - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl name: semver version: 3.0.4 sha256: 9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746 requires_python: '>=3.7' - conda: https://prefix.dev/conda-forge/noarch/send2trash-2.1.0-pyh5552912_0.conda sha256: 6b1a863b2a3e106e573a6efce2303963c3adc2764dfdbf08c4a35dbe62604988 md5: 297e2901b530c5d321c563e66a65db99 depends: - __osx - pyobjc-framework-cocoa - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/send2trash?source=hash-mapping size: 22409 timestamp: 1768402460843 - conda: https://prefix.dev/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_0.conda sha256: b64e5cdb66f5d31fcef05b6ed95b8be3e80796528aa8a165428496c0dda3383f md5: 69ba308f1356f39901f5654d82405df3 depends: - __win - pywin32 - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/send2trash?source=hash-mapping size: 22700 timestamp: 1768402455730 - conda: https://prefix.dev/conda-forge/noarch/send2trash-2.1.0-pyha191276_0.conda sha256: b25d573874fe39cb8e4cf6ed0279acb9a94fedce5c5ae885da11566d595035ad md5: 645026465469ecd4989188e1c4e24953 depends: - __linux - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/send2trash?source=hash-mapping size: 23960 timestamp: 1768402421616 - conda: https://prefix.dev/conda-forge/noarch/setuptools-80.10.2-pyh332efcf_0.conda sha256: f5fcb7854d2b7639a5b1aca41dd0f2d5a69a60bbc313e7f192e2dc385ca52f86 md5: 7b446fcbb6779ee479debb4fd7453e6c depends: - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/setuptools?source=compressed-mapping size: 678888 timestamp: 1769601206751 - conda: https://prefix.dev/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda sha256: 2161ac35fc22770b248bab0be2cc3b5bd765f528a9e60e7f3be784fd8d0d605a md5: e2e4d7094d0580ccd62e2a41947444f3 depends: - importlib-metadata - packaging >=20.0 - python >=3.10 - setuptools >=45 - tomli >=1.0.0 - typing-extensions license: MIT license_family: MIT purls: - pkg:pypi/setuptools-scm?source=hash-mapping size: 52539 timestamp: 1760965125925 - conda: https://prefix.dev/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d md5: 3339e3b65d58accf4ca4fb8748ab16b3 depends: - python >=3.9 - python license: MIT license_family: MIT purls: - pkg:pypi/six?source=hash-mapping size: 18455 timestamp: 1753199211006 - conda: https://prefix.dev/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda sha256: 48f3f6a76c34b2cfe80de9ce7f2283ecb55d5ed47367ba91e8bb8104e12b8f11 md5: 98b6c9dc80eb87b2519b97bcf7e578dd depends: - libgcc >=14 - __glibc >=2.17,<3.0.a0 - libstdcxx >=14 - libgcc >=14 license: BSD-3-Clause license_family: BSD purls: [] size: 45829 timestamp: 1762948049098 - conda: https://prefix.dev/conda-forge/osx-64/snappy-1.2.2-h01f5ddf_1.conda sha256: 1525e6d8e2edf32dabfe2a8e2fc8bf2df81c5ef9f0b5374a3d4ccfa672bfd949 md5: 2e993292ec18af5cd480932d448598cf depends: - libcxx >=19 - __osx >=10.13 license: BSD-3-Clause license_family: BSD purls: [] size: 40023 timestamp: 1762948053450 - conda: https://prefix.dev/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda sha256: cb9305ede19584115f43baecdf09a3866bfcd5bcca0d9e527bd76d9a1dbe2d8d md5: fca4a2222994acd7f691e57f94b750c5 depends: - libcxx >=19 - __osx >=11.0 license: BSD-3-Clause license_family: BSD purls: [] size: 38883 timestamp: 1762948066818 - conda: https://prefix.dev/conda-forge/win-64/snappy-1.2.2-h7fa0ca8_1.conda sha256: d2deda1350abf8c05978b73cf7fe9147dd5c7f2f9b312692d1b98e52efad53c3 md5: 3075846de68f942150069d4289aaad63 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 license: BSD-3-Clause license_family: BSD purls: [] size: 67417 timestamp: 1762948090450 - conda: https://prefix.dev/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda sha256: dce518f45e24cd03f401cb0616917773159a210c19d601c5f2d4e0e5879d30ad md5: 03fe290994c5e4ec17293cfb6bdce520 depends: - python >=3.10 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/sniffio?source=compressed-mapping size: 15698 timestamp: 1762941572482 - conda: https://prefix.dev/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_1.conda sha256: d1e3e06b5cf26093047e63c8cc77b70d970411c5cbc0cb1fad461a8a8df599f7 md5: 0401a17ae845fa72c7210e206ec5647d depends: - python >=3.9 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/sortedcontainers?source=hash-mapping size: 28657 timestamp: 1738440459037 - conda: https://prefix.dev/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda sha256: 23b71ecf089967d2900126920e7f9ff18cdcef82dbff3e2f54ffa360243a17ac md5: 18de09b20462742fe093ba39185d9bac depends: - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/soupsieve?source=hash-mapping size: 38187 timestamp: 1769034509657 - conda: . name: sparse version: 0.1.0 build: pyh4616a5c_0 subdir: noarch variants: target_platform: noarch depends: - numba >=0.49 - numpy >=1.17 - python >=3.11 - python * - conda: https://prefix.dev/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda sha256: 570da295d421661af487f1595045760526964f41471021056e993e73089e9c41 md5: b1b505328da7a6b246787df4b5a49fbc depends: - asttokens - executing - pure_eval - python >=3.9 license: MIT license_family: MIT purls: - pkg:pypi/stack-data?source=hash-mapping size: 26988 timestamp: 1733569565672 - conda: https://prefix.dev/conda-forge/noarch/tabulate-0.9.0-pyhcf101f3_3.conda sha256: 795e03d14ce50ae409e86cf2a8bd8441a8c459192f97841449f33d2221066fef md5: de98449f11d48d4b52eefb354e2bfe35 depends: - python >=3.10 - python license: MIT license_family: MIT size: 40319 timestamp: 1765140047040 - conda: https://prefix.dev/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda sha256: abd9a489f059fba85c8ffa1abdaa4d515d6de6a3325238b8e81203b913cf65a9 md5: 0f9817ffbe25f9e69ceba5ea70c52606 depends: - libhwloc >=2.12.2,<2.12.3.0a0 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: APACHE purls: [] size: 155869 timestamp: 1767886839029 - conda: https://prefix.dev/conda-forge/noarch/tblib-3.2.2-pyhcf101f3_0.conda sha256: 6b549360f687ee4d11bf85a6d6a276a30f9333df1857adb0fe785f0f8e9bcd60 md5: f88bb644823094f436792f80fba3207e depends: - python >=3.10 - python license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/tblib?source=hash-mapping size: 19397 timestamp: 1762956379123 - conda: https://prefix.dev/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda sha256: b375e8df0d5710717c31e7c8e93c025c37fa3504aea325c7a55509f64e5d4340 md5: e43ca10d61e55d0a8ec5d8c62474ec9e depends: - __win - pywinpty >=1.1.0 - python >=3.10 - tornado >=6.1.0 - python license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/terminado?source=hash-mapping size: 23665 timestamp: 1766513806974 - conda: https://prefix.dev/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda sha256: 6b6727a13d1ca6a23de5e6686500d0669081a117736a87c8abf444d60c1e40eb md5: 17b43cee5cc84969529d5d0b0309b2cb depends: - __unix - ptyprocess - python >=3.10 - tornado >=6.1.0 - python license: BSD-2-Clause license_family: BSD purls: - pkg:pypi/terminado?source=hash-mapping size: 24749 timestamp: 1766513766867 - conda: https://prefix.dev/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda sha256: 6016672e0e72c4cf23c0cf7b1986283bd86a9c17e8d319212d78d8e9ae42fdfd md5: 9d64911b31d57ca443e9f1e36b04385f depends: - python >=3.9 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/threadpoolctl?source=hash-mapping size: 23869 timestamp: 1741878358548 - conda: https://prefix.dev/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda sha256: 7c803480dbfb8b536b9bf6287fa2aa0a4f970f8c09075694174eb4550a4524cd md5: c0d0b883e97906f7524e2aac94be0e0d depends: - python >=3.10 - webencodings >=0.4 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/tinycss2?source=compressed-mapping size: 30571 timestamp: 1764621508086 - conda: https://prefix.dev/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac md5: cffd3bdd58090148f4cfcd831f4b26ab depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libzlib >=1.3.1,<2.0a0 constrains: - xorg-libx11 >=1.8.12,<2.0a0 license: TCL license_family: BSD purls: [] size: 3301196 timestamp: 1769460227866 - conda: https://prefix.dev/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda sha256: 7f0d9c320288532873e2d8486c331ec6d87919c9028208d3f6ac91dc8f99a67b md5: 6e6efb7463f8cef69dbcb4c2205bf60e depends: - __osx >=10.13 - libzlib >=1.3.1,<2.0a0 license: TCL license_family: BSD purls: [] size: 3282953 timestamp: 1769460532442 - conda: https://prefix.dev/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda sha256: 799cab4b6cde62f91f750149995d149bc9db525ec12595e8a1d91b9317f038b3 md5: a9d86bc62f39b94c4661716624eb21b0 depends: - __osx >=11.0 - libzlib >=1.3.1,<2.0a0 license: TCL license_family: BSD purls: [] size: 3127137 timestamp: 1769460817696 - conda: https://prefix.dev/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda sha256: 0e79810fae28f3b69fe7391b0d43f5474d6bd91d451d5f2bde02f55ae481d5e3 md5: 0481bfd9814bf525bd4b3ee4b51494c4 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: TCL license_family: BSD purls: [] size: 3526350 timestamp: 1769460339384 - conda: https://prefix.dev/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda sha256: 62940c563de45790ba0f076b9f2085a842a65662268b02dd136a8e9b1eaf47a8 md5: 72e780e9aa2d0a3295f59b1874e3768b depends: - python >=3.10 - python license: MIT license_family: MIT purls: - pkg:pypi/tomli?source=compressed-mapping size: 21453 timestamp: 1768146676791 - pypi: https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl name: tomlkit version: 0.13.3 sha256: c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0 requires_python: '>=3.8' - conda: https://prefix.dev/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda sha256: 4e379e1c18befb134247f56021fdf18e112fb35e64dd1691858b0a0f3bea9a45 md5: c07a6153f8306e45794774cf9b13bd32 depends: - python >=3.10 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/toolz?source=hash-mapping size: 53978 timestamp: 1760707830681 - conda: https://prefix.dev/conda-forge/linux-64/tornado-6.5.3-py311h49ec1c0_0.conda sha256: 0d5c53a3ae7531ddf6bc28fb95edded05f1908f3ccffe5ab820f5992b81e5418 md5: a0d8cab7384ccfca582b952d9c8c619a depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/tornado?source=compressed-mapping size: 871254 timestamp: 1765458944370 - conda: https://prefix.dev/conda-forge/linux-64/tornado-6.5.3-py313h07c4f96_0.conda sha256: 6006d4e5a6ff99be052c939e43adee844a38f2dc148f44a7c11aa0011fd3d811 md5: 82da2dcf1ea3e298f2557b50459809e0 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/tornado?source=hash-mapping size: 878109 timestamp: 1765458900582 - conda: https://prefix.dev/conda-forge/osx-64/tornado-6.5.4-py311ha2bb86f_0.conda sha256: a7ef7e9e43e27a4ae6b1c7b523d4beae202eedafaa6c5fd4e116d4437fd5c0da md5: 354f5036a42f0ee629877a63a4ac801e depends: - __osx >=11.0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/tornado?source=hash-mapping size: 872287 timestamp: 1765836899438 - conda: https://prefix.dev/conda-forge/osx-64/tornado-6.5.4-py313h16c19ce_0.conda sha256: 94d25f6ad0a21dd788f4e1dddec24696edb36e651939a4c241444ee1340ac006 md5: d8976bd40232eea804fa55c429774c0d depends: - __osx >=11.0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/tornado?source=hash-mapping size: 878614 timestamp: 1765836723769 - conda: https://prefix.dev/conda-forge/osx-arm64/tornado-6.5.4-py311h9408147_0.conda sha256: b7098eb573af83912e13df4d373feb35854b3e37a7f7cc97f8fc01a03a10b995 md5: df911f6f4b283ce96679e1031a8ff530 depends: - __osx >=11.0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/tornado?source=hash-mapping size: 872651 timestamp: 1765836782876 - conda: https://prefix.dev/conda-forge/osx-arm64/tornado-6.5.4-py313h6535dbc_0.conda sha256: a8130a361b7bc21190836ba8889276cc263fcb09f52bf22efcaed1de98179948 md5: 67a85c1b5c17124eaf9194206afd5159 depends: - __osx >=11.0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/tornado?source=hash-mapping size: 877647 timestamp: 1765836696426 - conda: https://prefix.dev/conda-forge/win-64/tornado-6.5.4-py311h3485c13_0.conda sha256: 9e6f04d593e9ced76a72cfe2ad79cc9bc1ad4b6a2bc68c8eda959c5f1103e0a0 md5: 6e8d1faf5c0c08641c151e0fb79cb4db depends: - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/tornado?source=hash-mapping size: 874166 timestamp: 1765836627577 - conda: https://prefix.dev/conda-forge/win-64/tornado-6.5.4-py313h5ea7bf4_0.conda sha256: 81b131db1bebed88f11a5f9891c0c0a7c6998dfd96cd96f54839f3a0cbebd5a0 md5: 1402782887fafaa117a8d76d2cfa4761 depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/tornado?source=hash-mapping size: 880049 timestamp: 1765836649731 - conda: https://prefix.dev/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda sha256: f39a5620c6e8e9e98357507262a7869de2ae8cc07da8b7f84e517c9fd6c2b959 md5: 019a7385be9af33791c989871317e1ed depends: - python >=3.9 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/traitlets?source=hash-mapping size: 110051 timestamp: 1733367480074 - conda: https://prefix.dev/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c md5: edd329d7d3a4ab45dcf905899a7a6115 depends: - typing_extensions ==4.15.0 pyhcf101f3_0 license: PSF-2.0 license_family: PSF purls: [] size: 91383 timestamp: 1756220668932 - conda: https://prefix.dev/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 md5: 0caa1af407ecff61170c9437a808404d depends: - python >=3.10 - python license: PSF-2.0 license_family: PSF purls: - pkg:pypi/typing-extensions?source=hash-mapping size: 51692 timestamp: 1756220668932 - conda: https://prefix.dev/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda sha256: 3088d5d873411a56bf988eee774559335749aed6f6c28e07bf933256afb9eb6c md5: f6d7aa696c67756a650e91e15e88223c depends: - python >=3.9 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/typing-utils?source=hash-mapping size: 15183 timestamp: 1733331395943 - conda: https://prefix.dev/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c md5: ad659d0a2b3e47e38d829aa8cad2d610 license: LicenseRef-Public-Domain purls: [] size: 119135 timestamp: 1767016325805 - conda: https://prefix.dev/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda sha256: 3005729dce6f3d3f5ec91dfc49fc75a0095f9cd23bab49efb899657297ac91a5 md5: 71b24316859acd00bdb8b38f5e2ce328 constrains: - vc14_runtime >=14.29.30037 - vs2015_runtime >=14.29.30037 license: LicenseRef-MicrosoftWindowsSDK10 purls: [] size: 694692 timestamp: 1756385147981 - conda: https://prefix.dev/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda sha256: e0eb6c8daf892b3056f08416a96d68b0a358b7c46b99c8a50481b22631a4dfc0 md5: e7cb0f5745e4c5035a460248334af7eb depends: - python >=3.9 license: MIT license_family: MIT purls: - pkg:pypi/uri-template?source=hash-mapping size: 23990 timestamp: 1733323714454 - conda: https://prefix.dev/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a md5: 9272daa869e03efe68833e3dc7a02130 depends: - backports.zstd >=1.0.0 - brotli-python >=1.2.0 - h2 >=4,<5 - pysocks >=1.5.6,<2.0,!=1.5.7 - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/urllib3?source=hash-mapping size: 103172 timestamp: 1767817860341 - conda: https://prefix.dev/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda sha256: 9dc40c2610a6e6727d635c62cced5ef30b7b30123f5ef67d6139e23d21744b3a md5: 1e610f2416b6acdd231c5f573d754a0f depends: - vc14_runtime >=14.44.35208 track_features: - vc14 license: BSD-3-Clause license_family: BSD purls: [] size: 19356 timestamp: 1767320221521 - conda: https://prefix.dev/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda sha256: 02732f953292cce179de9b633e74928037fa3741eb5ef91c3f8bae4f761d32a5 md5: 37eb311485d2d8b2c419449582046a42 depends: - ucrt >=10.0.20348.0 - vcomp14 14.44.35208 h818238b_34 constrains: - vs2015_runtime 14.44.35208.* *_34 license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime license_family: Proprietary purls: [] size: 683233 timestamp: 1767320219644 - conda: https://prefix.dev/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda sha256: 878d5d10318b119bd98ed3ed874bd467acbe21996e1d81597a1dbf8030ea0ce6 md5: 242d9f25d2ae60c76b38a5e42858e51d depends: - ucrt >=10.0.20348.0 constrains: - vs2015_runtime 14.44.35208.* *_34 license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime license_family: Proprietary purls: [] size: 115235 timestamp: 1767320173250 - conda: https://prefix.dev/conda-forge/win-64/vs2015_runtime-14.44.35208-h38c0c73_34.conda sha256: 63ff4ec6e5833f768d402f5e95e03497ce211ded5b6f492e660e2bfc726ad24d md5: f276d1de4553e8fca1dfb6988551ebb4 depends: - vc14_runtime >=14.44.35208 license: BSD-3-Clause license_family: BSD purls: [] size: 19347 timestamp: 1767320221943 - conda: https://prefix.dev/conda-forge/linux-64/watchdog-6.0.0-py313h78bf25f_2.conda sha256: 2ac9fa6fe7f771244dda964485617be55e7d3329da1347b22efb911700eea5cc md5: 283321e8f46f8102ee3b5d1c282ff0fa depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - pyyaml >=3.10 license: Apache-2.0 license_family: APACHE size: 144332 timestamp: 1763021754141 - conda: https://prefix.dev/conda-forge/osx-64/watchdog-6.0.0-py313hf050af9_2.conda sha256: 38d3595b560c74635acedc7c0300042d155640f8dccc2ba096cd98f57a217538 md5: ea12d2a212ac4010892006a339e9d35d depends: - __osx >=10.13 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - pyyaml >=3.10 license: Apache-2.0 license_family: APACHE size: 151391 timestamp: 1763022338658 - conda: https://prefix.dev/conda-forge/osx-arm64/watchdog-6.0.0-py313h6535dbc_2.conda sha256: 14357dd29019b4c03813ba2e60abbde70c26bb0bd2b80229bb1dfb7ce8cefc96 md5: 75178475e411be3d70b9725d850d6aba depends: - __osx >=11.0 - python >=3.13,<3.14.0a0 - python >=3.13,<3.14.0a0 *_cp313 - python_abi 3.13.* *_cp313 - pyyaml >=3.10 license: Apache-2.0 license_family: APACHE size: 152560 timestamp: 1763022038634 - conda: https://prefix.dev/conda-forge/win-64/watchdog-6.0.0-py313hfa70ccb_2.conda sha256: fede6e7ed557aa8290973ceda605b29dffec01c8a97ee6bd1e52ad02b897906f md5: ce01d1bdf4558aee247efb613ff77e2a depends: - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - pyyaml >=3.10 license: Apache-2.0 license_family: APACHE size: 169318 timestamp: 1763021892678 - conda: https://prefix.dev/conda-forge/linux-64/wayland-1.24.0-hd6090a7_1.conda sha256: 3aa04ae8e9521d9b56b562376d944c3e52b69f9d2a0667f77b8953464822e125 md5: 035da2e4f5770f036ff704fa17aace24 depends: - __glibc >=2.17,<3.0.a0 - libexpat >=2.7.1,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - libstdcxx >=14 license: MIT license_family: MIT purls: [] size: 329779 timestamp: 1761174273487 - conda: https://prefix.dev/conda-forge/noarch/wcwidth-0.5.2-pyhd8ed1ab_0.conda sha256: 8cd3605c84960bbd7626f80fdd19c46d44564cfdf87c12e5c3d71f2ea01adfbb md5: 76f0a1179bd0324c03a5d7032b7b73b9 depends: - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/wcwidth?source=hash-mapping size: 69057 timestamp: 1769769550636 - conda: https://prefix.dev/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda sha256: 21f6c8a20fe050d09bfda3fb0a9c3493936ce7d6e1b3b5f8b01319ee46d6c6f6 md5: 6639b6b0d8b5a284f027a2003669aa65 depends: - python >=3.10 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/webcolors?source=hash-mapping size: 18987 timestamp: 1761899393153 - conda: https://prefix.dev/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda sha256: 19ff205e138bb056a46f9e3839935a2e60bd1cf01c8241a5e172a422fed4f9c6 md5: 2841eb5bfc75ce15e9a0054b98dcd64d depends: - python >=3.9 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/webencodings?source=hash-mapping size: 15496 timestamp: 1733236131358 - conda: https://prefix.dev/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda sha256: 42a2b61e393e61cdf75ced1f5f324a64af25f347d16c60b14117393a98656397 md5: 2f1ed718fcd829c184a6d4f0f2e07409 depends: - python >=3.10 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/websocket-client?source=hash-mapping size: 61391 timestamp: 1759928175142 - conda: https://prefix.dev/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda sha256: d6cf2f0ebd5e09120c28ecba450556ce553752652d91795442f0e70f837126ae md5: bdbd7385b4a67025ac2dba4ef8cb6a8f depends: - packaging >=24.0 - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/wheel?source=hash-mapping size: 31858 timestamp: 1769139207397 - conda: https://prefix.dev/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda sha256: 93807369ab91f230cf9e6e2a237eaa812492fe00face5b38068735858fba954f md5: 46e441ba871f524e2b067929da3051c2 depends: - __win - python >=3.9 license: LicenseRef-Public-Domain purls: - pkg:pypi/win-inet-pton?source=hash-mapping size: 9555 timestamp: 1733130678956 - conda: https://prefix.dev/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 sha256: 9df10c5b607dd30e05ba08cbd940009305c75db242476f4e845ea06008b0a283 md5: 1cee351bf20b830d991dbe0bc8cd7dfe license: MIT license_family: MIT purls: [] size: 1176306 - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda sha256: ad8cab7e07e2af268449c2ce855cbb51f43f4664936eff679b1f3862e6e4b01d md5: fdc27cb255a7a2cc73b7919a968b48f0 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - libxcb >=1.17.0,<2.0a0 license: MIT license_family: MIT purls: [] size: 20772 timestamp: 1750436796633 - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-cursor-0.1.6-hb03c661_0.conda sha256: c2be9cae786fdb2df7c2387d2db31b285cf90ab3bfabda8fa75a596c3d20fc67 md5: 4d1fc190b99912ed557a8236e958c559 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libxcb >=1.13 - libxcb >=1.17.0,<2.0a0 - xcb-util-image >=0.4.0,<0.5.0a0 - xcb-util-renderutil >=0.3.10,<0.4.0a0 license: MIT license_family: MIT purls: [] size: 20829 timestamp: 1763366954390 - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-image-0.4.0-hb711507_2.conda sha256: 94b12ff8b30260d9de4fd7a28cca12e028e572cbc504fd42aa2646ec4a5bded7 md5: a0901183f08b6c7107aab109733a3c91 depends: - libgcc-ng >=12 - libxcb >=1.16,<2.0.0a0 - xcb-util >=0.4.1,<0.5.0a0 license: MIT license_family: MIT purls: [] size: 24551 timestamp: 1718880534789 - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-keysyms-0.4.1-hb711507_0.conda sha256: 546e3ee01e95a4c884b6401284bb22da449a2f4daf508d038fdfa0712fe4cc69 md5: ad748ccca349aec3e91743e08b5e2b50 depends: - libgcc-ng >=12 - libxcb >=1.16,<2.0.0a0 license: MIT license_family: MIT purls: [] size: 14314 timestamp: 1718846569232 - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-renderutil-0.3.10-hb711507_0.conda sha256: 2d401dadc43855971ce008344a4b5bd804aca9487d8ebd83328592217daca3df md5: 0e0cbe0564d03a99afd5fd7b362feecd depends: - libgcc-ng >=12 - libxcb >=1.16,<2.0.0a0 license: MIT license_family: MIT purls: [] size: 16978 timestamp: 1718848865819 - conda: https://prefix.dev/conda-forge/linux-64/xcb-util-wm-0.4.2-hb711507_0.conda sha256: 31d44f297ad87a1e6510895740325a635dd204556aa7e079194a0034cdd7e66a md5: 608e0ef8256b81d04456e8d211eee3e8 depends: - libgcc-ng >=12 - libxcb >=1.16,<2.0.0a0 license: MIT license_family: MIT purls: [] size: 51689 timestamp: 1718844051451 - conda: https://prefix.dev/conda-forge/linux-64/xkeyboard-config-2.46-hb03c661_0.conda sha256: aa03b49f402959751ccc6e21932d69db96a65a67343765672f7862332aa32834 md5: 71ae752a748962161b4740eaff510258 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - xorg-libx11 >=1.8.12,<2.0a0 license: MIT license_family: MIT purls: [] size: 396975 timestamp: 1759543819846 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b md5: fb901ff28063514abb6046c9ec2c4a45 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 license: MIT license_family: MIT purls: [] size: 58628 timestamp: 1734227592886 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda sha256: 277841c43a39f738927145930ff963c5ce4c4dacf66637a3d95d802a64173250 md5: 1c74ff8c35dcadf952a16f752ca5aa49 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - libuuid >=2.38.1,<3.0a0 - xorg-libice >=1.1.2,<2.0a0 license: MIT license_family: MIT purls: [] size: 27590 timestamp: 1741896361728 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libx11-1.8.12-h4f16b4b_0.conda sha256: 51909270b1a6c5474ed3978628b341b4d4472cd22610e5f22b506855a5e20f67 md5: db038ce880f100acc74dba10302b5630 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - libxcb >=1.17.0,<2.0a0 license: MIT license_family: MIT purls: [] size: 835896 timestamp: 1741901112627 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b md5: b2895afaf55bf96a8c8282a2e47a5de0 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 15321 timestamp: 1762976464266 - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxau-1.0.12-h8616949_1.conda sha256: 928f28bd278c7da674b57d71b2e7f4ac4e7c7ce56b0bf0f60d6a074366a2e76d md5: 47f1b8b4a76ebd0cd22bd7153e54a4dc depends: - __osx >=10.13 license: MIT license_family: MIT purls: [] size: 13810 timestamp: 1762977180568 - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda sha256: adae11db0f66f86156569415ed79cda75b2dbf4bea48d1577831db701438164f md5: 78b548eed8227a689f93775d5d23ae09 depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 14105 timestamp: 1762976976084 - conda: https://prefix.dev/conda-forge/win-64/xorg-libxau-1.0.12-hba3369d_1.conda sha256: 156a583fa43609507146de1c4926172286d92458c307bb90871579601f6bc568 md5: 8436cab9a76015dfe7208d3c9f97c156 depends: - libgcc >=14 - libwinpthread >=12.0.0.r4.gg4f2fc60ca - ucrt >=10.0.20348.0 license: MIT license_family: MIT purls: [] size: 109246 timestamp: 1762977105140 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxcomposite-0.4.6-hb9d3cd8_2.conda sha256: 753f73e990c33366a91fd42cc17a3d19bb9444b9ca5ff983605fa9e953baf57f md5: d3c295b50f092ab525ffe3c2aa4b7413 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - xorg-libx11 >=1.8.10,<2.0a0 - xorg-libxfixes >=6.0.1,<7.0a0 license: MIT license_family: MIT purls: [] size: 13603 timestamp: 1727884600744 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxcursor-1.2.3-hb9d3cd8_0.conda sha256: 832f538ade441b1eee863c8c91af9e69b356cd3e9e1350fff4fe36cc573fc91a md5: 2ccd714aa2242315acaf0a67faea780b depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - xorg-libx11 >=1.8.10,<2.0a0 - xorg-libxfixes >=6.0.1,<7.0a0 - xorg-libxrender >=0.9.11,<0.10.0a0 license: MIT license_family: MIT purls: [] size: 32533 timestamp: 1730908305254 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxdamage-1.1.6-hb9d3cd8_0.conda sha256: 43b9772fd6582bf401846642c4635c47a9b0e36ca08116b3ec3df36ab96e0ec0 md5: b5fcc7172d22516e1f965490e65e33a4 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - xorg-libx11 >=1.8.10,<2.0a0 - xorg-libxext >=1.3.6,<2.0a0 - xorg-libxfixes >=6.0.1,<7.0a0 license: MIT license_family: MIT purls: [] size: 13217 timestamp: 1727891438799 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 md5: 1dafce8548e38671bea82e3f5c6ce22f depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: MIT license_family: MIT purls: [] size: 20591 timestamp: 1762976546182 - conda: https://prefix.dev/conda-forge/osx-64/xorg-libxdmcp-1.1.5-h8616949_1.conda sha256: b7b291cc5fd4e1223058542fca46f462221027779920dd433d68b98e858a4afc md5: 435446d9d7db8e094d2c989766cfb146 depends: - __osx >=10.13 license: MIT license_family: MIT purls: [] size: 19067 timestamp: 1762977101974 - conda: https://prefix.dev/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-hc919400_1.conda sha256: f7fa0de519d8da589995a1fe78ef74556bb8bc4172079ae3a8d20c3c81354906 md5: 9d1299ace1924aa8f4e0bc8e71dd0cf7 depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 19156 timestamp: 1762977035194 - conda: https://prefix.dev/conda-forge/win-64/xorg-libxdmcp-1.1.5-hba3369d_1.conda sha256: 366b8ae202c3b48958f0b8784bbfdc37243d3ee1b1cd4b8e76c10abe41fa258b md5: a7c03e38aa9c0e84d41881b9236eacfb depends: - libgcc >=14 - libwinpthread >=12.0.0.r4.gg4f2fc60ca - ucrt >=10.0.20348.0 license: MIT license_family: MIT purls: [] size: 70691 timestamp: 1762977015220 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda sha256: 79c60fc6acfd3d713d6340d3b4e296836a0f8c51602327b32794625826bd052f md5: 34e54f03dfea3e7a2dcf1453a85f1085 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - xorg-libx11 >=1.8.12,<2.0a0 license: MIT license_family: MIT purls: [] size: 50326 timestamp: 1769445253162 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda sha256: 83c4c99d60b8784a611351220452a0a85b080668188dce5dfa394b723d7b64f4 md5: ba231da7fccf9ea1e768caf5c7099b84 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - xorg-libx11 >=1.8.12,<2.0a0 license: MIT license_family: MIT purls: [] size: 20071 timestamp: 1759282564045 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda sha256: 1a724b47d98d7880f26da40e45f01728e7638e6ec69f35a3e11f92acd05f9e7a md5: 17dcc85db3c7886650b8908b183d6876 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - xorg-libx11 >=1.8.10,<2.0a0 - xorg-libxext >=1.3.6,<2.0a0 - xorg-libxfixes >=6.0.1,<7.0a0 license: MIT license_family: MIT purls: [] size: 47179 timestamp: 1727799254088 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda sha256: 80ed047a5cb30632c3dc5804c7716131d767089f65877813d4ae855ee5c9d343 md5: e192019153591938acf7322b6459d36e depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - xorg-libx11 >=1.8.12,<2.0a0 - xorg-libxext >=1.3.6,<2.0a0 - xorg-libxrender >=0.9.12,<0.10.0a0 license: MIT license_family: MIT purls: [] size: 30456 timestamp: 1769445263457 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda sha256: 044c7b3153c224c6cedd4484dd91b389d2d7fd9c776ad0f4a34f099b3389f4a1 md5: 96d57aba173e878a2089d5638016dc5e depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - xorg-libx11 >=1.8.10,<2.0a0 license: MIT license_family: MIT purls: [] size: 33005 timestamp: 1734229037766 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda sha256: 752fdaac5d58ed863bbf685bb6f98092fe1a488ea8ebb7ed7b606ccfce08637a md5: 7bbe9a0cc0df0ac5f5a8ad6d6a11af2f depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - xorg-libx11 >=1.8.10,<2.0a0 - xorg-libxext >=1.3.6,<2.0a0 - xorg-libxi >=1.7.10,<2.0a0 license: MIT license_family: MIT purls: [] size: 32808 timestamp: 1727964811275 - conda: https://prefix.dev/conda-forge/linux-64/xorg-libxxf86vm-1.1.7-hb03c661_0.conda sha256: 64db17baaf36fa03ed8fae105e2e671a7383e22df4077486646f7dbf12842c9f md5: 665d152b9c6e78da404086088077c844 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - xorg-libx11 >=1.8.12,<2.0a0 - xorg-libxext >=1.3.6,<2.0a0 license: MIT license_family: MIT purls: [] size: 18701 timestamp: 1769434732453 - conda: https://prefix.dev/conda-forge/noarch/xyzservices-2025.11.0-pyhd8ed1ab_0.conda sha256: b194a1fbc38f29c563b102ece9d006f7a165bf9074cdfe50563d3bce8cae9f84 md5: 16933322051fa260285f1a44aae91dd6 depends: - python >=3.8 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/xyzservices?source=hash-mapping size: 51128 timestamp: 1763813786075 - conda: https://prefix.dev/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad md5: a77f85f77be52ff59391544bfe73390a depends: - libgcc >=14 - __glibc >=2.17,<3.0.a0 license: MIT license_family: MIT purls: [] size: 85189 timestamp: 1753484064210 - conda: https://prefix.dev/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda sha256: a335161bfa57b64e6794c3c354e7d49449b28b8d8a7c4ed02bf04c3f009953f9 md5: a645bb90997d3fc2aea0adf6517059bd depends: - __osx >=10.13 license: MIT license_family: MIT purls: [] size: 79419 timestamp: 1753484072608 - conda: https://prefix.dev/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda sha256: b03433b13d89f5567e828ea9f1a7d5c5d697bf374c28a4168d71e9464f5dafac md5: 78a0fe9e9c50d2c381e8ee47e3ea437d depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] size: 83386 timestamp: 1753484079473 - conda: https://prefix.dev/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda sha256: 80ee68c1e7683a35295232ea79bcc87279d31ffeda04a1665efdb43cbd50a309 md5: 433699cba6602098ae8957a323da2664 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 license: MIT license_family: MIT purls: [] size: 63944 timestamp: 1753484092156 - conda: https://prefix.dev/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda sha256: 47cfe31255b91b4a6fa0e9dbaf26baa60ac97e033402dbc8b90ba5fee5ffe184 md5: 8035e5b54c08429354d5d64027041cad depends: - libstdcxx >=14 - libgcc >=14 - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libsodium >=1.0.20,<1.0.21.0a0 - krb5 >=1.21.3,<1.22.0a0 license: MPL-2.0 license_family: MOZILLA purls: [] size: 310648 timestamp: 1757370847287 - conda: https://prefix.dev/conda-forge/osx-64/zeromq-4.3.5-h6c33b1e_9.conda sha256: 30aa5a2e9c7b8dbf6659a2ccd8b74a9994cdf6f87591fcc592970daa6e7d3f3c md5: d940d809c42fbf85b05814c3290660f5 depends: - __osx >=10.13 - libcxx >=19 - libsodium >=1.0.20,<1.0.21.0a0 - krb5 >=1.21.3,<1.22.0a0 license: MPL-2.0 license_family: MOZILLA purls: [] size: 259628 timestamp: 1757371000392 - conda: https://prefix.dev/conda-forge/osx-arm64/zeromq-4.3.5-h888dc83_9.conda sha256: b6f9c130646e5971f6cad708e1eee278f5c7eea3ca97ec2fdd36e7abb764a7b8 md5: 26f39dfe38a2a65437c29d69906a0f68 depends: - __osx >=11.0 - libcxx >=19 - libsodium >=1.0.20,<1.0.21.0a0 - krb5 >=1.21.3,<1.22.0a0 license: MPL-2.0 license_family: MOZILLA purls: [] size: 244772 timestamp: 1757371008525 - conda: https://prefix.dev/conda-forge/win-64/zeromq-4.3.5-h5bddc39_9.conda sha256: 690cf749692c8ea556646d1a47b5824ad41b2f6dfd949e4cdb6c44a352fcb1aa md5: a6c8f8ee856f7c3c1576e14b86cd8038 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - libsodium >=1.0.20,<1.0.21.0a0 - krb5 >=1.21.3,<1.22.0a0 license: MPL-2.0 license_family: MOZILLA purls: [] size: 265212 timestamp: 1757370864284 - conda: https://prefix.dev/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda sha256: 5488542dceeb9f2874e726646548ecc5608060934d6f9ceaa7c6a48c61f9cc8d md5: e52c2ef711ccf31bb7f70ca87d144b9e depends: - python >=3.9 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/zict?source=hash-mapping size: 36341 timestamp: 1733261642963 - conda: https://prefix.dev/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae md5: 30cd29cb87d819caead4d55184c1d115 depends: - python >=3.10 - python license: MIT license_family: MIT purls: - pkg:pypi/zipp?source=hash-mapping size: 24194 timestamp: 1764460141901 - conda: https://prefix.dev/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda sha256: 5d7c0e5f0005f74112a34a7425179f4eb6e73c92f5d109e6af4ddeca407c92ab md5: c9f075ab2f33b3bbee9e62d4ad0a6cd8 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - libzlib 1.3.1 hb9d3cd8_2 license: Zlib license_family: Other purls: [] size: 92286 timestamp: 1727963153079 - conda: https://prefix.dev/conda-forge/osx-64/zlib-1.3.1-hd23fc13_2.conda sha256: 219edbdfe7f073564375819732cbf7cc0d7c7c18d3f546a09c2dfaf26e4d69f3 md5: c989e0295dcbdc08106fe5d9e935f0b9 depends: - __osx >=10.13 - libzlib 1.3.1 hd23fc13_2 license: Zlib license_family: Other purls: [] size: 88544 timestamp: 1727963189976 - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda sha256: 58f8860756680a4831c1bf4f294e2354d187f2e999791d53b1941834c4b37430 md5: e3170d898ca6cb48f1bb567afb92f775 depends: - __osx >=11.0 - libzlib 1.3.1 h8359307_2 license: Zlib license_family: Other purls: [] size: 77606 timestamp: 1727963209370 - conda: https://prefix.dev/conda-forge/linux-64/zlib-ng-2.3.2-hceb46e0_1.conda sha256: f2b6a175677701a0b6ce556b3bd362dc94a4e36ffcd10e3860e52ca036b4ad96 md5: 40feea2979654ed579f1cda7c63ccb94 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 license: Zlib license_family: Other purls: [] size: 122303 timestamp: 1766076745735 - conda: https://prefix.dev/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda sha256: ea4e50c465d70236408cb0bfe0115609fd14db1adcd8bd30d8918e0291f8a75f md5: 2aadb0d17215603a82a2a6b0afd9a4cb depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libstdcxx >=14 license: Zlib license_family: Other purls: [] size: 122618 timestamp: 1770167931827 - conda: https://prefix.dev/conda-forge/osx-64/zlib-ng-2.3.2-h8bce59a_1.conda sha256: 945725769bc668435af1c23733c3c1dba01eb115ad3bad5393c9df2e23de6cfc md5: cdd69480d52f2b871fad1a91324d9942 depends: - __osx >=10.13 - libcxx >=19 license: Zlib license_family: Other purls: [] size: 120585 timestamp: 1766077108928 - conda: https://prefix.dev/conda-forge/osx-64/zlib-ng-2.3.3-h8bce59a_1.conda sha256: 4a1beb656761c7d8c9a53474bfd3932c30d82af5d93a32b8ef626c01c059d981 md5: b3ecb6480fd46194e3f7dd0ff4445dff depends: - __osx >=10.13 - libcxx >=19 license: Zlib license_family: Other purls: [] size: 120464 timestamp: 1770168263684 - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-ng-2.3.2-hed4e4f5_1.conda sha256: ab481487381a6a6213d667e883252e52b8ca867b3b466c31a058126f964efffe md5: 75f39a44c08cb5dc4ea847698de34ba3 depends: - __osx >=11.0 - libcxx >=19 license: Zlib license_family: Other purls: [] size: 94882 timestamp: 1766076931977 - conda: https://prefix.dev/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda sha256: a339606a6b224bb230ff3d711e801934f3b3844271df9720165e0353716580d4 md5: d99c2a23a31b0172e90f456f580b695e depends: - __osx >=11.0 - libcxx >=19 license: Zlib license_family: Other purls: [] size: 94375 timestamp: 1770168363685 - conda: https://prefix.dev/conda-forge/win-64/zlib-ng-2.3.2-h0261ad2_1.conda sha256: e058e925bed8d9e5227cecc098e02992813046fd89206194435e975a9f6eff56 md5: bc2fba648e1e784c549e20bbe1a8af40 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Zlib license_family: Other purls: [] size: 123890 timestamp: 1766076739436 - conda: https://prefix.dev/conda-forge/win-64/zlib-ng-2.3.3-h0261ad2_1.conda sha256: 71332532332d13b5dbe57074ddcf82ae711bdc132affa5a2982a29ffa06dc234 md5: 46a21c0a4e65f1a135251fc7c8663f83 depends: - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: Zlib license_family: Other purls: [] size: 124542 timestamp: 1770167984883 - conda: https://prefix.dev/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 depends: - __glibc >=2.17,<3.0.a0 - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 601375 timestamp: 1764777111296 - conda: https://prefix.dev/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda sha256: 47101a4055a70a4876ffc87b750ab2287b67eca793f21c8224be5e1ee6394d3f md5: 727109b184d680772e3122f40136d5ca depends: - __osx >=10.13 - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 528148 timestamp: 1764777156963 - conda: https://prefix.dev/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9 md5: ab136e4c34e97f34fb621d2592a393d8 depends: - __osx >=11.0 - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 433413 timestamp: 1764777166076 - conda: https://prefix.dev/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda sha256: 368d8628424966fd8f9c8018326a9c779e06913dd39e646cf331226acc90e5b2 md5: 053b84beec00b71ea8ff7a4f84b55207 depends: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] size: 388453 timestamp: 1764777142545 sparse-0.18.0/pixi.toml000066400000000000000000000135711514474157100147630ustar00rootroot00000000000000[workspace] authors = ["Hameer Abbasi <2190658+hameerabbasi@users.noreply.github.com>"] channels = ["https://prefix.dev/conda-forge"] name = "sparse" platforms = ["osx-arm64", "osx-64", "linux-64", "win-64"] preview = ["pixi-build"] [environments] test = ["test", "extra"] doc = ["doc", "extra"] mlir = ["test", "mlir"] finch = ["test", "finch"] matrepr = ["matrepr"] notebooks = ["extra", "mlir", "finch", "test", "notebooks"] examples = ["extra", "finch", "examples"] xp-tests = ["test", "xp-tests", "finch"] mindeps = ["test", "extra", "mindeps", "numba-boundscheck", "finch", "mlir"] # sparse package definition # [package] version = "0.1.0" # TODO: fix this [package.build.backend] name = "pixi-build-python" version = "*" [package.host-dependencies] python = ">=3.11,<3.14" setuptools = "*" setuptools-scm = "*" [package.run-dependencies] numba = ">=0.49" numpy = ">=1.17" # default feature definition # [dependencies] sparse.path = "." [dev] # pulls in host and run dependencies sparse.path = "." # non-default feature definitions # # extra [feature.extra.dependencies] dask = ">=2024" scipy = ">=0.19" scikit-learn = "*" # doc [feature.doc.dependencies] mkdocs-material = "*" mkdocstrings-python = "*" mkdocs-gen-files = "*" mkdocs-literate-nav = "*" mkdocs-section-index = "*" mkdocs-jupyter = "*" # test [feature.test.dependencies] pytest = ">=3.5" pytest-cov = "*" pytest-xdist = "*" pytest-codspeed = "*" [feature.test.tasks.test] cmd = "pytest -n auto -vvv" default-environment = "test" [feature.test.tasks.test-numba] cmd = "pytest --pyargs sparse --doctest-modules --cov-report=xml:coverage_Numba.xml -n auto -vvv" default-environment = "test" [feature.test.tasks.test-all] depends-on = ["test-numba", "test-finch", "test-mlir", "test-examples", "test-notebooks", "xp-tests"] # xp-tests [feature.xp-tests.dependencies] pytest-json-report = "*" hypothesis = "*" ndindex = "*" [feature.xp-tests.tasks.clean-xp-tests] cmd = "rm -rf array-api-tests" [feature.xp-tests.tasks.clone-xp-tests] cmd = "git clone https://github.com/data-apis/array-api-tests.git" depends-on = ["clean-xp-tests"] [feature.xp-tests.tasks.checkout-xp-tests] cmd = [ "git", "reset", "--hard", "$(cat ../xp-tests/array-api-tests-rev.txt)", "&&", "git", "submodule", "update", "--init", ] cwd = "array-api-tests" depends-on = ["clone-xp-tests"] [feature.xp-tests.tasks._xp-tests] cmd = [ "pytest", "-v", "--max-examples=2", "--derandomize", "--disable-deadline", "--disable-warnings", "-o xfail_strict=True", "-nauto", "--xfails-file", "../xp-tests/{{ SPARSE_BACKEND }}-array-api-xfails.txt", "--skips-file", "../xp-tests/{{ SPARSE_BACKEND }}-array-api-skips.txt", "array_api_tests/", ] args = [{ arg = "SPARSE_BACKEND", default = "Numba" }] env.SPARSE_BACKEND = "Numba" # TODO: set to arg env.ARRAY_API_TESTS_MODULE = "sparse" cwd = "array-api-tests" depends-on = ["checkout-xp-tests"] [feature.xp-tests.tasks.xp-tests-numba] depends-on = [{ task = "_xp-tests", args = [{ "SPARSE_BACKEND" = "Numba" }] }] [feature.xp-tests.tasks.xp-tests-finch] depends-on = [ "_precompile_finch", "checkout-xp-tests", # { task = "_xp-tests", args = [{"SPARSE_BACKEND" = "Finch" }]}, ] # TODO: depend on `_xp-tests` once it can correctly set SPARSE_BACKEND cmd = [ "pytest", "-v", "--max-examples=2", "--derandomize", "--disable-deadline", "--disable-warnings", "-o xfail_strict=True", "-nauto", "--xfails-file", "../xp-tests/Finch-array-api-xfails.txt", "--skips-file", "../xp-tests/Finch-array-api-skips.txt", "array_api_tests/", ] env.ARRAY_API_TESTS_MODULE = "sparse" env.SPARSE_BACKEND = "Finch" cwd = "array-api-tests" [feature.xp-tests.tasks.xp-tests] depends-on = ["xp-tests-numba", "xp-tests-finch"] # notebooks [feature.notebooks.dependencies] ipykernel = "*" nbmake = "*" matplotlib = "*" networkx = "*" jupyterlab = "*" [feature.notebooks.tasks.test-notebooks-ci] cmd = "pytest -n 4 --nbmake --nbmake-timeout=600 ./examples/*.ipynb" env.CI_MODE = "1" [feature.notebooks.tasks.test-notebooks] cmd = "pytest -n 4 --nbmake --nbmake-timeout=600 ./examples/*.ipynb" # examples [feature.examples.dependencies] networkx = "*" graphblas-algorithms = "*" [feature.examples.tasks.test-examples-ci] cmd = "scripts/test_examples.sh" env.CI_MODE = "1" [feature.examples.tasks.test-examples] cmd = "scripts/test_examples.sh" # finch [feature.finch.dependencies] python = ">=3.10" juliaup = ">=1.17.10" scipy = ">=1.13" [feature.finch.pypi-dependencies] finch-tensor = ">=0.2.13" [feature.finch.activation.env] SPARSE_BACKEND = "Finch" [feature.finch.target.osx-arm64.activation.env] PYTHONFAULTHANDLER = "${HOME}/faulthandler.log" [feature.finch.tasks._precompile_finch] cmd = "python -c 'import finch'" default-environment = "finch" [feature.finch.tasks.test-finch] cmd = "pytest --pyargs sparse/tests --cov-report=xml:coverage_Finch.xml -n auto -vvv" depends-on = ["_precompile_finch"] default-environment = "finch" # mlir [feature.mlir.dependencies] scipy = ">=0.19" pyyaml = "*" [feature.mlir.pypi-dependencies] finch-mlir = ">=0.0.2" [feature.mlir.activation.env] SPARSE_BACKEND = "MLIR" [feature.mlir.tasks.test-mlir] cmd = "pytest --pyargs sparse/mlir_backend --cov-report=xml:coverage_MLIR.xml -n auto -vvv" default-environment = "mlir" # matrepr [feature.matrepr.dependencies] matrepr = "*" # mindeps [feature.mindeps.dependencies] python = "3.11.*" numpy = "1.*" [feature.mindeps.tasks.test-numba-mindeps] cmd = "pytest --pyargs sparse --cov-report=xml:coverage_Numba.xml -n auto -vvv" env.SPARSE_BACKEND = "Numba" [feature.mindeps.tasks.test-finch-mindeps] cmd = "pytest --pyargs sparse/tests --cov-report=xml:coverage_Finch.xml -n auto -vvv" env.SPARSE_BACKEND = "Finch" [feature.mindeps.tasks.test-mlir-mindeps] cmd = "pytest --pyargs sparse/mlir_backend --cov-report=xml:coverage_MLIR.xml -n auto -vvv" env.SPARSE_BACKEND = "MLIR" [feature.numba-boundscheck.activation.env] NUMBA_BOUNDSCHECK = "1" sparse-0.18.0/pyproject.toml000066400000000000000000000053621514474157100160300ustar00rootroot00000000000000[build-system] requires = ["setuptools>=64", "setuptools_scm>=8"] build-backend = "setuptools.build_meta" [project] name = "sparse" dynamic = ["version"] description = "Sparse n-dimensional arrays for the PyData ecosystem" readme = "README.md" dependencies = ["numpy>=1.17", "numba>=0.49"] maintainers = [{ name = "Hameer Abbasi", email = "hameerabbasi@yahoo.com" }] requires-python = ">=3.11" license = { file = "LICENSE" } keywords = ["sparse", "numpy", "scipy", "dask"] classifiers = [ "Development Status :: 2 - Pre-Alpha", "Operating System :: OS Independent", "License :: OSI Approved :: BSD License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3 :: Only", "Intended Audience :: Developers", "Intended Audience :: Science/Research", ] [project.optional-dependencies] docs = [ "mkdocs-material", "mkdocstrings[python]", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-section-index", "mkdocs-jupyter", "sparse[extras]", ] extras = [ "dask[array]", "sparse[finch]", "scipy", "scikit-learn", "networkx", ] tests = [ "sparse[extras]", "pytest>=3.5", "pytest-cov", "pytest-xdist", "pre-commit", "pytest-codspeed", ] tox = ["sparse[tests]", "tox"] notebooks = ["sparse[tests]", "nbmake", "matplotlib"] all = ["sparse[docs,tox,notebooks,mlir]", "matrepr"] finch = ["finch-tensor>=0.2.13"] mlir = ["finch-mlir>=0.0.2"] [project.urls] Documentation = "https://sparse.pydata.org/" Source = "https://github.com/pydata/sparse/" Repository = "https://github.com/pydata/sparse.git" "Issue Tracker" = "https://github.com/pydata/sparse/issues" Discussions = "https://github.com/pydata/sparse/discussions" [project.entry-points.numba_extensions] init = "sparse.numba_backend._numba_extension:_init_extension" [tool.setuptools.packages.find] where = ["."] include = ["sparse", "sparse.*"] [tool.setuptools_scm] version_file = "sparse/_version.py" [tool.ruff] exclude = ["sparse/_version.py"] line-length = 120 [tool.ruff.lint] select = ["F", "E", "W", "I", "B", "UP", "YTT", "BLE", "C4", "T10", "ISC", "ICN", "PIE", "PYI", "RSE", "RET", "SIM", "PGH", "FLY", "NPY", "PERF"] [tool.ruff.lint.isort.sections] numpy = ["numpy", "numpy.*", "scipy", "scipy.*"] [tool.ruff.format] quote-style = "double" docstring-code-format = true [tool.ruff.lint.isort] section-order = [ "future", "standard-library", "first-party", "third-party", "numpy", "local-folder", ] [tool.jupytext.formats] "docs/examples_ipynb/" = "ipynb" "docs/examples/" = "py:light" sparse-0.18.0/pytest.ini000066400000000000000000000003461514474157100151420ustar00rootroot00000000000000[pytest] addopts = --cov-report term-missing --cov-report html --cov-report=term:skip-covered --cov sparse --cov-config .coveragerc filterwarnings = ignore::PendingDeprecationWarning testpaths = sparse junit_family=xunit2 sparse-0.18.0/release-procedure.md000066400000000000000000000022361514474157100170410ustar00rootroot00000000000000* Tag commit ```bash git tag -a x.x.x -m 'Version x.x.x' ``` * Push to github ```bash git push pydata main --tags ``` When you open the PR on GitHub, make sure the title of the PR starts with "release". * Upload to PyPI ```bash git clean -xfd # remove all files in directory not in repository python -m build --wheel --sdist # make packages twine upload dist/* # upload packages ``` * Update the release drafter: Go to https://github.com/pydata/sparse Under the โ€œRelease" section there are two links: One is the latest release (it has a tag). The second one is +. Click on the second one so you can see the release drafter. Edit the draft by clicking the "pencil" figure. Make sure you have the correct tags. If they are not, you can create one. If the markdown page looks correct, click on โ€œPublish releaseโ€.
* Enable the newly-pushed tag for documentation: https://readthedocs.org/projects/sparse-nd/versions/ * Wait for conda-forge to realise that the build is too old and make a PR. * Edit and merge that PR. * Announce the release on: * numpy-discussion@python.org * python-announce-list@python.org sparse-0.18.0/scripts/000077500000000000000000000000001514474157100145755ustar00rootroot00000000000000sparse-0.18.0/scripts/gen_ref_pages.py000066400000000000000000000011071514474157100177320ustar00rootroot00000000000000"""Generate the code reference pages.""" from pathlib import Path import sparse import mkdocs_gen_files nav = mkdocs_gen_files.Nav() root = Path(__file__).parent.parent for item in dir(sparse): if item.startswith("_") or not getattr(getattr(sparse, item), "__module__", "").startswith("sparse"): continue full_doc_path = Path("api/" + item + ".md") with mkdocs_gen_files.open(Path("api", f"{item}.md"), "w") as fd: print(f"# {item}", file=fd) print("::: " + f"sparse.{item}", file=fd) mkdocs_gen_files.set_edit_path(full_doc_path, root) sparse-0.18.0/scripts/test_examples.sh000077500000000000000000000001641514474157100200120ustar00rootroot00000000000000#!/usr/bin/env bash set -euxo pipefail for example in $(find ./examples/ -iname '*.py'); do python $example done sparse-0.18.0/setup.cfg000066400000000000000000000004431514474157100147300ustar00rootroot00000000000000[flake8] # References: # https://flake8.readthedocs.io/en/latest/user/configuration.html # https://flake8.readthedocs.io/en/latest/user/error-codes.html # Note: there cannot be spaces after comma's here exclude = __init__.py .tox/ max-line-length = 120 [bdist_wheel] universal=1 sparse-0.18.0/sparse/000077500000000000000000000000001514474157100144035ustar00rootroot00000000000000sparse-0.18.0/sparse/__init__.py000066400000000000000000000030171514474157100165150ustar00rootroot00000000000000import os import warnings from enum import Enum from ._version import __version__, __version_tuple__ # noqa: F401 __array_api_version__ = "2024.12" class _BackendType(Enum): Numba = "Numba" Finch = "Finch" MLIR = "MLIR" _ENV_VAR_NAME = "SPARSE_BACKEND" class SparseFutureWarning(FutureWarning): pass if os.environ.get(_ENV_VAR_NAME, "") != "": warnings.warn( "Changing back-ends is a development feature, please do not rely on it in production.", SparseFutureWarning, stacklevel=1, ) _backend_name = os.environ[_ENV_VAR_NAME] else: _backend_name = _BackendType.Numba.value if _backend_name not in {v.value for v in _BackendType}: warnings.warn(f"Invalid backend identifier: {_backend_name}. Selecting Numba backend.", UserWarning, stacklevel=1) _BACKEND = _BackendType.Numba else: _BACKEND = _BackendType[_backend_name] del _backend_name if _BackendType.Finch == _BACKEND: from sparse.finch_backend import * # noqa: F403 from sparse.finch_backend import __all__ elif _BackendType.MLIR == _BACKEND: from sparse.mlir_backend import * # noqa: F403 from sparse.mlir_backend import __all__ else: from sparse.numba_backend import * # noqa: F403 from sparse.numba_backend import ( # noqa: F401 __all__, __array_namespace_info__, _common, _compressed, _coo, _dok, _io, _numba_extension, _settings, _slicing, _sparse_array, _umath, _utils, ) sparse-0.18.0/sparse/finch_backend/000077500000000000000000000000001514474157100171415ustar00rootroot00000000000000sparse-0.18.0/sparse/finch_backend/__init__.py000066400000000000000000000003721514474157100212540ustar00rootroot00000000000000try: import finch # noqa: F401 except ModuleNotFoundError as e: raise ImportError("Finch not installed. Run `pip install sparse[finch]` to enable Finch backend") from e from finch import * # noqa: F403 from finch import __all__ as __all__ sparse-0.18.0/sparse/mlir_backend/000077500000000000000000000000001514474157100170155ustar00rootroot00000000000000sparse-0.18.0/sparse/mlir_backend/__init__.py000066400000000000000000000016521514474157100211320ustar00rootroot00000000000000try: import mlir_finch # noqa: F401 del mlir_finch except ModuleNotFoundError as e: raise ImportError( "MLIR Python bindings not installed. Run `pip install finch-mlir` to enable the MLIR backend." ) from e from . import formats from ._array import Array from ._conversions import asarray, from_constituent_arrays, to_numpy, to_scipy from ._dtypes import ( asdtype, complex64, complex128, float16, float32, float64, int8, int16, int32, int64, uint8, uint16, uint32, uint64, ) from ._ops import add, reshape __all__ = [ "Array", "add", "asarray", "asdtype", "to_numpy", "to_scipy", "formats", "reshape", "from_constituent_arrays", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float16", "float32", "float64", "complex64", "complex128", ] sparse-0.18.0/sparse/mlir_backend/_array.py000066400000000000000000000026461514474157100206540ustar00rootroot00000000000000import numpy as np from ._dtypes import DType from .formats import ConcreteFormat class Array: def __init__(self, *, storage, shape: tuple[int, ...]) -> None: storage_rank = storage.get_storage_format().rank if len(shape) != storage_rank: raise ValueError(f"Mismatched rank, `{storage_rank=}`, `{shape=}`") self._storage = storage self._shape = shape @property def shape(self) -> tuple[int, ...]: return self._shape @property def ndim(self) -> int: return len(self.shape) @property def dtype(self) -> DType: return self._storage.get_storage_format().dtype @property def format(self) -> ConcreteFormat: return self._storage.get_storage_format() def _get_mlir_type(self): return self.format._get_mlir_type(shape=self.shape) def _to_module_arg(self): return self._storage.to_module_arg() def copy(self) -> "Array": from ._conversions import from_constituent_arrays arrs = tuple(arr.copy() for arr in self.get_constituent_arrays()) return from_constituent_arrays(format=self.format, arrays=arrs, shape=self.shape) def asformat(self, format: ConcreteFormat) -> "Array": from ._ops import asformat return asformat(self, format=format) def get_constituent_arrays(self) -> tuple[np.ndarray, ...]: return self._storage.get_constituent_arrays() sparse-0.18.0/sparse/mlir_backend/_common.py000066400000000000000000000032211514474157100210140ustar00rootroot00000000000000import ctypes import functools import weakref from collections.abc import Iterable import mlir_finch.runtime as rt import numpy as np from ._core import libc from ._dtypes import DType, asdtype def fn_cache(f, maxsize: int | None = None): return functools.wraps(f)(functools.lru_cache(maxsize=maxsize)(f)) def get_nd_memref_descr(rank: int, dtype: DType) -> ctypes.Structure: return _get_nd_memref_descr(int(rank), asdtype(dtype)) @fn_cache def _get_nd_memref_descr(rank: int, dtype: DType) -> ctypes.Structure: return rt.make_nd_memref_descriptor(rank, dtype.to_ctype()) def numpy_to_ranked_memref(arr: np.ndarray) -> ctypes.Structure: memref = rt.get_ranked_memref_descriptor(arr) memref_descr = get_nd_memref_descr(arr.ndim, asdtype(arr.dtype)) # Required due to ctypes type checks return memref_descr( allocated=memref.allocated, aligned=memref.aligned, offset=memref.offset, shape=memref.shape, strides=memref.strides, ) def ranked_memref_to_numpy(ref: ctypes.Structure) -> np.ndarray: return rt.ranked_memref_to_numpy([ref]) def free_memref(obj: ctypes.Structure) -> None: libc.free(ctypes.cast(obj.allocated, ctypes.c_void_p)) def _hold_ref(owner, obj): ptr = ctypes.py_object(obj) ctypes.pythonapi.Py_IncRef(ptr) def finalizer(ptr): ctypes.pythonapi.Py_DecRef(ptr) weakref.finalize(owner, finalizer, ptr) def as_shape(x) -> tuple[int]: if not isinstance(x, Iterable): x = (x,) if not all(isinstance(xi, int) for xi in x): raise TypeError("Shape must be an `int` or tuple of `int`s.") return tuple(int(xi) for xi in x) sparse-0.18.0/sparse/mlir_backend/_conversions.py000066400000000000000000000121341514474157100220770ustar00rootroot00000000000000import functools import numpy as np from ._array import Array from .formats import ConcreteFormat, Coo, Csf, Dense, Level, LevelFormat try: import scipy.sparse as sps ScipySparseArray = sps.sparray | sps.spmatrix except ImportError: sps = None ScipySparseArray = None def _guard_scipy(f): @functools.wraps(f) def wrapped(*args, **kwargs): if sps is None: raise RuntimeError("Could not import `scipy.sparse`. Please install `scipy`.") return f(*args, **kwargs) return wrapped def _from_numpy(arr: np.ndarray, copy: bool | None = None) -> Array: if copy is not None and not copy and not arr.flags["C_CONTIGUOUS"]: raise NotImplementedError("Cannot only convert C-contiguous arrays at the moment.") if copy: arr = arr.copy(order="C") arr_flat = np.ascontiguousarray(arr).reshape(-1) dense_format = Dense().with_ndim(arr.ndim).with_dtype(arr.dtype).build() return from_constituent_arrays(format=dense_format, arrays=(arr_flat,), shape=arr.shape) def to_numpy(arr: Array) -> np.ndarray: if not Dense.is_this_format(arr.format): raise TypeError(f"Cannot convert a non-dense array to NumPy. `{arr.format=}`") (data,) = arr.get_constituent_arrays() arg_order = [0] * arr.format.storage_rank for i, o in enumerate(arr.format.order): arg_order[o] = i arg_order = tuple(arg_order) storage_shape = tuple(int(arr.shape[o]) for o in arg_order) return data.reshape(storage_shape).transpose(arg_order) @_guard_scipy def _from_scipy(arr: ScipySparseArray, copy: bool | None = None) -> Array: if not isinstance(arr, ScipySparseArray): raise TypeError(f"`arr` is not a `scipy.sparse` array, `{type(arr)=}`.") match arr.format: case "csr" | "csc": order = (0, 1) if arr.format == "csr" else (1, 0) pos_width = arr.indptr.dtype.itemsize * 8 crd_width = arr.indices.dtype.itemsize * 8 csx_format = ( Csf() .with_ndim(2, canonical=arr.has_canonical_format) .with_dtype(arr.dtype) .with_crd_width(crd_width) .with_pos_width(pos_width) .with_order(order) .build() ) indptr = arr.indptr indices = arr.indices data = arr.data if copy: indptr = indptr.copy() indices = indices.copy() data = data.copy() return from_constituent_arrays(format=csx_format, arrays=(indptr, indices, data), shape=arr.shape) case "coo": row, col = arr.row, arr.col if row.dtype != col.dtype: raise RuntimeError(f"`row` and `col` dtypes must be the same: {row.dtype} != {col.dtype}.") pos = np.array([0, arr.nnz], dtype=np.int64) pos_width = pos.dtype.itemsize * 8 crd_width = row.dtype.itemsize * 8 data = arr.data if copy: data = data.copy() row = row.copy() col = col.copy() coo_format = ( Coo() .with_ndim(2, canonical=arr.has_canonical_format) .with_dtype(arr.dtype) .with_pos_width(pos_width) .with_crd_width(crd_width) .build() ) return from_constituent_arrays(format=coo_format, arrays=(pos, row, col, data), shape=arr.shape) case _: raise NotImplementedError(f"No conversion implemented for `scipy.sparse.{type(arr.__name__)}`.") @_guard_scipy def to_scipy(arr: Array) -> ScipySparseArray: storage_format = arr.format match storage_format.levels: case (Level(LevelFormat.Dense, _), Level(LevelFormat.Compressed, _)): indptr, indices, data = arr.get_constituent_arrays() if storage_format.order == (0, 1): return sps.csr_array((data, indices, indptr), shape=arr.shape) return sps.csc_array((data, indices, indptr), shape=arr.shape) case (Level(LevelFormat.Compressed, _), Level(LevelFormat.Singleton, _)): _, row, col, data = arr.get_constituent_arrays() return sps.coo_array((data, (row, col)), shape=arr.shape) case _: raise RuntimeError(f"No conversion implemented for `{storage_format=}`.") def asarray(arr, copy: bool | None = None) -> Array: if sps is not None and isinstance(arr, ScipySparseArray): return _from_scipy(arr, copy=copy) if isinstance(arr, np.ndarray): return _from_numpy(arr, copy=copy) if isinstance(arr, Array): if copy: arr = arr.copy() return arr if copy is not None and not copy and not isinstance(arr, np.ndarray): raise ValueError("Cannot non-copy convert this object.") return _from_numpy(np.asarray(arr), copy=copy) def from_constituent_arrays(*, format: ConcreteFormat, arrays: tuple[np.ndarray, ...], shape: tuple[int, ...]) -> Array: storage = format._get_ctypes_type().from_constituent_arrays(arrays) return Array(storage=storage, shape=shape) sparse-0.18.0/sparse/mlir_backend/_core.py000066400000000000000000000024531514474157100204620ustar00rootroot00000000000000import ctypes import ctypes.util import os import pathlib import sys from mlir_finch.ir import Context from mlir_finch.passmanager import PassManager DEBUG = bool(int(os.environ.get("DEBUG", "0"))) CWD = pathlib.Path(".") finch_lib_path = f"{sys.prefix}/lib/python3.{sys.version_info.minor}/site-packages/lib" ld_library_path = os.environ.get("LD_LIBRARY_PATH") ld_library_path = f"{finch_lib_path}:{ld_library_path}" if ld_library_path is None else finch_lib_path os.environ["LD_LIBRARY_PATH"] = ld_library_path MLIR_C_RUNNER_UTILS = ctypes.util.find_library("mlir_c_runner_utils") if os.name == "posix" and MLIR_C_RUNNER_UTILS is not None: MLIR_C_RUNNER_UTILS = f"{finch_lib_path}/{MLIR_C_RUNNER_UTILS}" SHARED_LIBS = [] if MLIR_C_RUNNER_UTILS is not None: SHARED_LIBS.append(MLIR_C_RUNNER_UTILS) libc = ctypes.CDLL(ctypes.util.find_library("c")) if os.name != "nt" else ctypes.cdll.msvcrt libc.free.argtypes = [ctypes.c_void_p] libc.free.restype = None SHARED_LIBS = [] if DEBUG: SHARED_LIBS.append(MLIR_C_RUNNER_UTILS) OPT_LEVEL = 0 if DEBUG else 2 # TODO: remove global state ctx = Context() pm = PassManager.parse( """ builtin.module( sparse-assembler{direct-out=true}, sparsifier{create-sparse-deallocs=1 enable-runtime-library=false} ) """, context=ctx, ) sparse-0.18.0/sparse/mlir_backend/_dtypes.py000066400000000000000000000057171514474157100210500ustar00rootroot00000000000000import abc import dataclasses import math import sys import mlir_finch.runtime as rt from mlir_finch import ir import numpy as np class MlirType(abc.ABC): @abc.abstractmethod def _get_mlir_type(self) -> ir.Type: ... def _get_pointer_width() -> int: return round(math.log2(sys.maxsize + 1.0)) + 1 _PTR_WIDTH = _get_pointer_width() @dataclasses.dataclass(eq=True, frozen=True, kw_only=True) class DType(MlirType): bit_width: int @property @abc.abstractmethod def np_dtype(self) -> np.dtype: raise NotImplementedError def to_ctype(self): return rt.as_ctype(self.np_dtype) def __eq__(self, value): if np.isdtype(value) or isinstance(value, str): value = asdtype(value) return super().__eq__(value) @dataclasses.dataclass(eq=True, frozen=True, kw_only=True) class IeeeRealFloatingDType(DType): @property def np_dtype(self) -> np.dtype: return np.dtype(getattr(np, f"float{self.bit_width}")) def _get_mlir_type(self) -> ir.Type: return getattr(ir, f"F{self.bit_width}Type").get() float64 = IeeeRealFloatingDType(bit_width=64) float32 = IeeeRealFloatingDType(bit_width=32) float16 = IeeeRealFloatingDType(bit_width=16) @dataclasses.dataclass(eq=True, frozen=True, kw_only=True) class IeeeComplexFloatingDType(DType): @property def np_dtype(self) -> np.dtype: return np.dtype(getattr(np, f"complex{self.bit_width}")) def _get_mlir_type(self) -> ir.Type: return ir.ComplexType.get(getattr(ir, f"F{self.bit_width // 2}Type").get()) complex64 = IeeeComplexFloatingDType(bit_width=64) complex128 = IeeeComplexFloatingDType(bit_width=128) @dataclasses.dataclass(eq=True, frozen=True, kw_only=True) class IntegerDType(DType): def _get_mlir_type(self) -> ir.Type: return ir.IntegerType.get_signless(self.bit_width) @dataclasses.dataclass(eq=True, frozen=True, kw_only=True) class UnsignedIntegerDType(IntegerDType): @property def np_dtype(self) -> np.dtype: return np.dtype(getattr(np, f"uint{self.bit_width}")) uint8 = UnsignedIntegerDType(bit_width=8) uint16 = UnsignedIntegerDType(bit_width=16) uint32 = UnsignedIntegerDType(bit_width=32) uint64 = UnsignedIntegerDType(bit_width=64) @dataclasses.dataclass(eq=True, frozen=True, kw_only=True) class SignedIntegerDType(IntegerDType): @property def np_dtype(self) -> np.dtype: return np.dtype(getattr(np, f"int{self.bit_width}")) int8 = SignedIntegerDType(bit_width=8) int16 = SignedIntegerDType(bit_width=16) int32 = SignedIntegerDType(bit_width=32) int64 = SignedIntegerDType(bit_width=64) intp: SignedIntegerDType = locals()[f"int{_PTR_WIDTH}"] uintp: UnsignedIntegerDType = locals()[f"uint{_PTR_WIDTH}"] def isdtype(dt, /) -> bool: return isinstance(dt, DType) NUMPY_DTYPE_MAP = {np.dtype(dt.np_dtype): dt for dt in locals().values() if isdtype(dt)} def asdtype(dt, /) -> DType: if isdtype(dt): return dt return NUMPY_DTYPE_MAP[np.dtype(dt)] sparse-0.18.0/sparse/mlir_backend/_ops.py000066400000000000000000000205611514474157100203330ustar00rootroot00000000000000import ctypes import math import mlir_finch.execution_engine import mlir_finch.passmanager from mlir_finch import ir from mlir_finch.dialects import arith, complex, func, linalg, sparse_tensor, tensor import numpy as np from ._array import Array from ._common import as_shape, fn_cache from ._core import CWD, DEBUG, OPT_LEVEL, SHARED_LIBS, ctx, pm from ._dtypes import DType, IeeeComplexFloatingDType, IeeeRealFloatingDType, IntegerDType from .formats import ConcreteFormat, _determine_format @fn_cache def get_add_module( a_tensor_type: ir.RankedTensorType, b_tensor_type: ir.RankedTensorType, out_tensor_type: ir.RankedTensorType, dtype: DType, ) -> ir.Module: with ir.Location.unknown(ctx): module = ir.Module.create() if isinstance(dtype, IeeeRealFloatingDType): arith_op = arith.AddFOp elif isinstance(dtype, IeeeComplexFloatingDType): arith_op = complex.AddOp elif isinstance(dtype, IntegerDType): arith_op = arith.AddIOp else: raise RuntimeError(f"Can not add {dtype=}.") dtype = dtype._get_mlir_type() max_rank = out_tensor_type.rank with ir.InsertionPoint(module.body): @func.FuncOp.from_py_func(a_tensor_type, b_tensor_type) def add(a, b): out = tensor.empty(out_tensor_type.shape, dtype, encoding=out_tensor_type.encoding) generic_op = linalg.GenericOp( [out_tensor_type], [a, b], [out], ir.ArrayAttr.get( [ ir.AffineMapAttr.get(ir.AffineMap.get_minor_identity(max_rank, t.rank)) for t in (a_tensor_type, b_tensor_type, out_tensor_type) ] ), ir.ArrayAttr.get([ir.Attribute.parse("#linalg.iterator_type")] * max_rank), ) block = generic_op.regions[0].blocks.append(dtype, dtype, dtype) with ir.InsertionPoint(block): a, b, o = block.arguments res = sparse_tensor.BinaryOp(dtype, a, b) overlap = res.regions[0].blocks.append(dtype, dtype) with ir.InsertionPoint(overlap): arg0, arg1 = overlap.arguments overlap_res = arith_op(arg0, arg1) sparse_tensor.YieldOp([overlap_res]) left_region = res.regions[1].blocks.append(dtype) with ir.InsertionPoint(left_region): (arg0,) = left_region.arguments sparse_tensor.YieldOp([arg0]) right_region = res.regions[2].blocks.append(dtype) with ir.InsertionPoint(right_region): (arg0,) = right_region.arguments sparse_tensor.YieldOp([arg0]) linalg.YieldOp([res]) return generic_op.result add.func_op.attributes["llvm.emit_c_interface"] = ir.UnitAttr.get() if DEBUG: (CWD / "add_module.mlir").write_text(str(module)) pm.run(module.operation) if DEBUG: (CWD / "add_module_opt.mlir").write_text(str(module)) return mlir_finch.execution_engine.ExecutionEngine(module, opt_level=OPT_LEVEL, shared_libs=SHARED_LIBS) @fn_cache def get_reshape_module( a_tensor_type: ir.RankedTensorType, shape_tensor_type: ir.RankedTensorType, out_tensor_type: ir.RankedTensorType, ) -> ir.Module: with ir.Location.unknown(ctx): module = ir.Module.create() with ir.InsertionPoint(module.body): @func.FuncOp.from_py_func(a_tensor_type, shape_tensor_type) def reshape(a, shape): return tensor.reshape(out_tensor_type, a, shape) reshape.func_op.attributes["llvm.emit_c_interface"] = ir.UnitAttr.get() if DEBUG: (CWD / "reshape_module.mlir").write_text(str(module)) pm.run(module.operation) if DEBUG: (CWD / "reshape_module_opt.mlir").write_text(str(module)) return mlir_finch.execution_engine.ExecutionEngine(module, opt_level=OPT_LEVEL, shared_libs=SHARED_LIBS) @fn_cache def get_broadcast_to_module( in_tensor_type: ir.RankedTensorType, out_tensor_type: ir.RankedTensorType, dimensions: tuple[int, ...], ) -> ir.Module: with ir.Location.unknown(ctx): module = ir.Module.create() with ir.InsertionPoint(module.body): @func.FuncOp.from_py_func(in_tensor_type) def broadcast_to(in_tensor): out = tensor.empty( out_tensor_type.shape, out_tensor_type.element_type, encoding=out_tensor_type.encoding ) return linalg.broadcast(in_tensor, outs=[out], dimensions=dimensions) broadcast_to.func_op.attributes["llvm.emit_c_interface"] = ir.UnitAttr.get() if DEBUG: (CWD / "broadcast_to_module.mlir").write_text(str(module)) pm.run(module.operation) if DEBUG: (CWD / "broadcast_to_module_opt.mlir").write_text(str(module)) return mlir_finch.execution_engine.ExecutionEngine(module, opt_level=OPT_LEVEL, shared_libs=SHARED_LIBS) @fn_cache def get_convert_module( in_tensor_type: ir.RankedTensorType, out_tensor_type: ir.RankedTensorType, ): with ir.Location.unknown(ctx): module = ir.Module.create() with ir.InsertionPoint(module.body): @func.FuncOp.from_py_func(in_tensor_type) def convert(in_tensor): return sparse_tensor.convert(out_tensor_type, in_tensor) convert.func_op.attributes["llvm.emit_c_interface"] = ir.UnitAttr.get() if DEBUG: (CWD / "convert_module.mlir").write_text(str(module)) pm.run(module.operation) if DEBUG: (CWD / "convert_module.mlir").write_text(str(module)) return mlir_finch.execution_engine.ExecutionEngine(module, opt_level=OPT_LEVEL, shared_libs=SHARED_LIBS) def add(x1: Array, x2: Array, /) -> Array: # TODO: Determine output format via autoscheduler ret_storage_format = _determine_format(x1.format, x2.format, dtype=x1.dtype, union=True) ret_storage = ret_storage_format._get_ctypes_type(owns_memory=True)() out_tensor_type = ret_storage_format._get_mlir_type(shape=np.broadcast_shapes(x1.shape, x2.shape)) add_module = get_add_module( x1._get_mlir_type(), x2._get_mlir_type(), out_tensor_type=out_tensor_type, dtype=x1.dtype, ) add_module.invoke( "add", ctypes.pointer(ctypes.pointer(ret_storage)), *x1._to_module_arg(), *x2._to_module_arg(), ) return Array(storage=ret_storage, shape=tuple(out_tensor_type.shape)) def asformat(x: Array, /, format: ConcreteFormat) -> Array: if format.rank != x.ndim: raise ValueError(f"`format.rank != `self.ndim`, {format.rank=}, {x.ndim=}") if format == x.format: return x out_tensor_type = format._get_mlir_type(shape=x.shape) ret_storage = format._get_ctypes_type(owns_memory=True)() convert_module = get_convert_module( x._get_mlir_type(), out_tensor_type, ) convert_module.invoke( "convert", ctypes.pointer(ctypes.pointer(ret_storage)), *x._to_module_arg(), ) return Array(storage=ret_storage, shape=x.shape) def reshape(x: Array, /, shape: tuple[int, ...]) -> Array: from ._conversions import _from_numpy shape = as_shape(shape) if math.prod(x.shape) != math.prod(shape): raise ValueError(f"`math.prod(x.shape) != math.prod(shape)`, {x.shape=}, {shape=}") ret_storage_format = _determine_format(x.format, dtype=x.dtype, union=len(shape) > x.ndim, out_ndim=len(shape)) shape_array = _from_numpy(np.asarray(shape, dtype=np.uint64)) out_tensor_type = ret_storage_format._get_mlir_type(shape=shape) ret_storage = ret_storage_format._get_ctypes_type(owns_memory=True)() reshape_module = get_reshape_module(x._get_mlir_type(), shape_array._get_mlir_type(), out_tensor_type) reshape_module.invoke( "reshape", ctypes.pointer(ctypes.pointer(ret_storage)), *x._to_module_arg(), *shape_array._to_module_arg(), ) return Array(storage=ret_storage, shape=shape) sparse-0.18.0/sparse/mlir_backend/formats.py000066400000000000000000000344331514474157100210510ustar00rootroot00000000000000import ctypes import dataclasses import enum import itertools import re import typing from mlir_finch import ir from mlir_finch.dialects import sparse_tensor import numpy as np from ._common import ( _hold_ref, fn_cache, free_memref, get_nd_memref_descr, numpy_to_ranked_memref, ranked_memref_to_numpy, ) from ._core import ctx from ._dtypes import DType, asdtype _CAMEL_TO_SNAKE = [re.compile("(.)([A-Z][a-z]+)"), re.compile("([a-z0-9])([A-Z])")] __all__ = ["LevelProperties", "LevelFormat", "ConcreteFormat", "Level", "get_concrete_format"] def _camel_to_snake(name: str) -> str: for exp in _CAMEL_TO_SNAKE: name = exp.sub(r"\1_\2", name) return name.lower() class LevelProperties(enum.Flag): NonOrdered = enum.auto() NonUnique = enum.auto() SOA = enum.auto() def build(self) -> list[sparse_tensor.LevelProperty]: return [getattr(sparse_tensor.LevelProperty, _camel_to_snake(p.name)) for p in type(self) if p in self] class LevelFormat(enum.Enum): Dense = "dense" Compressed = "compressed" Singleton = "singleton" def build(self) -> sparse_tensor.LevelFormat: return getattr(sparse_tensor.LevelFormat, self.value) @dataclasses.dataclass(eq=True, frozen=True) class Level: format: LevelFormat properties: LevelProperties = LevelProperties(0) def build(self): return sparse_tensor.EncodingAttr.build_level_type(self.format.build(), self.properties.build()) @dataclasses.dataclass(eq=True, frozen=True, kw_only=True) class ConcreteFormat: levels: tuple[Level, ...] order: tuple[int, ...] pos_width: int crd_width: int dtype: DType @property def storage_rank(self) -> int: return len(self.levels) @property def rank(self) -> int: return self.storage_rank def __post_init__(self): if sorted(self.order) != list(range(self.rank)): raise ValueError(f"`sorted(self.order) != list(range(self.rank))`, `{self.order=}`, `{self.rank=}`.") @fn_cache def _get_mlir_type(self, *, shape: tuple[int, ...]) -> ir.RankedTensorType: if len(shape) != self.rank: raise ValueError(f"`len(shape) != self.rank`, {shape=}, {self.rank=}") with ir.Location.unknown(ctx): mlir_levels = [level.build() for level in self.levels] mlir_order = list(self.order) mlir_reverse_order = [0] * self.rank for i, r in enumerate(mlir_order): mlir_reverse_order[r] = i dtype = self.dtype._get_mlir_type() encoding = sparse_tensor.EncodingAttr.get( mlir_levels, ir.AffineMap.get_permutation(mlir_order), ir.AffineMap.get_permutation(mlir_reverse_order), self.pos_width, self.crd_width, ) return ir.RankedTensorType.get(list(shape), dtype, encoding) @fn_cache def _get_ctypes_type(self, *, owns_memory=False): ptr_dtype = asdtype(getattr(np, f"int{self.pos_width}")) idx_dtype = asdtype(getattr(np, f"int{self.crd_width}")) def get_fields(): fields = [] compressed_counter = 0 singleton_counter = 0 for level, next_level in itertools.zip_longest(self.levels, self.levels[1:]): if LevelFormat.Compressed == level.format: compressed_counter += 1 fields.append((f"pointers_to_{compressed_counter}", get_nd_memref_descr(1, ptr_dtype))) if next_level is not None and LevelFormat.Singleton == next_level.format: singleton_counter += 1 fields.append( ( f"indices_{compressed_counter}_coords_{singleton_counter}", get_nd_memref_descr(1, idx_dtype), ) ) else: fields.append((f"indices_{compressed_counter}", get_nd_memref_descr(1, idx_dtype))) if LevelFormat.Singleton == level.format: singleton_counter += 1 fields.append( (f"indices_{compressed_counter}_coords_{singleton_counter}", get_nd_memref_descr(1, idx_dtype)) ) fields.append(("values", get_nd_memref_descr(1, self.dtype))) return fields storage_format = self class Storage(ctypes.Structure): _fields_ = get_fields() def to_module_arg(self) -> list: return [ctypes.pointer(ctypes.pointer(f)) for f in self.get__fields_()] def get__fields_(self) -> list: return [getattr(self, field[0]) for field in self._fields_] def get_constituent_arrays(self) -> tuple[np.ndarray, ...]: arrays = tuple(ranked_memref_to_numpy(field) for field in self.get__fields_()) for arr in arrays: _hold_ref(arr, self) return arrays def get_storage_format(self) -> ConcreteFormat: return storage_format @classmethod def from_constituent_arrays(cls, arrs: list[np.ndarray]) -> "Storage": storage = cls(*(numpy_to_ranked_memref(arr) for arr in arrs)) for arr in arrs: _hold_ref(storage, arr) return storage if owns_memory: def __del__(self) -> None: for field in self.get__fields_(): free_memref(field) return Storage @dataclasses.dataclass(eq=True, frozen=True, kw_only=True) class FormatFactory: levels: tuple[Level, ...] | None = None order: typing.Literal["C", "F"] | tuple[int, ...] = "C" pos_width: int = 64 crd_width: int = 64 dtype: DType | None = None def is_ready(self) -> bool: fields = dataclasses.fields(self) return all(getattr(self, f.name) is not None for f in fields) def build(self) -> ConcreteFormat: if not self.is_ready(): raise RuntimeError("This factory is not ready. All fields must be non-None.") return get_concrete_format( levels=self.levels, order=self.order, pos_width=self.pos_width, crd_width=self.crd_width, dtype=self.dtype, ) @classmethod def _get_levels_from_ndim(cls, ndim: int, /) -> tuple[Level, ...]: raise TypeError(f"`{cls.__name__}` doesn't implement this method.") def with_ndim(self, ndim: int, /, *, canonical: bool = True) -> "FormatFactory": if ndim < 0: raise ValueError(f"`ndim < 0`, `{ndim=}`.") levels = self._get_levels_from_ndim(ndim) if not canonical: levels = tuple( dataclasses.replace( level, properties=level.properties | LevelProperties.NonOrdered | LevelProperties.NonUnique ) for level in levels ) assert len(levels) == ndim return self.with_levels(levels) def with_levels(self, levels: tuple[Level, ...], /) -> "FormatFactory": out = dataclasses.replace(self, levels=levels) out._check_consistency() return out def _check_consistency(self) -> None: order = self.order if isinstance(order, str): if order in {"C", "F"}: return raise ValueError(f"Invalid order, `{order=}`.") if sorted(order) != list(range(len(order))): raise ValueError(f"`sorted(order) != list(range(len(order)))`, `{order=}`.") levels = self.levels if levels is not None and len(levels) != len(order): raise ValueError(f"`levels is not None and len(levels) != len(order)`, `{order=}`, `{levels=}`.") def with_order(self, order: typing.Literal["C", "F"] | tuple[int, ...], /): out = dataclasses.replace(self, order=order) out._check_consistency() return out def with_ptr_width(self, width: int, /) -> "FormatFactory": return dataclasses.replace(self, pos_width=width, crd_width=width) def with_pos_width(self, width: int, /) -> "FormatFactory": return dataclasses.replace(self, pos_width=width) def with_crd_width(self, width: int, /) -> "FormatFactory": return dataclasses.replace(self, crd_width=width) def with_dtype(self, dtype: DType, /) -> "FormatFactory": return dataclasses.replace(self, dtype=dtype) @classmethod def is_this_format(cls, format: ConcreteFormat) -> bool: levels_self = cls._get_levels_from_ndim(format.storage_rank) levels_other = format.levels return all( dataclasses.replace(l1, properties=l1.properties | LevelProperties.NonOrdered | LevelProperties.NonUnique) == dataclasses.replace( l2, properties=l2.properties | LevelProperties.NonOrdered | LevelProperties.NonUnique ) for l1, l2 in zip(levels_self, levels_other, strict=True) ) class Coo(FormatFactory): @classmethod def _get_levels_from_ndim(cls, ndim: int, /) -> tuple[Level, ...]: if ndim == 0: return () level_base = Level(LevelFormat.Compressed) level_middle = Level(LevelFormat.Singleton, LevelProperties.SOA) levels = [] for i in range(ndim): level = level_base if i == 0 else level_middle if i != ndim - 1: level = dataclasses.replace(level, properties=level.properties | LevelProperties.NonUnique) levels.append(level) return tuple(levels) class Csf(FormatFactory): @classmethod def _get_levels_from_ndim(self, ndim: int, /) -> tuple[Level, ...]: if ndim == 0: return () level_middle = Level(LevelFormat.Compressed) level_base = Level(LevelFormat.Dense) levels = [] for i in range(ndim): level = level_base if i == 0 else level_middle levels.append(level) return tuple(levels) class Dense(FormatFactory): @classmethod def _get_levels_from_ndim(self, ndim: int, /) -> tuple[Level, ...]: return (Level(LevelFormat.Dense),) * ndim def get_concrete_format( *, levels: tuple[Level, ...], order: typing.Literal["C", "F"] | tuple[int, ...], pos_width: int, crd_width: int, dtype: DType, ) -> ConcreteFormat: levels = tuple(levels) if isinstance(order, str): if order == "C": order = tuple(range(len(levels))) if order == "F": order = tuple(reversed(range(len(levels)))) return _get_concrete_format( levels=levels, order=order, pos_width=int(pos_width), crd_width=int(crd_width), dtype=asdtype(dtype), ) @fn_cache def _get_concrete_format( *, levels: tuple[Level, ...], order: tuple[int, ...], pos_width: int, crd_width: int, dtype: DType, ) -> ConcreteFormat: return ConcreteFormat( levels=levels, order=order, pos_width=pos_width, crd_width=crd_width, dtype=dtype, ) def _is_sparse_level(lvl: Level | LevelFormat, /) -> bool: assert isinstance(lvl, Level | LevelFormat) if isinstance(lvl, Level): lvl = lvl.format return LevelFormat.Dense != lvl def _count_sparse_levels(format: ConcreteFormat) -> int: return sum(_is_sparse_level(lvl) for lvl in format.levels) def _count_dense_levels(format: ConcreteFormat) -> int: return sum(not _is_sparse_level(lvl) for lvl in format.levels) def _get_sparse_dense_levels( *, n_sparse: int | None = None, n_dense: int | None = None, ndim: int | None = None ) -> tuple[Level, ...]: if (n_sparse is not None) + (n_dense is not None) + (ndim is not None) != 2: assert n_sparse is not None and n_dense is not None and ndim is not None # assert n_sparse + n_dense == ndim if n_sparse is None: n_sparse = ndim - n_dense if n_dense is None: n_dense = ndim - n_sparse if ndim is None: ndim = n_dense + n_sparse assert ndim >= 0 assert n_dense >= 0 assert n_sparse >= 0 return (Level(LevelFormat.Dense),) * n_dense + (Level(LevelFormat.Compressed),) * n_sparse def _determine_format( *formats: ConcreteFormat, dtype: DType, union: bool, out_ndim: int | None = None ) -> ConcreteFormat: """Determines the output format from a group of input formats. 1. Counts the sparse levels for `union=True`, and dense ones for `union=False`. 2. Gets the max number of counted levels for each format. 3. Constructs a format with rank of `out_ndim` (max rank of inputs is taken if it's `None`). If `union=False` counted levels is the number of sparse levels, otherwise dense. Sparse levels are replaced with `LevelFormat.Compressed`. Returns ------- StorageFormat Output storage format. """ if len(formats) == 0: if out_ndim is None: out_ndim = 0 return get_concrete_format( levels=(Level(LevelFormat.Dense if union else LevelFormat.Compressed),) * out_ndim, order="C", pos_width=64, crd_width=64, dtype=dtype, ) if out_ndim is None: out_ndim = max(fmt.rank for fmt in formats) pos_width = 0 crd_width = 0 counter = _count_sparse_levels if not union else _count_dense_levels n_counted = None order = () for fmt in formats: n_counted = counter(fmt) if n_counted is None else max(n_counted, counter(fmt)) pos_width = max(pos_width, fmt.pos_width) crd_width = max(crd_width, fmt.crd_width) if order != "C": if fmt.order[: len(order)] == order: order = fmt.order elif order[: len(fmt.order)] != fmt.order: order = "C" if not isinstance(order, str): order = order + tuple(range(len(order), out_ndim)) order = order[:out_ndim] if out_ndim < n_counted: n_counted = out_ndim n_sparse = n_counted if not union else out_ndim - n_counted levels = _get_sparse_dense_levels(n_sparse=n_sparse, ndim=out_ndim) return get_concrete_format( levels=levels, order=order, pos_width=pos_width, crd_width=crd_width, dtype=dtype, ) sparse-0.18.0/sparse/mlir_backend/tests/000077500000000000000000000000001514474157100201575ustar00rootroot00000000000000sparse-0.18.0/sparse/mlir_backend/tests/__init__.py000066400000000000000000000000001514474157100222560ustar00rootroot00000000000000sparse-0.18.0/sparse/mlir_backend/tests/conftest.py000066400000000000000000000002131514474157100223520ustar00rootroot00000000000000import pytest import numpy as np @pytest.fixture(scope="module") def rng() -> np.random.Generator: return np.random.default_rng(42) sparse-0.18.0/sparse/mlir_backend/tests/test_simple.py000066400000000000000000000352651514474157100230740ustar00rootroot00000000000000import math import typing from collections.abc import Iterable import sparse import pytest import numpy as np import scipy.sparse as sps parametrize_dtypes = pytest.mark.parametrize( "dtype", [ np.int8, np.uint8, np.int16, np.uint16, np.int32, np.uint32, np.int64, np.uint64, np.float32, np.float64, np.complex64, np.complex128, ], ) def parametrize_scipy_fmt_with_arg(name: str) -> pytest.MarkDecorator: return pytest.mark.parametrize( name, ["csr", "csc", "coo"], ) parametrize_scipy_fmt = parametrize_scipy_fmt_with_arg("format") def assert_sps_equal( expected: sps.csr_array | sps.csc_array | sps.coo_array, actual: sps.csr_array | sps.csc_array | sps.coo_array, /, *, check_canonical=False, check_dtype=True, ) -> None: assert expected.shape == actual.shape assert expected.format == actual.format if check_dtype: assert expected.dtype == actual.dtype if check_canonical: expected.eliminate_zeros() expected.sum_duplicates() actual.eliminate_zeros() actual.sum_duplicates() if expected.format != "coo": np.testing.assert_array_equal(expected.indptr, actual.indptr) np.testing.assert_array_equal(expected.indices, actual.indices) else: np.testing.assert_array_equal(expected.row, actual.row) np.testing.assert_array_equal(expected.col, actual.col) np.testing.assert_array_equal(expected.data, actual.data) def generate_sampler(dtype: np.dtype, rng: np.random.Generator) -> typing.Callable[[tuple[int, ...]], np.ndarray]: dtype = np.dtype(dtype) if np.issubdtype(dtype, np.signedinteger): def sampler_signed(size: tuple[int, ...]): return rng.integers(-10, 10, dtype=dtype, endpoint=True, size=size) return sampler_signed if np.issubdtype(dtype, np.unsignedinteger): def sampler_unsigned(size: tuple[int, ...]): return rng.integers(0, 10, dtype=dtype, endpoint=True, size=size) return sampler_unsigned if np.issubdtype(dtype, np.floating): def sampler_real_floating(size: tuple[int, ...]): return -10 + 20 * rng.random(dtype=dtype, size=size) return sampler_real_floating if np.issubdtype(dtype, np.complexfloating): float_dtype = np.array(0, dtype=dtype).real.dtype def sampler_complex_floating(size: tuple[int, ...]): real_sampler = generate_sampler(float_dtype, rng) if not isinstance(size, Iterable): size = (size,) float_arr = real_sampler(tuple(size) + (2,)) return float_arr.view(dtype)[..., 0] return sampler_complex_floating raise NotImplementedError(f"{dtype=} not yet supported.") def get_example_csf_arrays(dtype: np.dtype) -> tuple: pos_1 = np.array([0, 1, 3], dtype=np.int64) crd_1 = np.array([1, 0, 1], dtype=np.int64) pos_2 = np.array([0, 3, 5, 7], dtype=np.int64) crd_2 = np.array([0, 1, 3, 0, 3, 0, 1], dtype=np.int64) data = np.array([1, 2, 3, 4, 5, 6, 7], dtype=dtype) return pos_1, crd_1, pos_2, crd_2, data @parametrize_dtypes @pytest.mark.parametrize("shape", [(100,), (10, 200), (5, 10, 20)]) def test_dense_format(dtype, shape): data = np.arange(math.prod(shape), dtype=dtype).reshape(shape) tensor = sparse.asarray(data) actual = sparse.to_numpy(tensor) np.testing.assert_equal(actual, data) def assert_array_equal( expected: sparse.Array, actual: sparse.Array, /, *, same_format: bool = True, same_dtype: bool = True, data_test_fn: typing.Callable[[np.ndarray, np.ndarray], None] = np.testing.assert_array_equal, ) -> None: if same_format: assert expected.format == actual.format if same_dtype: assert expected.dtype == actual.dtype assert expected.shape == actual.shape actual = actual.asformat(expected.format) carrs_expected = expected.get_constituent_arrays() carrs_actual = actual.get_constituent_arrays() for e, a in zip(carrs_expected[:-1], carrs_actual[:-1], strict=True): assert e.dtype == a.dtype np.testing.assert_equal(e, a) data_test_fn(carrs_expected[-1], carrs_actual[-1]) @parametrize_dtypes @parametrize_scipy_fmt def test_roundtrip(rng, dtype, format): SHAPE = (80, 100) DENSITY = 0.6 sampler = generate_sampler(dtype, rng) sps_arr = sps.random_array( SHAPE, density=DENSITY, format=format, dtype=dtype, random_state=rng, data_sampler=sampler ) sp_arr = sparse.asarray(sps_arr) sps_roundtripped = sparse.to_scipy(sp_arr) assert_sps_equal(sps_arr, sps_roundtripped) sp_arr_roundtripped = sparse.asarray(sps_roundtripped) assert_array_equal(sp_arr, sp_arr_roundtripped) @parametrize_dtypes @pytest.mark.parametrize("shape", [(80, 100), (200,), (10, 20, 30)]) def test_roundtrip_dense(rng, dtype, shape): sampler = generate_sampler(dtype, rng) np_arr = sampler(shape) sp_arr = sparse.asarray(np_arr) np_roundtripped = sparse.to_numpy(sp_arr) assert np_arr.dtype == np_roundtripped.dtype np.testing.assert_array_equal(np_arr, np_roundtripped) sp_arr_roundtripped = sparse.asarray(np_roundtripped) assert_array_equal(sp_arr, sp_arr_roundtripped) @parametrize_dtypes @parametrize_scipy_fmt_with_arg("format1") @parametrize_scipy_fmt_with_arg("format2") def test_add(rng, dtype, format1, format2): if format1 == "coo" or format2 == "coo": pytest.xfail(reason="https://github.com/llvm/llvm-project/issues/116012") SHAPE = (100, 50) DENSITY = 0.5 sampler = generate_sampler(dtype, rng) sps_arr1 = sps.random_array( SHAPE, density=DENSITY, format=format1, dtype=dtype, random_state=rng, data_sampler=sampler ) sps_arr2 = sps.random_array( SHAPE, density=DENSITY, format=format2, dtype=dtype, random_state=rng, data_sampler=sampler ) sp_arr1 = sparse.asarray(sps_arr1) sp_arr2 = sparse.asarray(sps_arr2) expected = sps_arr1 + sps_arr2 actual = sparse.add(sp_arr1, sp_arr2) actual_sps = sparse.to_scipy(actual.asformat(sparse.asarray(expected).format)) assert_sps_equal(expected, actual_sps, check_canonical=True) @parametrize_dtypes @pytest.mark.parametrize("shape", [(80, 100), (200,), (10, 20, 30)]) def test_add_dense(rng, dtype, shape): sampler = generate_sampler(dtype, rng) np_arr1 = sampler(shape) np_arr2 = sampler(shape) sp_arr1 = sparse.asarray(np_arr1) sp_arr2 = sparse.asarray(np_arr2) expected = np_arr1 + np_arr2 actual = sparse.add(sp_arr1, sp_arr2) actual_np = sparse.to_numpy(actual) np.testing.assert_array_equal(expected, actual_np) @parametrize_dtypes @parametrize_scipy_fmt def test_add_dense_sparse(rng, dtype, format): if format == "coo": pytest.xfail(reason="https://github.com/llvm/llvm-project/issues/116012") sampler = generate_sampler(dtype, rng) SHAPE = (100, 50) DENSITY = 0.5 np_arr1 = sampler(SHAPE) sps_arr2 = sps.random_array( SHAPE, density=DENSITY, format=format, dtype=dtype, random_state=rng, data_sampler=sampler ) sp_arr1 = sparse.asarray(np_arr1) sp_arr2 = sparse.asarray(sps_arr2) expected = np_arr1 + sps_arr2 actual = sparse.add(sp_arr1, sp_arr2) actual_np = sparse.to_numpy(actual.asformat(sp_arr1.format)) np.testing.assert_array_equal(expected, actual_np) @parametrize_dtypes def test_csf_format(dtype): format = sparse.formats.Csf().with_ndim(3).with_dtype(dtype).build() SHAPE = (2, 2, 4) pos_1, crd_1, pos_2, crd_2, data = get_example_csf_arrays(dtype) constituent_arrays = (pos_1, crd_1, pos_2, crd_2, data) csf_array = sparse.from_constituent_arrays(format=format, arrays=constituent_arrays, shape=SHAPE) result_arrays = csf_array.get_constituent_arrays() for actual, expected in zip(result_arrays, constituent_arrays, strict=True): np.testing.assert_array_equal(actual, expected) actual = sparse.add(csf_array, csf_array) expected = sparse.from_constituent_arrays(format=format, arrays=(pos_1, crd_1, pos_2, crd_2, data * 2), shape=SHAPE) assert_array_equal(expected, actual) @parametrize_dtypes def test_coo_3d_format(dtype): format = sparse.formats.Coo().with_ndim(3).with_dtype(dtype).build() SHAPE = (2, 2, 4) pos = np.array([0, 7]) crd = [np.array([0, 1, 0, 0, 1, 1, 0]), np.array([1, 3, 1, 0, 0, 1, 0]), np.array([3, 1, 1, 0, 1, 1, 1])] data = np.array([1, 2, 3, 4, 5, 6, 7], dtype=dtype) carrs = (pos, *crd, data) coo_array = sparse.from_constituent_arrays(format=format, arrays=carrs, shape=SHAPE) result = coo_array.get_constituent_arrays() for actual, expected in zip(result, carrs, strict=True): np.testing.assert_array_equal(actual, expected) actual = sparse.add(coo_array, coo_array).asformat(coo_array.format) expected = sparse.from_constituent_arrays(format=actual.format, arrays=(pos, *crd, data * 2), shape=SHAPE) assert_array_equal(expected, actual) @parametrize_dtypes def test_sparse_vector_format(dtype): if sparse.asdtype(dtype) in {sparse.complex64, sparse.complex128}: pytest.xfail("The sparse_vector format returns incorrect results for complex dtypes.") format = sparse.formats.Coo().with_ndim(1).with_dtype(dtype).build() SHAPE = (10,) pos = np.array([0, 6]) crd = np.array([0, 1, 2, 6, 8, 9]) data = np.array([1, 2, 3, 4, 5, 6], dtype=dtype) carrs = (pos, crd, data) sv_array = sparse.from_constituent_arrays(format=format, arrays=carrs, shape=SHAPE) result = sv_array.get_constituent_arrays() for actual, expected in zip(result, carrs, strict=True): np.testing.assert_array_equal(actual, expected) actual = sparse.add(sv_array, sv_array) expected = sparse.from_constituent_arrays(format=actual.format, arrays=(pos, crd, data * 2), shape=SHAPE) assert_array_equal(expected, actual) dense = np.array([1, 2, 3, 0, 0, 0, 4, 0, 5, 6], dtype=dtype) dense_array = sparse.asarray(dense) res = sparse.to_numpy(sparse.add(dense_array, sv_array)) np.testing.assert_array_equal(res, dense * 2) def test_copy(): arr_np_orig = np.arange(25).reshape((5, 5)) arr_np_copy = arr_np_orig.copy() arr_sp1 = sparse.asarray(arr_np_copy, copy=True) arr_sp2 = sparse.asarray(arr_np_copy, copy=False).copy() arr_sp3 = sparse.asarray(arr_np_copy, copy=False) arr_np_copy[2, 2] = 42 np.testing.assert_array_equal(sparse.to_numpy(arr_sp1), arr_np_orig) np.testing.assert_array_equal(sparse.to_numpy(arr_sp2), arr_np_orig) np.testing.assert_array_equal(sparse.to_numpy(arr_sp3), arr_np_copy) @parametrize_dtypes @pytest.mark.parametrize( "format", [ "csr", pytest.param("csc", marks=pytest.mark.xfail(reason="https://github.com/llvm/llvm-project/pull/109641")), "coo", ], ) @pytest.mark.parametrize( ("shape", "new_shape"), [ ((100, 50), (25, 200)), ((100, 50), (10, 500, 1)), ((80, 1), (8, 10)), ((80, 1), (80,)), ], ) def test_reshape(rng, dtype, format, shape, new_shape): DENSITY = 0.5 sampler = generate_sampler(dtype, rng) arr_sps = sps.random_array( shape, density=DENSITY, format=format, dtype=dtype, random_state=rng, data_sampler=sampler ) arr_sps.eliminate_zeros() arr_sps.sum_duplicates() arr = sparse.asarray(arr_sps) actual = sparse.reshape(arr, shape=new_shape) assert actual.shape == new_shape try: scipy_format = sparse.to_scipy(actual).format except RuntimeError: tmp_fmt = sparse.formats.Dense().with_ndim(arr.ndim).with_dtype(dtype).build() arr_dense = arr.asformat(tmp_fmt) arr_np = sparse.to_numpy(arr_dense) expected_np = arr_np.reshape(new_shape) out_fmt = sparse.formats.Dense().with_ndim(expected_np.ndim).with_dtype(dtype).build() actual_dense = actual.asformat(out_fmt) actual_np = sparse.to_numpy(actual_dense) np.testing.assert_array_equal(expected_np, actual_np) return expected = sparse.asarray(arr_sps.reshape(new_shape).asformat(scipy_format)) for x, y in zip(expected.get_constituent_arrays(), actual.get_constituent_arrays(), strict=True): np.testing.assert_array_equal(x, y) @parametrize_dtypes def test_reshape_csf(dtype): # CSF csf_shape = (2, 2, 4) csf_format = sparse.formats.Csf().with_ndim(3).with_dtype(dtype).build() for shape, new_shape, expected_arrs in [ ( csf_shape, (4, 4, 1), [ np.array([0, 0, 3, 5, 7]), np.array([0, 1, 3, 0, 3, 0, 1]), np.array([0, 1, 2, 3, 4, 5, 6, 7]), np.array([0, 0, 0, 0, 0, 0, 0]), np.array([1, 2, 3, 4, 5, 6, 7]), ], ), ( csf_shape, (2, 1, 8), [ np.array([0, 1, 2]), np.array([0, 0]), np.array([0, 3, 7]), np.array([4, 5, 7, 0, 3, 4, 5]), np.array([1, 2, 3, 4, 5, 6, 7]), ], ), ]: arrs = get_example_csf_arrays(dtype) csf_tensor = sparse.from_constituent_arrays(format=csf_format, arrays=arrs, shape=shape) result = sparse.reshape(csf_tensor, shape=new_shape) for actual, expected in zip(result.get_constituent_arrays(), expected_arrs, strict=True): np.testing.assert_array_equal(actual, expected) @parametrize_dtypes def test_reshape_dense(dtype): SHAPE = (2, 2, 4) np_arr = np.arange(math.prod(SHAPE), dtype=dtype).reshape(SHAPE) sp_arr = sparse.asarray(np_arr) for new_shape in [ (4, 4, 1), (2, 1, 8), ]: expected = np_arr.reshape(new_shape) actual = sparse.reshape(sp_arr, new_shape) actual_np = sparse.to_numpy(actual) assert actual_np.dtype == expected.dtype np.testing.assert_equal(actual_np, expected) @pytest.mark.parametrize("src_fmt", ["csr", "csc", "coo"]) @pytest.mark.parametrize("dst_fmt", ["csr", "csc", "coo"]) def test_asformat(rng, src_fmt, dst_fmt): if "coo" in {src_fmt, dst_fmt}: pytest.xfail(reason="https://github.com/llvm/llvm-project/issues/116012") SHAPE = (100, 50) DENSITY = 0.5 sampler = generate_sampler(np.float64, rng) sps_arr = sps.random_array( SHAPE, density=DENSITY, format=src_fmt, dtype=np.float64, random_state=rng, data_sampler=sampler ) sp_arr = sparse.asarray(sps_arr) expected = sps_arr.asformat(dst_fmt) actual_fmt = sparse.asarray(expected, copy=False).format actual = sp_arr.asformat(actual_fmt) actual_sps = sparse.to_scipy(actual) assert actual_sps.format == dst_fmt assert_sps_equal(expected, actual_sps) sparse-0.18.0/sparse/numba_backend/000077500000000000000000000000001514474157100171545ustar00rootroot00000000000000sparse-0.18.0/sparse/numba_backend/__init__.py000066400000000000000000000121661514474157100212730ustar00rootroot00000000000000from numpy import ( add, bitwise_and, bitwise_not, bitwise_or, bitwise_xor, ceil, complex64, complex128, conj, copysign, cos, cosh, divide, e, exp, expm1, finfo, float16, float32, float64, floor, floor_divide, greater, greater_equal, hypot, iinfo, inf, int8, int16, int32, int64, isfinite, less, less_equal, log, log1p, log2, log10, logaddexp, logical_and, logical_not, logical_or, logical_xor, maximum, minimum, multiply, nan, negative, newaxis, nextafter, not_equal, pi, positive, reciprocal, remainder, sign, signbit, sin, sinh, sqrt, square, subtract, tan, tanh, trunc, uint8, uint16, uint32, uint64, ) from numpy import arccos as acos from numpy import arccosh as acosh from numpy import arcsin as asin from numpy import arcsinh as asinh from numpy import arctan as atan from numpy import arctan2 as atan2 from numpy import arctanh as atanh from numpy import bool_ as bool from numpy import invert as bitwise_invert from numpy import left_shift as bitwise_left_shift from numpy import power as pow from numpy import right_shift as bitwise_right_shift from ._common import ( SparseArray, abs, all, any, asarray, asnumpy, astype, broadcast_arrays, broadcast_to, can_cast, concat, concatenate, diff, dot, einsum, empty, empty_like, equal, eye, full, full_like, imag, interp, isinf, isnan, matmul, max, mean, min, moveaxis, nonzero, ones, ones_like, outer, pad, permute_dims, prod, real, repeat, reshape, round, squeeze, stack, std, sum, tensordot, tile, unstack, var, vecdot, zeros, zeros_like, ) from ._compressed import GCXS from ._coo import COO, as_coo from ._coo.common import ( argmax, argmin, argwhere, asCOO, clip, diagonal, diagonalize, expand_dims, flip, isneginf, isposinf, kron, matrix_transpose, nanmax, nanmean, nanmin, nanprod, nanreduce, nansum, result_type, roll, sort, take, tril, triu, unique_counts, unique_values, where, ) from ._dok import DOK from ._io import load_npz, save_npz from ._settings import IS_NUMPY2 as _IS_NUMPY2 from ._settings import __array_namespace_info__ # noqa: F401 from ._umath import elemwise from ._utils import random __all__ = [ "COO", "DOK", "GCXS", "SparseArray", "abs", "acos", "acosh", "add", "all", "any", "argmax", "argmin", "argwhere", "asCOO", "as_coo", "asarray", "asin", "asinh", "asnumpy", "astype", "atan", "atan2", "atanh", "bitwise_and", "bitwise_invert", "bitwise_left_shift", "bitwise_not", "bitwise_or", "bitwise_right_shift", "bitwise_xor", "bool", "broadcast_arrays", "broadcast_to", "can_cast", "ceil", "clip", "complex128", "complex64", "concat", "concatenate", "conj", "copysign", "cos", "cosh", "diagonal", "diagonalize", "divide", "dot", "e", "einsum", "elemwise", "empty", "empty_like", "equal", "exp", "expand_dims", "expm1", "eye", "finfo", "flip", "float16", "float32", "float64", "floor", "floor_divide", "full", "full_like", "greater", "greater_equal", "hypot", "iinfo", "imag", "inf", "int16", "int32", "int64", "int8", "interp", "isfinite", "isinf", "isnan", "isneginf", "isposinf", "kron", "less", "less_equal", "load_npz", "log", "log10", "log1p", "log2", "logaddexp", "logical_and", "logical_not", "logical_or", "logical_xor", "matmul", "matrix_transpose", "max", "maximum", "mean", "min", "minimum", "moveaxis", "multiply", "nan", "nanmax", "nanmean", "nanmin", "nanprod", "nanreduce", "nansum", "negative", "newaxis", "nextafter", "nonzero", "not_equal", "ones", "ones_like", "outer", "pad", "permute_dims", "pi", "positive", "pow", "prod", "random", "real", "reciprocal", "remainder", "reshape", "result_type", "roll", "round", "save_npz", "sign", "signbit", "sin", "sinh", "sort", "sqrt", "square", "squeeze", "stack", "std", "subtract", "sum", "take", "tan", "tanh", "tensordot", "tril", "triu", "trunc", "uint16", "uint32", "uint64", "uint8", "unique_counts", "unique_values", "var", "vecdot", "where", "zeros", "zeros_like", "repeat", "tile", "unstack", "diff", ] if _IS_NUMPY2: from numpy import isdtype __all__ += [ "isdtype", ] __all__.sort() sparse-0.18.0/sparse/numba_backend/_common.py000066400000000000000000003272521514474157100211700ustar00rootroot00000000000000import builtins import warnings from collections.abc import Iterable from functools import reduce, wraps from itertools import chain from operator import index, mul import numba from numba import literal_unroll import numpy as np from ._coo import as_coo, expand_dims from ._sparse_array import SparseArray from ._utils import ( _zero_of_dtype, check_zero_fill_value, equivalent, normalize_axis, ) _EINSUM_SYMBOLS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" _EINSUM_SYMBOLS_SET = set(_EINSUM_SYMBOLS) def _is_scipy_sparse_obj(x): """ Tests if the supplied argument is a SciPy sparse object. """ return bool(hasattr(x, "__module__") and x.__module__.startswith("scipy.sparse")) def _check_device(func): @wraps(func) def wrapped(*args, **kwargs): device = kwargs.get("device") if device not in {"cpu", None}: raise ValueError("Device must be `'cpu'` or `None`.") return func(*args, **kwargs) return wrapped def _is_sparse(x): """ Tests if the supplied argument is a SciPy sparse object, or one from this library. """ return isinstance(x, SparseArray) or _is_scipy_sparse_obj(x) @numba.njit def nan_check(*args): """ Check for the NaN values in Numpy Arrays Parameters ---------- Union[Numpy Array, Integer, Float] Returns ------- Boolean Whether Numpy Array Contains NaN """ for i in literal_unroll(args): ia = np.asarray(i) if ia.size != 0 and np.isnan(np.min(ia)): return True return False def check_class_nan(test): """ Check NaN for Sparse Arrays Parameters ---------- test : Union[sparse.COO, sparse.GCXS, scipy.sparse.spmatrix, Numpy Ndarrays] Returns ------- Boolean Whether Sparse Array Contains NaN """ from ._compressed import GCXS from ._coo import COO if isinstance(test, GCXS | COO): return nan_check(test.fill_value, test.data) if _is_scipy_sparse_obj(test): return nan_check(test.data) return nan_check(test) def tensordot(a, b, axes=2, *, return_type=None): """ Perform the equivalent of [`numpy.tensordot`][]. Parameters ---------- a, b : Union[SparseArray, np.ndarray, scipy.sparse.spmatrix] The arrays to perform the `tensordot` operation on. axes : tuple[Union[int, tuple[int], Union[int, tuple[int]], optional The axes to match when performing the sum. return_type : {None, COO, np.ndarray}, optional Type of returned array. Returns ------- Union[SparseArray, numpy.ndarray] The result of the operation. Raises ------ ValueError If all arguments don't have zero fill-values. See Also -------- - [`numpy.tensordot`][] : NumPy equivalent function """ from ._compressed import GCXS # Much of this is stolen from numpy/core/numeric.py::tensordot # Please see license at https://github.com/numpy/numpy/blob/main/LICENSE.txt check_zero_fill_value(a, b) if _is_scipy_sparse_obj(a): a = GCXS.from_scipy_sparse(a) if _is_scipy_sparse_obj(b): b = GCXS.from_scipy_sparse(b) try: iter(axes) except TypeError: axes_a = list(range(-axes, 0)) axes_b = list(range(axes)) else: axes_a, axes_b = axes try: na = len(axes_a) axes_a = list(axes_a) except TypeError: axes_a = [axes_a] na = 1 try: nb = len(axes_b) axes_b = list(axes_b) except TypeError: axes_b = [axes_b] nb = 1 # a, b = asarray(a), asarray(b) # <--- modified as_ = a.shape nda = a.ndim bs = b.shape ndb = b.ndim equal = True if nda == 0 or ndb == 0: if axes_a == [] and axes_b == []: if nda == 0 and isinstance(a, SparseArray): a = a.todense() if ndb == 0 and isinstance(b, SparseArray): b = b.todense() return a * b pos = int(nda != 0) raise ValueError(f"Input {pos} operand does not have enough dimensions") if na != nb: equal = False else: for k in range(na): if as_[axes_a[k]] != bs[axes_b[k]]: equal = False break if axes_a[k] < 0: axes_a[k] += nda if axes_b[k] < 0: axes_b[k] += ndb if not equal: raise ValueError("shape-mismatch for sum") # Move the axes to sum over to the end of "a" # and to the front of "b" notin = [k for k in range(nda) if k not in axes_a] newaxes_a = notin + axes_a N2 = 1 for axis in axes_a: N2 *= as_[axis] newshape_a = (-1, N2) olda = [as_[axis] for axis in notin] notin = [k for k in range(ndb) if k not in axes_b] newaxes_b = axes_b + notin N2 = 1 for axis in axes_b: N2 *= bs[axis] newshape_b = (N2, -1) oldb = [bs[axis] for axis in notin] if builtins.any(dim == 0 for dim in chain(newshape_a, newshape_b)): from sparse import COO dt = np.result_type(a.dtype, b.dtype) res = COO( np.empty((len(olda) + len(oldb), 0), dtype=np.uintp), data=np.empty(0, dtype=dt), shape=tuple(olda + oldb) ) if isinstance(a, np.ndarray) or isinstance(b, np.ndarray): res = res.todense() return res at = a.transpose(newaxes_a).reshape(newshape_a) bt = b.transpose(newaxes_b).reshape(newshape_b) res = _dot(at, bt, return_type) return res.reshape(olda + oldb) def matmul(a, b): """Perform the equivalent of [`numpy.matmul`][] on two arrays. Parameters ---------- a, b : Union[SparseArray, np.ndarray, scipy.sparse.spmatrix] The arrays to perform the `matmul` operation on. Returns ------- Union[SparseArray, numpy.ndarray] The result of the operation. Raises ------ ValueError If all arguments don't have zero fill-values, or the shape of the two arrays is not broadcastable. See Also -------- - [`numpy.matmul`][] : NumPy equivalent function. - `COO.__matmul__`: Equivalent function for COO objects. """ check_zero_fill_value(a, b) if not hasattr(a, "ndim") or not hasattr(b, "ndim"): raise TypeError(f"Cannot perform dot product on types {type(a)}, {type(b)}") if check_class_nan(a) or check_class_nan(b): warnings.warn("Nan will not be propagated in matrix multiplication", RuntimeWarning, stacklevel=1) # When b is 2-d, it is equivalent to dot if b.ndim <= 2: return dot(a, b) # when a is 2-d, we need to transpose result after dot if a.ndim <= 2: res = dot(a, b) axes = list(range(res.ndim)) axes.insert(-1, axes.pop(0)) return res.transpose(axes) # If a can be squeeze to a vector, use dot will be faster if a.ndim <= b.ndim and np.prod(a.shape[:-1]) == 1: res = dot(a.reshape(-1), b) shape = list(res.shape) shape.insert(-1, 1) return res.reshape(shape) # If b can be squeeze to a matrix, use dot will be faster if b.ndim <= a.ndim and np.prod(b.shape[:-2]) == 1: return dot(a, b.reshape(b.shape[-2:])) if a.ndim < b.ndim: a = a[(None,) * (b.ndim - a.ndim)] if a.ndim > b.ndim: b = b[(None,) * (a.ndim - b.ndim)] for i, j in zip(a.shape[:-2], b.shape[:-2], strict=True): if i != 1 and j != 1 and i != j: raise ValueError("shapes of a and b are not broadcastable") def _matmul_recurser(a, b): if a.ndim == 2: return dot(a, b) res = [] for i in range(builtins.max(a.shape[0], b.shape[0])): a_i = a[0] if a.shape[0] == 1 else a[i] b_i = b[0] if b.shape[0] == 1 else b[i] res.append(_matmul_recurser(a_i, b_i)) mask = [isinstance(x, SparseArray) for x in res] if builtins.all(mask): return stack(res) res = [x.todense() if isinstance(x, SparseArray) else x for x in res] return np.stack(res) return _matmul_recurser(a, b) def dot(a, b): """ Perform the equivalent of [`numpy.dot`][] on two arrays. Parameters ---------- a, b : Union[SparseArray, np.ndarray, scipy.sparse.spmatrix] The arrays to perform the `dot` operation on. Returns ------- Union[SparseArray, numpy.ndarray] The result of the operation. Raises ------ ValueError If all arguments don't have zero fill-values. See Also -------- - [`numpy.dot`][] : NumPy equivalent function. - [`sparse.COO.dot`][] : Equivalent function for COO objects. """ check_zero_fill_value(a, b) if not hasattr(a, "ndim") or not hasattr(b, "ndim"): raise TypeError(f"Cannot perform dot product on types {type(a)}, {type(b)}") if a.ndim == 1 and b.ndim == 1: if isinstance(a, SparseArray): a = as_coo(a) if isinstance(b, SparseArray): b = as_coo(b) return (a * b).sum() a_axis = -1 b_axis = -2 if b.ndim == 1: b_axis = -1 return tensordot(a, b, axes=(a_axis, b_axis)) def _dot(a, b, return_type=None): from ._compressed import GCXS from ._coo import COO from ._sparse_array import SparseArray out_shape = (a.shape[0], b.shape[1]) if builtins.all(isinstance(arr, SparseArray) for arr in [a, b]) and builtins.any( isinstance(arr, GCXS) for arr in [a, b] ): a = a.asformat("gcxs") b = b.asformat("gcxs", compressed_axes=a.compressed_axes) if isinstance(a, GCXS) and isinstance(b, GCXS): if a.nbytes > b.nbytes: b = b.change_compressed_axes(a.compressed_axes) else: a = a.change_compressed_axes(b.compressed_axes) if a.compressed_axes == (0,): # csr @ csr compressed_axes = (0,) data, indices, indptr = _dot_csr_csr_type(a.dtype, b.dtype)( out_shape, a.data, b.data, a.indices, b.indices, a.indptr, b.indptr ) elif a.compressed_axes == (1,): # csc @ csc # a @ b = (b.T @ a.T).T compressed_axes = (1,) data, indices, indptr = _dot_csr_csr_type(b.dtype, a.dtype)( out_shape[::-1], b.data, a.data, b.indices, a.indices, b.indptr, a.indptr, ) out = GCXS( (data, indices, indptr), shape=out_shape, compressed_axes=compressed_axes, prune=True, ) if return_type == np.ndarray: return out.todense() if return_type == COO: return out.tocoo() return out if isinstance(a, GCXS) and isinstance(b, np.ndarray): if a.compressed_axes == (0,): # csr @ ndarray if return_type is None or return_type == np.ndarray: return _dot_csr_ndarray_type(a.dtype, b.dtype)(out_shape, a.data, a.indices, a.indptr, b) data, indices, indptr = _dot_csr_ndarray_type_sparse(a.dtype, b.dtype)( out_shape, a.data, a.indices, a.indptr, b ) out = GCXS( (data, indices, indptr), shape=out_shape, compressed_axes=(0,), prune=True, ) if return_type == COO: return out.tocoo() return out if return_type is None or return_type == np.ndarray: # csc @ ndarray return _dot_csc_ndarray_type(a.dtype, b.dtype)(a.shape, b.shape, a.data, a.indices, a.indptr, b) data, indices, indptr = _dot_csc_ndarray_type_sparse(a.dtype, b.dtype)( a.shape, b.shape, a.data, a.indices, a.indptr, b ) compressed_axes = (1,) out = GCXS( (data, indices, indptr), shape=out_shape, compressed_axes=compressed_axes, prune=True, ) if return_type == COO: return out.tocoo() return out if isinstance(a, np.ndarray) and isinstance(b, GCXS): at = a.view(type=np.ndarray).T bt = b.T # constant-time transpose if b.compressed_axes == (0,): if return_type is None or return_type == np.ndarray: out = _dot_csc_ndarray_type(bt.dtype, at.dtype)(bt.shape, at.shape, bt.data, bt.indices, bt.indptr, at) return out.T data, indices, indptr = _dot_csc_ndarray_type_sparse(bt.dtype, at.dtype)( bt.shape, at.shape, bt.data, b.indices, b.indptr, at ) out = GCXS( (data, indices, indptr), shape=out_shape, compressed_axes=(0,), prune=True, ) if return_type == COO: return out.tocoo() return out # compressed_axes == (1,) if return_type is None or return_type == np.ndarray: out = _dot_csr_ndarray_type(bt.dtype, at.dtype)(out_shape[::-1], bt.data, bt.indices, bt.indptr, at) return out.T data, indices, indptr = _dot_csr_ndarray_type_sparse(bt.dtype, at.dtype)( out_shape[::-1], bt.data, bt.indices, bt.indptr, at ) out = GCXS((data, indices, indptr), shape=out_shape, compressed_axes=(1,), prune=True) if return_type == COO: return out.tocoo() return out if isinstance(a, COO) and isinstance(b, COO): # convert to csr a_indptr = np.empty(a.shape[0] + 1, dtype=np.intp) a_indptr[0] = 0 np.cumsum(np.bincount(a.coords[0], minlength=a.shape[0]), out=a_indptr[1:]) b_indptr = np.empty(b.shape[0] + 1, dtype=np.intp) b_indptr[0] = 0 np.cumsum(np.bincount(b.coords[0], minlength=b.shape[0]), out=b_indptr[1:]) coords, data = _dot_coo_coo_type(a.dtype, b.dtype)( out_shape, a.coords, b.coords, a.data, b.data, a_indptr, b_indptr ) out = COO( coords, data, shape=out_shape, has_duplicates=False, sorted=False, prune=True, ) if return_type == np.ndarray: return out.todense() if return_type == GCXS: return out.asformat("gcxs") return out if isinstance(a, COO) and isinstance(b, np.ndarray): b = b.view(type=np.ndarray).T if return_type is None or return_type == np.ndarray: return _dot_coo_ndarray_type(a.dtype, b.dtype)(a.coords, a.data, b, out_shape) coords, data = _dot_coo_ndarray_type_sparse(a.dtype, b.dtype)(a.coords, a.data, b, out_shape) out = COO(coords, data, shape=out_shape, has_duplicates=False, sorted=True) if return_type == GCXS: return out.asformat("gcxs") return out if isinstance(a, np.ndarray) and isinstance(b, COO): a = a.view(type=np.ndarray) if return_type is None or return_type == np.ndarray: return _dot_ndarray_coo_type(a.dtype, b.dtype)(a, b.coords, b.data, out_shape) b = b.T coords, data = _dot_ndarray_coo_type_sparse(a.dtype, b.dtype)(a, b.coords, b.data, out_shape) out = COO(coords, data, shape=out_shape, has_duplicates=False, sorted=True, prune=True) if return_type == GCXS: return out.asformat("gcxs") return out if isinstance(a, np.ndarray) and isinstance(b, np.ndarray): return np.dot(a, b) raise TypeError("Unsupported types.") def _memoize_dtype(f): """ Memoizes a function taking in NumPy dtypes. Parameters ---------- f : Callable Returns ------- wrapped : Callable Examples -------- >>> def func(dt1): ... return object() >>> func = _memoize_dtype(func) >>> func(np.dtype("i8")) is func(np.dtype("int64")) True >>> func(np.dtype("i8")) is func(np.dtype("i4")) False """ cache = {} @wraps(f) def wrapped(*args): key = tuple(arg.name for arg in args) if key in cache: return cache[key] result = f(*args) cache[key] = result return result return wrapped @numba.jit(nopython=True, nogil=True) def _csr_csr_count_nnz(out_shape, a_indices, b_indices, a_indptr, b_indptr): # pragma: no cover """ A function for computing the number of nonzero values in the resulting array from multiplying an array with compressed rows with an array with compressed rows: (a @ b).nnz. Parameters ---------- out_shape : tuple The shape of the output array. a_indices, a_indptr : np.ndarray The indices and index pointer array of ``a``. b_data, b_indices, b_indptr : np.ndarray The indices and index pointer array of ``b``. """ n_row, n_col = out_shape nnz = 0 mask = np.full(n_col, -1) for i in range(n_row): row_nnz = 0 for j in a_indices[a_indptr[i] : a_indptr[i + 1]]: for k in b_indices[b_indptr[j] : b_indptr[j + 1]]: if mask[k] != i: mask[k] = i row_nnz += 1 nnz += row_nnz return nnz @numba.jit(nopython=True, nogil=True) def _csr_ndarray_count_nnz(out_shape, indptr, a_indices, a_indptr, b): # pragma: no cover """ A function for computing the number of nonzero values in the resulting array from multiplying an array with compressed rows with a dense numpy array: (a @ b).nnz. Parameters ---------- out_shape : tuple The shape of the output array. indptr : ndarray The empty index pointer array for the output. a_indices, a_indptr : np.ndarray The indices and index pointer array of ``a``. b : np.ndarray The second input array ``b``. """ nnz = 0 for i in range(out_shape[0]): cur_row = a_indices[a_indptr[i] : a_indptr[i + 1]] for j in range(out_shape[1]): for k in cur_row: if b[k, j] != 0: nnz += 1 break indptr[i + 1] = nnz return nnz @numba.jit(nopython=True, nogil=True) def _csc_ndarray_count_nnz(a_shape, b_shape, indptr, a_indices, a_indptr, b): # pragma: no cover """ A function for computing the number of nonzero values in the resulting array from multiplying an array with compressed columns with a dense numpy array: (a @ b).nnz. Parameters ---------- a_shape, b_shape : tuple The shapes of the input arrays. indptr : ndarray The empty index pointer array for the output. a_indices, a_indptr : np.ndarray The indices and index pointer array of ``a``. b : np.ndarray The second input array ``b``. """ nnz = 0 mask = np.full(a_shape[0], -1) for i in range(b_shape[1]): col_nnz = 0 for j in range(b_shape[0]): for k in a_indices[a_indptr[j] : a_indptr[j + 1]]: if b[j, i] != 0 and mask[k] != i: mask[k] = i col_nnz += 1 nnz += col_nnz indptr[i + 1] = nnz return nnz def _dot_dtype(dt1, dt2): return (np.zeros((), dtype=dt1) * np.zeros((), dtype=dt2)).dtype @_memoize_dtype def _dot_csr_csr_type(dt1, dt2): dtr = _dot_dtype(dt1, dt2) @numba.jit( nopython=True, nogil=True, locals={"data_curr": numba.np.numpy_support.from_dtype(dtr)}, ) def _dot_csr_csr(out_shape, a_data, b_data, a_indices, b_indices, a_indptr, b_indptr): # pragma: no cover """ Utility function taking in two ``GCXS`` objects and calculating their dot product: a @ b for a and b with compressed rows. Parameters ---------- out_shape : tuple The shape of the output array. a_data, a_indices, a_indptr : np.ndarray The data, indices, and index pointer arrays of ``a``. b_data, b_indices, b_indptr : np.ndarray The data, indices, and index pointer arrays of ``b``. """ # much of this is borrowed from: # https://github.com/scipy/scipy/blob/main/scipy/sparse/sparsetools/csr.h # calculate nnz before multiplying so we can use static arrays nnz = _csr_csr_count_nnz(out_shape, a_indices, b_indices, a_indptr, b_indptr) n_row, n_col = out_shape indptr = np.empty(n_row + 1, dtype=np.intp) indptr[0] = 0 indices = np.empty(nnz, dtype=np.intp) data = np.empty(nnz, dtype=dtr) next_ = np.full(n_col, -1) sums = np.zeros(n_col, dtype=dtr) nnz = 0 for i in range(n_row): head = -2 length = 0 next_[:] = -1 for j, av in zip( # noqa: B905 a_indices[a_indptr[i] : a_indptr[i + 1]], a_data[a_indptr[i] : a_indptr[i + 1]], ): for k, bv in zip( # noqa: B905 b_indices[b_indptr[j] : b_indptr[j + 1]], b_data[b_indptr[j] : b_indptr[j + 1]], ): sums[k] += av * bv if next_[k] == -1: next_[k] = head head = k length += 1 for _ in range(length): if next_[head] != -1: indices[nnz] = head data[nnz] = sums[head] nnz += 1 temp = head head = next_[head] next_[temp] = -1 sums[temp] = 0 indptr[i + 1] = nnz if len(indices) == (n_col * n_row): for i in range(len(indices) // n_col): j = n_col * i k = n_col * (1 + i) data[j:k] = data[j:k][::-1] indices[j:k] = indices[j:k][::-1] return data, indices, indptr return _dot_csr_csr @_memoize_dtype def _dot_csr_ndarray_type(dt1, dt2): dtr = _dot_dtype(dt1, dt2) @numba.jit( nopython=True, nogil=True, locals={"data_curr": numba.np.numpy_support.from_dtype(dtr)}, ) def _dot_csr_ndarray(out_shape, a_data, a_indices, a_indptr, b): # pragma: no cover """ Utility function taking in one `GCXS` and one ``ndarray`` and calculating their dot product: a @ b for a with compressed rows. Returns a dense result. Parameters ---------- a_data, a_indices, a_indptr : np.ndarray The data, indices, and index pointers of ``a``. b : np.ndarray The second input array ``b``. out_shape : Tuple[int] The shape of the output array. """ b = np.ascontiguousarray(b) # ensure memory aligned out = np.zeros(out_shape, dtype=dtr) for i in range(out_shape[0]): val = out[i] for k in range(a_indptr[i], a_indptr[i + 1]): ind = a_indices[k] v = a_data[k] for j in range(out_shape[1]): val[j] += v * b[ind, j] return out return _dot_csr_ndarray @_memoize_dtype def _dot_csr_ndarray_type_sparse(dt1, dt2): dtr = _dot_dtype(dt1, dt2) @numba.jit( nopython=True, nogil=True, locals={"data_curr": numba.np.numpy_support.from_dtype(dtr)}, ) def _dot_csr_ndarray_sparse(out_shape, a_data, a_indices, a_indptr, b): # pragma: no cover """ Utility function taking in one `GCXS` and one ``ndarray`` and calculating their dot product: a @ b for a with compressed rows. Returns a sparse result. Parameters ---------- a_data, a_indices, a_indptr : np.ndarray The data, indices, and index pointers of ``a``. b : np.ndarray The second input array ``b``. out_shape : Tuple[int] The shape of the output array. """ indptr = np.empty(out_shape[0] + 1, dtype=np.intp) indptr[0] = 0 nnz = _csr_ndarray_count_nnz(out_shape, indptr, a_indices, a_indptr, b) indices = np.empty(nnz, dtype=np.intp) data = np.empty(nnz, dtype=dtr) current = 0 for i in range(out_shape[0]): for j in range(out_shape[1]): val = 0 nonzero = False for k in range(a_indptr[i], a_indptr[i + 1]): ind = a_indices[k] v = a_data[k] val += v * b[ind, j] if b[ind, j] != 0: nonzero = True if nonzero: data[current] = val indices[current] = j current += 1 return data, indices, indptr return _dot_csr_ndarray_sparse @_memoize_dtype def _dot_csc_ndarray_type_sparse(dt1, dt2): dtr = _dot_dtype(dt1, dt2) @numba.jit( nopython=True, nogil=True, locals={"data_curr": numba.np.numpy_support.from_dtype(dtr)}, ) def _dot_csc_ndarray_sparse(a_shape, b_shape, a_data, a_indices, a_indptr, b): # pragma: no cover """ Utility function taking in one `GCXS` and one ``ndarray`` and calculating their dot product: a @ b for a with compressed columns. Returns a sparse result. Parameters ---------- a_data, a_indices, a_indptr : np.ndarray The data, indices, and index pointers of ``a``. b : np.ndarray The second input array ``b``. a_shape, b_shape : Tuple[int] The shapes of the input arrays. """ indptr = np.empty(b_shape[1] + 1, dtype=np.intp) nnz = _csc_ndarray_count_nnz(a_shape, b_shape, indptr, a_indices, a_indptr, b) indices = np.empty(nnz, dtype=np.intp) data = np.empty(nnz, dtype=dtr) sums = np.zeros(a_shape[0]) mask = np.full(a_shape[0], -1) nnz = 0 indptr[0] = 0 for i in range(b_shape[1]): head = -2 length = 0 for j in range(b_shape[0]): u = b[j, i] if u != 0: for k in range(a_indptr[j], a_indptr[j + 1]): ind = a_indices[k] v = a_data[k] sums[ind] += u * v if mask[ind] == -1: mask[ind] = head head = ind length += 1 for _ in range(length): if sums[head] != 0: indices[nnz] = head data[nnz] = sums[head] nnz += 1 temp = head head = mask[head] mask[temp] = -1 sums[temp] = 0 return data, indices, indptr return _dot_csc_ndarray_sparse @_memoize_dtype def _dot_csc_ndarray_type(dt1, dt2): dtr = _dot_dtype(dt1, dt2) @numba.jit( nopython=True, nogil=True, locals={"data_curr": numba.np.numpy_support.from_dtype(dtr)}, ) def _dot_csc_ndarray(a_shape, b_shape, a_data, a_indices, a_indptr, b): # pragma: no cover """ Utility function taking in one `GCXS` and one ``ndarray`` and calculating their dot product: a @ b for a with compressed columns. Returns a dense result. Parameters ---------- a_data, a_indices, a_indptr : np.ndarray The data, indices, and index pointers of ``a``. b : np.ndarray The second input array ``b``. a_shape, b_shape : Tuple[int] The shapes of the input arrays. """ b = np.ascontiguousarray(b) # ensure memory aligned out = np.zeros((a_shape[0], b_shape[1]), dtype=dtr) for i in range(b_shape[0]): for k in range(a_indptr[i], a_indptr[i + 1]): ind = a_indices[k] v = a_data[k] val = out[ind] for j in range(b_shape[1]): val[j] += v * b[i, j] return out return _dot_csc_ndarray @_memoize_dtype def _dot_coo_coo_type(dt1, dt2): dtr = _dot_dtype(dt1, dt2) @numba.jit( nopython=True, nogil=True, locals={"data_curr": numba.np.numpy_support.from_dtype(dtr)}, ) def _dot_coo_coo(out_shape, a_coords, b_coords, a_data, b_data, a_indptr, b_indptr): # pragma: no cover """ Utility function taking in two ``COO`` objects and calculating their dot product: a @ b. Parameters ---------- a_shape, b_shape : tuple The shapes of the input arrays. a_data, a_coords : np.ndarray The data and coordinates of ``a``. b_data, b_coords : np.ndarray The data and coordinates of ``b``. """ # much of this is borrowed from: # https://github.com/scipy/scipy/blob/main/scipy/sparse/sparsetools/csr.h n_row, n_col = out_shape # calculate nnz before multiplying so we can use static arrays nnz = _csr_csr_count_nnz(out_shape, a_coords[1], b_coords[1], a_indptr, b_indptr) coords = np.empty((2, nnz), dtype=np.intp) data = np.empty(nnz, dtype=dtr) next_ = np.full(n_col, -1) sums = np.zeros(n_col, dtype=dtr) nnz = 0 for i in range(n_row): head = -2 length = 0 next_[:] = -1 for j, av in zip( # noqa: B905 a_coords[1, a_indptr[i] : a_indptr[i + 1]], a_data[a_indptr[i] : a_indptr[i + 1]], ): for k, bv in zip( # noqa: B905 b_coords[1, b_indptr[j] : b_indptr[j + 1]], b_data[b_indptr[j] : b_indptr[j + 1]], ): sums[k] += av * bv if next_[k] == -1: next_[k] = head head = k length += 1 for _ in range(length): if next_[head] != -1: coords[0, nnz] = i coords[1, nnz] = head data[nnz] = sums[head] nnz += 1 temp = head head = next_[head] next_[temp] = -1 sums[temp] = 0 return coords, data return _dot_coo_coo @_memoize_dtype def _dot_coo_ndarray_type(dt1, dt2): dtr = _dot_dtype(dt1, dt2) @numba.jit(nopython=True, nogil=True) def _dot_coo_ndarray(coords1, data1, array2, out_shape): # pragma: no cover """ Utility function taking in one `COO` and one ``ndarray`` and calculating a "sense" of their dot product. Acually computes ``s1 @ x2.T``. Parameters ---------- data1, coords1 : np.ndarray The data and coordinates of ``s1``. array2 : np.ndarray The second input array ``x2``. out_shape : Tuple[int] The output shape. """ out = np.zeros(out_shape, dtype=dtr) didx1 = 0 while didx1 < len(data1): oidx1 = coords1[0, didx1] didx1_curr = didx1 for oidx2 in range(out_shape[1]): didx1 = didx1_curr while didx1 < len(data1) and coords1[0, didx1] == oidx1: out[oidx1, oidx2] += data1[didx1] * array2[oidx2, coords1[1, didx1]] didx1 += 1 return out return _dot_coo_ndarray @_memoize_dtype def _dot_coo_ndarray_type_sparse(dt1, dt2): dtr = _dot_dtype(dt1, dt2) @numba.jit( nopython=True, nogil=True, locals={"data_curr": numba.np.numpy_support.from_dtype(dtr)}, ) def _dot_coo_ndarray(coords1, data1, array2, out_shape): # pragma: no cover """ Utility function taking in one `COO` and one ``ndarray`` and calculating a "sense" of their dot product. Acually computes ``s1 @ x2.T``. Parameters ---------- data1, coords1 : np.ndarray The data and coordinates of ``s1``. array2 : np.ndarray The second input array ``x2``. out_shape : Tuple[int] The output shape. """ out_data = [] out_coords = [] # coords1.shape = (2, len(data1)) # coords1[0, :] = rows, sorted # coords1[1, :] = columns didx1 = 0 while didx1 < len(data1): current_row = coords1[0, didx1] cur_didx1 = didx1 oidx2 = 0 while oidx2 < out_shape[1]: cur_didx1 = didx1 data_curr = 0 while cur_didx1 < len(data1) and coords1[0, cur_didx1] == current_row: data_curr += data1[cur_didx1] * array2[oidx2, coords1[1, cur_didx1]] cur_didx1 += 1 if data_curr != 0: out_data.append(data_curr) out_coords.append((current_row, oidx2)) oidx2 += 1 didx1 = cur_didx1 if len(out_data) == 0: return np.empty((2, 0), dtype=np.intp), np.empty((0,), dtype=dtr) return np.array(out_coords).T, np.array(out_data) return _dot_coo_ndarray @_memoize_dtype def _dot_ndarray_coo_type(dt1, dt2): dtr = _dot_dtype(dt1, dt2) @numba.jit(nopython=True, nogil=True) def _dot_ndarray_coo(array1, coords2, data2, out_shape): # pragma: no cover """ Utility function taking in two one ``ndarray`` and one ``COO`` and calculating a "sense" of their dot product. Acually computes ``x1 @ s2.T``. Parameters ---------- array1 : np.ndarray The input array ``x1``. data2, coords2 : np.ndarray The data and coordinates of ``s2``. out_shape : Tuple[int] The output shape. """ out = np.zeros(out_shape, dtype=dtr) for oidx1 in range(out_shape[0]): for didx2 in range(len(data2)): oidx2 = coords2[1, didx2] out[oidx1, oidx2] += array1[oidx1, coords2[0, didx2]] * data2[didx2] return out return _dot_ndarray_coo @_memoize_dtype def _dot_ndarray_coo_type_sparse(dt1, dt2): dtr = _dot_dtype(dt1, dt2) @numba.jit( nopython=True, nogil=True, locals={"data_curr": numba.np.numpy_support.from_dtype(dtr)}, ) def _dot_ndarray_coo(array1, coords2, data2, out_shape): # pragma: no cover """ Utility function taking in two one ``ndarray`` and one ``COO`` and calculating a "sense" of their dot product. Acually computes ``x1 @ s2.T``. Parameters ---------- array1 : np.ndarray The input array ``x1``. data2, coords2 : np.ndarray The data and coordinates of ``s2``. out_shape : Tuple[int] The output shape. """ out_data = [] out_coords = [] # coords2.shape = (2, len(data2)) # coords2[0, :] = columns, sorted # coords2[1, :] = rows for oidx1 in range(out_shape[0]): data_curr = 0 current_col = 0 for didx2 in range(len(data2)): if coords2[0, didx2] != current_col: if data_curr != 0: out_data.append(data_curr) out_coords.append([oidx1, current_col]) data_curr = 0 current_col = coords2[0, didx2] data_curr += array1[oidx1, coords2[1, didx2]] * data2[didx2] if data_curr != 0: out_data.append(data_curr) out_coords.append([oidx1, current_col]) if len(out_data) == 0: return np.empty((2, 0), dtype=np.intp), np.empty((0,), dtype=dtr) return np.array(out_coords).T, np.array(out_data) return _dot_ndarray_coo # Copied from : https://github.com/numpy/numpy/blob/59fec4619403762a5d785ad83fcbde5a230416fc/numpy/core/einsumfunc.py#L523 # under BSD-3-Clause license : https://github.com/numpy/numpy/blob/v1.24.0/LICENSE.txt def _parse_einsum_input(operands): """ A copy of the numpy parse_einsum_input that does not cast the operands to numpy array. Returns ------- input_strings : str Parsed input strings output_string : str Parsed output string operands : list of array_like The operands to use in the numpy contraction Examples -------- The operand list is simplified to reduce printing: >>> rng = np.random.default_rng(42) >>> a = rng.random((4, 4)) >>> b = rng.random((4, 4, 4)) >>> _parse_einsum_input(("...a,...a->...", a, b)) # doctest: +SKIP ('za,xza', 'xz', [a, b]) >>> _parse_einsum_input((a, [Ellipsis, 0], b, [Ellipsis, 0])) # doctest: +SKIP ('za,xza', 'xz', [a, b]) """ if len(operands) == 0: raise ValueError("No input operands") if isinstance(operands[0], str): subscripts = operands[0].replace(" ", "") operands = operands[1:] # Ensure all characters are valid for s in subscripts: if s in ".,->": continue if not s.isalpha(): raise ValueError(f"Character {s} is not a valid symbol.") else: tmp_operands = list(operands) operand_list = [] subscript_list = [] for _ in range(len(operands) // 2): operand_list.append(tmp_operands.pop(0)) subscript_list.append(tmp_operands.pop(0)) output_list = tmp_operands[-1] if len(tmp_operands) else None operands = operand_list subscripts = "" last = len(subscript_list) - 1 for num, sub in enumerate(subscript_list): for s in sub: if s is Ellipsis: subscripts += "..." else: try: s = index(s) except TypeError as e: raise TypeError("For this input type lists must contain either int or Ellipsis") from e subscripts += _EINSUM_SYMBOLS[s] if num != last: subscripts += "," if output_list is not None: subscripts += "->" for s in output_list: if s is Ellipsis: subscripts += "..." else: try: s = index(s) except TypeError as e: raise TypeError("For this input type lists must contain either int or Ellipsis") from e subscripts += _EINSUM_SYMBOLS[s] # Check for proper "->" if ("-" in subscripts) or (">" in subscripts): invalid = (subscripts.count("-") > 1) or (subscripts.count(">") > 1) if invalid or (subscripts.count("->") != 1): raise ValueError("Subscripts can only contain one '->'.") # Parse ellipses if "." in subscripts: used = subscripts.replace(".", "").replace(",", "").replace("->", "") unused = list(_EINSUM_SYMBOLS_SET - set(used)) ellipse_inds = "".join(unused) longest = 0 if "->" in subscripts: input_tmp, output_sub = subscripts.split("->") split_subscripts = input_tmp.split(",") out_sub = True else: split_subscripts = subscripts.split(",") out_sub = False for num, sub in enumerate(split_subscripts): if "." in sub: if (sub.count(".") != 3) or (sub.count("...") != 1): raise ValueError("Invalid Ellipses.") # Take into account numerical values if operands[num].shape == (): ellipse_count = 0 else: ellipse_count = builtins.max(operands[num].ndim, 1) ellipse_count -= len(sub) - 3 if ellipse_count > longest: longest = ellipse_count if ellipse_count < 0: raise ValueError("Ellipses lengths do not match.") if ellipse_count == 0: split_subscripts[num] = sub.replace("...", "") else: rep_inds = ellipse_inds[-ellipse_count:] split_subscripts[num] = sub.replace("...", rep_inds) subscripts = ",".join(split_subscripts) out_ellipse = "" if longest == 0 else ellipse_inds[-longest:] if out_sub: subscripts += "->" + output_sub.replace("...", out_ellipse) else: # Special care for outputless ellipses output_subscript = "" tmp_subscripts = subscripts.replace(",", "") for s in sorted(set(tmp_subscripts)): if not s.isalpha(): raise ValueError(f"Character {s} is not a valid symbol.") if tmp_subscripts.count(s) == 1: output_subscript += s normal_inds = "".join(sorted(set(output_subscript) - set(out_ellipse))) subscripts += "->" + out_ellipse + normal_inds # Build output string if does not exist if "->" in subscripts: input_subscripts, output_subscript = subscripts.split("->") else: input_subscripts = subscripts # Build output subscripts tmp_subscripts = subscripts.replace(",", "") output_subscript = "" for s in sorted(set(tmp_subscripts)): if not s.isalpha(): raise ValueError(f"Character {s} is not a valid symbol.") if tmp_subscripts.count(s) == 1: output_subscript += s # Make sure output subscripts are in the input for char in output_subscript: if char not in input_subscripts: raise ValueError(f"Output character {char} did not appear in the input") # Make sure number operands is equivalent to the number of terms if len(input_subscripts.split(",")) != len(operands): raise ValueError("Number of einsum subscripts must be equal to the number of operands.") return (input_subscripts, output_subscript, operands) def _einsum_single(lhs, rhs, operand): """Perform a single term einsum, i.e. any combination of transposes, sums and traces of dimensions. Parameters ---------- lhs : str The indices of the input array. rhs : str The indices of the output array. operand : SparseArray The array to perform the einsum on. Returns ------- output : SparseArray """ from ._coo import COO if lhs == rhs: if not rhs: # ensure scalar output return operand.sum() return operand if not isinstance(operand, SparseArray): # just use numpy for dense input return np.einsum(f"{lhs}->{rhs}", operand) # else require COO for operations, but check if should convert back to_output_format = getattr(operand, "from_coo", lambda x: x) operand = as_coo(operand) # check if repeated / 'trace' indices mean we are only taking a subset where = {} for i, ix in enumerate(lhs): where.setdefault(ix, []).append(i) selector = None for locs in where.values(): loc0, *rlocs = locs if rlocs: # repeated index if len({operand.shape[loc] for loc in locs}) > 1: raise ValueError("Repeated indices must have the same dimension.") # only select data where all indices match subselector = (operand.coords[loc0] == operand.coords[rlocs]).all(axis=0) if selector is None: selector = subselector else: selector &= subselector # indices that are removed (i.e. not in the output / `perm`) # are handled by `has_duplicates=True` below perm = [lhs.index(ix) for ix in rhs] new_shape = tuple(operand.shape[i] for i in perm) # select the new COO data if selector is not None: new_coords = operand.coords[:, selector][perm] new_data = operand.data[selector] else: new_coords = operand.coords[perm] new_data = operand.data if not rhs: # scalar output - match numpy behaviour by not wrapping as array return new_data.sum() return to_output_format(COO(new_coords, new_data, shape=new_shape, has_duplicates=True)) def einsum(*operands, **kwargs): """ Perform the equivalent of [`numpy.einsum`][]. Parameters ---------- subscripts : str Specifies the subscripts for summation as comma separated list of subscript labels. An implicit (classical Einstein summation) calculation is performed unless the explicit indicator '->' is included as well as subscript labels of the precise output form. operands : sequence of SparseArray These are the arrays for the operation. dtype : data-type, optional If provided, forces the calculation to use the data type specified. Default is `None`. **kwargs : dict, optional Any additional arguments to pass to the function. Returns ------- output : SparseArray The calculation based on the Einstein summation convention. """ lhs, rhs, operands = _parse_einsum_input(operands) # Parse input check_zero_fill_value(*operands) if "dtype" in kwargs and kwargs["dtype"] is not None: operands = [o.astype(kwargs["dtype"]) for o in operands] if len(operands) == 1: return _einsum_single(lhs, rhs, operands[0]) # if multiple arrays: align, broadcast multiply and then use single einsum # for example: # "aab,cbd->dac" # we first perform single term reductions and align: # aab -> ab.. # cbd -> .bcd # (where dots represent broadcastable size 1 dimensions), then multiply all # to form the 'minimal outer product' and do a final single term einsum: # abcd -> dac # get ordered union of indices from all terms, indicies that only appear # on a single term will be removed in the 'preparation' step below terms = lhs.split(",") total = {} sizes = {} for t, term in enumerate(terms): shape = operands[t].shape for ix, d in zip(term, shape, strict=False): if d != sizes.setdefault(ix, d): raise ValueError(f"Inconsistent shape for index '{ix}'.") total.setdefault(ix, set()).add(t) for ix in rhs: total[ix].add(-1) aligned_term = "".join(ix for ix, apps in total.items() if len(apps) > 1) # NB: if every index appears exactly twice, # we could identify and dispatch to tensordot here? parrays = [] for term, array in zip(terms, operands, strict=True): # calc the target indices for this term pterm = "".join(ix for ix in aligned_term if ix in term) if pterm != term: # perform necessary transpose and reductions array = _einsum_single(term, pterm, array) # calc broadcastable shape shape = tuple(array.shape[pterm.index(ix)] if ix in pterm else 1 for ix in aligned_term) parrays.append(array.reshape(shape) if array.shape != shape else array) aligned_array = reduce(mul, parrays) return _einsum_single(aligned_term, rhs, aligned_array) def stack(arrays, axis=0, compressed_axes=None): """ Stack the input arrays along the given dimension. Parameters ---------- arrays : Iterable[SparseArray] The input arrays to stack. axis : int, optional The axis along which to stack the input arrays. compressed_axes : iterable, optional The axes to compress if returning a GCXS array. Returns ------- SparseArray The output stacked array. Raises ------ ValueError If all elements of `arrays` don't have the same fill-value. See Also -------- [`numpy.stack`][]: NumPy equivalent function """ from ._compressed import GCXS if not builtins.all(isinstance(arr, GCXS) for arr in arrays): from ._coo import stack as coo_stack return coo_stack(arrays, axis) from ._compressed import stack as gcxs_stack return gcxs_stack(arrays, axis, compressed_axes) def concatenate(arrays, axis=0, compressed_axes=None): """ Concatenate the input arrays along the given dimension. Parameters ---------- arrays : Iterable[SparseArray] The input arrays to concatenate. axis : int, optional The axis along which to concatenate the input arrays. The default is zero. compressed_axes : iterable, optional The axes to compress if returning a GCXS array. Returns ------- SparseArray The output concatenated array. Raises ------ ValueError If all elements of `arrays` don't have the same fill-value. See Also -------- [`numpy.concatenate`][] : NumPy equivalent function """ from ._compressed import GCXS if not builtins.all(isinstance(arr, GCXS) for arr in arrays): from ._coo import concatenate as coo_concat return coo_concat(arrays, axis) from ._compressed import concatenate as gcxs_concat return gcxs_concat(arrays, axis, compressed_axes) concat = concatenate @_check_device def eye(N, M=None, k=0, dtype=float, format="coo", *, device=None, **kwargs): """Return a 2-D array in the specified format with ones on the diagonal and zeros elsewhere. Parameters ---------- N : int Number of rows in the output. M : int, optional Number of columns in the output. If None, defaults to `N`. k : int, optional Index of the diagonal: 0 (the default) refers to the main diagonal, a positive value refers to an upper diagonal, and a negative value to a lower diagonal. dtype : data-type, optional Data-type of the returned array. format : str, optional A format string. Returns ------- I : SparseArray of shape (N, M) An array where all elements are equal to zero, except for the `k`-th diagonal, whose values are equal to one. Examples -------- >>> eye(2, dtype=int).todense() # doctest: +NORMALIZE_WHITESPACE array([[1, 0], [0, 1]]) >>> eye(3, k=1).todense() # doctest: +SKIP array([[0., 1., 0.], [0., 0., 1.], [0., 0., 0.]]) """ from ._coo import COO if M is None: M = N N = int(N) M = int(M) k = int(k) data_length = builtins.min(N, M) if k > 0: data_length = builtins.max(builtins.min(data_length, M - k), 0) elif k < 0: data_length = builtins.max(builtins.min(data_length, N + k), 0) if data_length == 0: return zeros((N, M), dtype=dtype, format=format, device=device) if k > 0: n_coords = np.arange(data_length, dtype=np.intp) m_coords = n_coords + k elif k < 0: m_coords = np.arange(data_length, dtype=np.intp) n_coords = m_coords - k else: n_coords = m_coords = np.arange(data_length, dtype=np.intp) coords = np.stack([n_coords, m_coords]) data = np.array(1, dtype=dtype) return COO(coords, data=data, shape=(N, M), has_duplicates=False, sorted=True).asformat(format, **kwargs) @_check_device def full(shape, fill_value, dtype=None, format="coo", order="C", *, device=None, **kwargs): """Return a SparseArray of given shape and type, filled with `fill_value`. Parameters ---------- shape : int or tuple of ints Shape of the new array, e.g., ``(2, 3)`` or ``2``. fill_value : scalar Fill value. dtype : data-type, optional The desired data-type for the array. The default, `None`, means `np.array(fill_value).dtype`. format : str, optional A format string. compressed_axes : iterable, optional The axes to compress if returning a GCXS array. order : {'C', None} Values except these are not currently supported and raise a NotImplementedError. Returns ------- out : SparseArray Array of `fill_value` with the given shape and dtype. Examples -------- >>> full(5, 9).todense() # doctest: +NORMALIZE_WHITESPACE array([9, 9, 9, 9, 9]) >>> full((2, 2), 9, dtype=float).todense() # doctest: +SKIP array([[9., 9.], [9., 9.]]) """ from sparse import COO if dtype is None: dtype = np.array(fill_value).dtype if not isinstance(shape, tuple): shape = (shape,) if order not in {"C", None}: raise NotImplementedError("Currently, only 'C' and None are supported.") data = np.empty(0, dtype=dtype) coords = np.empty((len(shape), 0), dtype=np.intp) return COO( coords, data=data, shape=shape, fill_value=fill_value, has_duplicates=False, sorted=True, ).asformat(format, **kwargs) @_check_device def full_like(a, fill_value, dtype=None, shape=None, format=None, *, device=None, **kwargs): """Return a full array with the same shape and type as a given array. Parameters ---------- a : array_like The shape and data-type of the result will match those of `a`. dtype : data-type, optional Overrides the data type of the result. format : str, optional A format string. compressed_axes : iterable, optional The axes to compress if returning a GCXS array. Returns ------- out : SparseArray Array of `fill_value` with the same shape and type as `a`. Examples -------- >>> x = np.ones((2, 3), dtype="i8") >>> full_like(x, 9.0).todense() # doctest: +NORMALIZE_WHITESPACE array([[9, 9, 9], [9, 9, 9]]) """ if format is None and not isinstance(a, np.ndarray): format = type(a).__name__.lower() elif format is None: format = "coo" compressed_axes = kwargs.pop("compressed_axes", None) if hasattr(a, "compressed_axes") and compressed_axes is None: compressed_axes = a.compressed_axes return full( a.shape if shape is None else shape, fill_value, dtype=(a.dtype if dtype is None else dtype), format=format, **kwargs, ) def zeros(shape, dtype=float, format="coo", *, device=None, **kwargs): """Return a SparseArray of given shape and type, filled with zeros. Parameters ---------- shape : int or tuple of ints Shape of the new array, e.g., ``(2, 3)`` or ``2``. dtype : data-type, optional The desired data-type for the array, e.g., `numpy.int8`. Default is `numpy.float64`. format : str, optional A format string. compressed_axes : iterable, optional The axes to compress if returning a GCXS array. Returns ------- out : SparseArray Array of zeros with the given shape and dtype. Examples -------- >>> zeros(5).todense() # doctest: +SKIP array([0., 0., 0., 0., 0.]) >>> zeros((2, 2), dtype=int).todense() # doctest: +NORMALIZE_WHITESPACE array([[0, 0], [0, 0]]) """ return full(shape, fill_value=0, dtype=np.dtype(dtype), format=format, device=device, **kwargs) def zeros_like(a, dtype=None, shape=None, format=None, *, device=None, **kwargs): """Return a SparseArray of zeros with the same shape and type as ``a``. Parameters ---------- a : array_like The shape and data-type of the result will match those of `a`. dtype : data-type, optional Overrides the data type of the result. format : str, optional A format string. compressed_axes : iterable, optional The axes to compress if returning a GCXS array. Returns ------- out : SparseArray Array of zeros with the same shape and type as `a`. Examples -------- >>> x = np.ones((2, 3), dtype="i8") >>> zeros_like(x).todense() # doctest: +NORMALIZE_WHITESPACE array([[0, 0, 0], [0, 0, 0]]) """ return full_like(a, fill_value=0, dtype=dtype, shape=shape, format=format, device=device, **kwargs) def ones(shape, dtype=float, format="coo", *, device=None, **kwargs): """Return a SparseArray of given shape and type, filled with ones. Parameters ---------- shape : int or tuple of ints Shape of the new array, e.g., ``(2, 3)`` or ``2``. dtype : data-type, optional The desired data-type for the array, e.g., `numpy.int8`. Default is `numpy.float64`. format : str, optional A format string. compressed_axes : iterable, optional The axes to compress if returning a GCXS array. Returns ------- out : SparseArray Array of ones with the given shape and dtype. Examples -------- >>> ones(5).todense() # doctest: +SKIP array([1., 1., 1., 1., 1.]) >>> ones((2, 2), dtype=int).todense() # doctest: +NORMALIZE_WHITESPACE array([[1, 1], [1, 1]]) """ return full(shape, fill_value=1, dtype=np.dtype(dtype), format=format, device=device, **kwargs) def ones_like(a, dtype=None, shape=None, format=None, *, device=None, **kwargs): """Return a SparseArray of ones with the same shape and type as ``a``. Parameters ---------- a : array_like The shape and data-type of the result will match those of `a`. dtype : data-type, optional Overrides the data type of the result. format : str, optional A format string. compressed_axes : iterable, optional The axes to compress if returning a GCXS array. Returns ------- out : SparseArray Array of ones with the same shape and type as `a`. Examples -------- >>> x = np.ones((2, 3), dtype="i8") >>> ones_like(x).todense() # doctest: +NORMALIZE_WHITESPACE array([[1, 1, 1], [1, 1, 1]]) """ return full_like(a, fill_value=1, dtype=dtype, shape=shape, format=format, device=device, **kwargs) def empty(shape, dtype=float, format="coo", *, device=None, **kwargs): return full(shape, fill_value=0, dtype=np.dtype(dtype), format=format, device=device, **kwargs) empty.__doc__ = zeros.__doc__ def empty_like(a, dtype=None, shape=None, format=None, *, device=None, **kwargs): return full_like(a, fill_value=0, dtype=dtype, shape=shape, format=format, device=device, **kwargs) empty_like.__doc__ = zeros_like.__doc__ def can_cast(from_: SparseArray, to: np.dtype, /, *, casting: str = "safe") -> bool: """Determines if one data type can be cast to another data type Parameters ---------- from_ : dtype or SparseArray Source array or dtype. to : dtype Destination dtype. casting: str Casting kind Returns ------- out : bool Whether or not a cast is possible. Examples -------- >>> x = sparse.ones((2, 3), dtype=sparse.int8) >>> sparse.can_cast(x, sparse.float64) True See Also -------- - [`numpy.can_cast`][] : NumPy equivalent function """ from_ = np.dtype(from_) return np.can_cast(from_, to, casting=casting) def outer(a, b, out=None): """ Return outer product of two sparse arrays. Parameters ---------- a, b : sparse.SparseArray The input arrays. out : sparse.SparseArray The output array. Examples -------- >>> import numpy as np >>> import sparse >>> a = sparse.COO(np.arange(4)) >>> o = sparse.outer(a, a) >>> o.todense() array([[0, 0, 0, 0], [0, 1, 2, 3], [0, 2, 4, 6], [0, 3, 6, 9]]) """ from ._coo import COO from ._sparse_array import SparseArray if isinstance(a, SparseArray): a = COO(a) if isinstance(b, SparseArray): b = COO(b) return np.multiply.outer(a.flatten(), b.flatten(), out=out) def asnumpy(a, dtype=None, order=None): """Returns a dense numpy array from an arbitrary source array. Parameters ---------- a: array_like Arbitrary object that can be converted to [`numpy.ndarray`][]. order: ({'C', 'F', 'A'}) The desired memory layout of the output array. When ``order`` is 'A', it uses 'F' if ``a`` is fortran-contiguous and 'C' otherwise. Returns ------- numpy.ndarray: Converted array on the host memory. """ from ._sparse_array import SparseArray if isinstance(a, SparseArray): a = a.todense() return np.asarray(a, dtype=dtype, order=order) # this code was taken from numpy.moveaxis # (cf. numpy/core/numeric.py, lines 1340-1409, v1.18.4) # https://github.com/numpy/numpy/blob/v1.18.4/numpy/core/numeric.py#L1340-L1409 def moveaxis(a, source, destination): """ Move axes of an array to new positions. Other axes remain in their original order. Parameters ---------- a : SparseArray The array whose axes should be reordered. source : int or List[int] Original positions of the axes to move. These must be unique. destination : int or List[int] Destination positions for each of the original axes. These must also be unique. Returns ------- SparseArray Array with moved axes. Examples -------- >>> import numpy as np >>> import sparse >>> x = sparse.COO.from_numpy(np.ones((2, 3, 4, 5))) >>> sparse.moveaxis(x, (0, 1), (2, 3)) """ if not isinstance(source, Iterable): source = (source,) if not isinstance(destination, Iterable): destination = (destination,) source = normalize_axis(source, a.ndim) destination = normalize_axis(destination, a.ndim) if len(source) != len(destination): raise ValueError("`source` and `destination` arguments must have the same number of elements") order = [n for n in range(a.ndim) if n not in source] for dest, src in sorted(zip(destination, source, strict=True)): order.insert(dest, src) return a.transpose(order) def pad(array, pad_width, mode="constant", **kwargs): """ Performs the equivalent of [`sparse.SparseArray`][]. Note that this function returns a new array instead of a view. Parameters ---------- array : SparseArray Sparse array which is to be padded. pad_width : {sequence, array_like, int} Number of values padded to the edges of each axis. ((before_1, after_1), โ€ฆ (before_N, after_N)) unique pad widths for each axis. ((before, after),) yields same before and after pad for each axis. (pad,) or int is a shortcut for before = after = pad width for all axes. mode : str Pads to a constant value which is fill value. Currently only constant mode is implemented constant_values : int The values to set the padded values for each axis. Default is 0. This must be same as fill value. Returns ------- SparseArray The padded sparse array. Raises ------ NotImplementedError If mode != 'constant' or there are unknown arguments. ValueError If constant_values != self.fill_value See Also -------- [`numpy.pad`][] : NumPy equivalent function """ if not isinstance(array, SparseArray): raise NotImplementedError("Input array is not compatible.") if mode.lower() != "constant": raise NotImplementedError(f"Mode '{mode}' is not yet supported.") if not equivalent(kwargs.pop("constant_values", _zero_of_dtype(array.dtype)), array.fill_value): raise ValueError("constant_values can only be equal to fill value.") if kwargs: raise NotImplementedError("Additional Unknown arguments present.") from ._coo import COO array = array.asformat("coo") pad_width = np.broadcast_to(pad_width, (len(array.shape), 2)) new_coords = array.coords + pad_width[:, 0:1] new_shape = tuple([array.shape[i] + pad_width[i, 0] + pad_width[i, 1] for i in range(len(array.shape))]) new_data = array.data return COO(new_coords, new_data, new_shape, fill_value=array.fill_value) def format_to_string(format): if isinstance(format, type): if not issubclass(format, SparseArray): raise ValueError(f"invalid format: {format}") format = format.__name__.lower() if isinstance(format, str): return format raise ValueError(f"invalid format: {format}") @_check_device def asarray(obj, /, *, dtype=None, format=None, copy=False, device=None): """ Convert the input to a sparse array. Parameters ---------- obj : array_like Object to be converted to an array. dtype : dtype, optional Output array data type. format : str, optional Output array sparse format. Default: existing format if the input is a `SparseArray`, else COO. device : str, optional Device on which to place the created array. copy : bool, optional Boolean indicating whether or not to copy the input. Returns ------- out : Union[SparseArray, numpy.ndarray] Sparse or 0-D array containing the data from `obj`. Examples -------- >>> x = np.eye(8, dtype="i8") >>> sparse.asarray(x, format="coo") """ if format not in {None, "coo", "dok", "gcxs", "csc", "csr"}: raise ValueError(f"{format} format not supported.") from ._compressed import CSC, CSR, GCXS from ._coo import COO from ._dok import DOK format_dict = {"coo": COO, "dok": DOK, "gcxs": GCXS, "csc": CSC, "csr": CSR} if isinstance(obj, SparseArray): return obj.asformat(format) if format is not None else obj format = "coo" if format is None else format if _is_scipy_sparse_obj(obj): sparse_obj = format_dict[format].from_scipy_sparse(obj) if dtype is None: dtype = sparse_obj.dtype return sparse_obj.astype(dtype=dtype, copy=copy) if np.isscalar(obj) or isinstance(obj, np.ndarray | Iterable): sparse_obj = format_dict[format].from_numpy(np.asarray(obj)) if dtype is None: dtype = sparse_obj.dtype return sparse_obj.astype(dtype=dtype, copy=copy) raise ValueError(f"{type(obj)} not supported.") def _support_numpy(func): """ In case a NumPy array is passed to `sparse` namespace function we want to flag it and dispatch to NumPy. """ @wraps(func) def wrapper_func(*args, **kwargs): x = args[0] if isinstance(x, np.ndarray | np.number): warnings.warn( f"Sparse {func.__name__} received dense NumPy array instead " "of sparse array. Dispatching to NumPy function.", RuntimeWarning, stacklevel=2, ) return getattr(np, func.__name__)(*args, **kwargs) return func(*args, **kwargs) return wrapper_func def all(x, /, *, axis=None, keepdims=False): """ Tests whether all input array elements evaluate to ``True`` along a specified axis. Parameters ---------- x: array input array. axis: Optional[Union[int, Tuple[int, ...]]] axis or axes along which to perform a logical AND reduction. By default, a logical AND reduction is performed over the entire array. If a tuple of integers, logical AND reductions are performed over multiple axes. A valid ``axis`` is an integer on the interval ``[-N, N)``, where ``N`` is the rank (number of dimensions) of ``x``. If an ``axis`` is specified as a negative integer, the function determines the axis along which to perform a reduction by counting backward from the last dimension (where ``-1`` refers to the last dimension). If provided an invalid ``axis``, the function raiseS an exception. Default: ``None``. keepdims: bool If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions, and, accordingly, the result is compatible with the input array. Otherwise, if ``False``, the reduced axes (dimensions) are not included in the result. Default: ``False``. Returns ------- out: array if a logical AND reduction was performed over the entire array, the returned array is a zero-dimensional array containing the test result; otherwise, the returned array is a non-zero-dimensional array containing the test results. The returned array has a data type of ``bool``. Special Cases ------------- - Positive infinity, negative infinity, and NaN evaluate to ``True``. - If ``x`` has a complex floating-point data type, elements having a non-zero component (real or imaginary) evaluate to ``True``. - If ``x`` is an empty array or the size of the axis (dimension) along which to evaluate elements is zero, the test result is ``True``. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> o = sparse.all(a, axis=1) >>> o.todense() # doctest: +NORMALIZE_WHITESPACE array([False, False]) """ return x.all(axis=axis, keepdims=keepdims) def any(x, /, *, axis=None, keepdims=False): """ Tests whether any input array element evaluates to ``True`` along a specified axis. Parameters ---------- x: array input array. axis: Optional[Union[int, Tuple[int, ...]]] axis or axes along which to perform a logical OR reduction. By default, a logical OR reduction is performed over the entire array. If a tuple of integers, logical OR reductions are performed over multiple axes. A valid ``axis`` must be an integer on the interval ``[-N, N)``, where ``N`` is the rank (number of dimensions) of ``x``. If an ``axis`` is specified as a negative integer, the function determines the axis along which to perform a reduction by counting backward from the last dimension (where ``-1`` refers to the last dimension). If provided an invalid ``axis``, the function raises an exception. Default: ``None``. keepdims: bool If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions, and, accordingly, the result must is compatible with the input array. Otherwise, if ``False``, the reduced axes (dimensions) is not included in the result. Default: ``False``. Returns ------- out: array if a logical OR reduction was performed over the entire array, the returned array is a zero-dimensional array containing the test result. Otherwise, the returned array is a non-zero-dimensional array containing the test results. The returned array is of type ``bool``. Special Cases ------------- - Positive infinity, negative infinity, and NaN evaluate to ``True``. - If ``x`` has a complex floating-point data type, elements having a non-zero component (real or imaginary) evaluate to ``True``. - If ``x`` is an empty array or the size of the axis (dimension) along which to evaluate elements is zero, the test result is ``False``. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> o = sparse.any(a, axis=1) >>> o.todense() # doctest: +NORMALIZE_WHITESPACE array([ True, True]) """ return x.any(axis=axis, keepdims=keepdims) def permute_dims(x, /, axes=None): """ Permutes the axes (dimensions) of an array ``x``. Parameters ---------- x: array input array. axes: Tuple[int, ...] tuple containing a permutation of ``(0, 1, ..., N-1)`` where ``N`` is the number of axes (dimensions) of ``x``. Returns ------- out: array an array containing the axes permutation. The returned array must have the same data type as ``x``. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> o = sparse.permute_dims(a, axes=(1, 0)) >>> o.todense() # doctest: +NORMALIZE_WHITESPACE array([[0, 2], [1, 0]]) """ return x.transpose(axes=axes) def max(x, /, *, axis=None, keepdims=False): """ Calculates the maximum value of the input array ``x``. Parameters ---------- x: array input array of a real-valued data type. axis: Optional[Union[int, Tuple[int, ...]]] axis or axes along which maximum values are computed. By default, the maximum value are computed over the entire array. If a tuple of integers, maximum values are computed over multiple axes. Default: ``None``. keepdims: bool If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions. Accordingly, the result is compatible with the input array. Otherwise, if ``False``, the reduced axes (dimensions) must not be included in the result. Default: ``False``. Returns ------- out: array if the maximum value was computed over the entire array, a zero-dimensional array containing the maximum value. Otherwise, a non-zero-dimensional array containing the maximum values. The returned array has the same data type as ``x``. Special Cases ------------- For floating-point operands, if ``x_i`` is ``NaN``, the maximum value is ``NaN`` (i.e., ``NaN`` values propagate). Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> o = sparse.max(a, axis=1) >>> o.todense() array([1, 2]) """ return x.max(axis=axis, keepdims=keepdims) def mean(x, /, *, axis=None, keepdims=False, dtype=None): """ Calculates the arithmetic mean of the input array ``x``. Parameters ---------- x: array input array of a real-valued floating-point data type. axis: Optional[Union[int, Tuple[int, ...]]] axis or axes along which arithmetic means must be computed. By default, the mean is computed over the entire array. If a tuple of integers, arithmetic means are computed over multiple axes. Default: ``None``. keepdims: bool if ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions. Accordingly, the result is compatible is the input array. Otherwise, if ``False``, the reduced axes (dimensions) are not be included in the result. Default: ``False``. Returns ------- out: array if the arithmetic mean was computed over the entire array, a zero-dimensional array with the arithmetic mean. Otherwise, a non-zero-dimensional array containing the arithmetic means. The returned array has the same data type as ``x``. Special Cases ------------- Let ``N`` equal the number of elements over which to compute the arithmetic mean. If ``N`` is ``0``, the arithmetic mean is ``NaN``. If ``x_i`` is ``NaN``, the arithmetic mean is ``NaN`` (i.e., ``NaN`` values propagate). Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> o = sparse.mean(a, axis=1) >>> o.todense() array([0.5, 1. ]) """ return x.mean(axis=axis, keepdims=keepdims, dtype=dtype) def min(x, /, *, axis=None, keepdims=False): """ Calculates the minimum value of the input array ``x``. Parameters ---------- x: array input array. Should have a real-valued data type. axis: Optional[Union[int, Tuple[int, ...]]] axis or axes along which minimum values are computed. By default, the minimum value must be computed over the entire array. If a tuple of integers, minimum values must be computed over multiple axes. Default: ``None``. keepdims: bool If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions. Accordingly, the result must be compatible with the input array. Otherwise, if ``False``, the reduced axes (dimensions) are not be included in the result. Default: ``False``. Returns ------- out: array if the minimum value was computed over the entire array, a zero-dimensional array containing the minimum value. Otherwise, a non-zero-dimensional array containing the minimum values. The returned array must have the same data type as ``x``. Special Cases ------------- For floating-point operands, if ``x_i`` is ``NaN``, the minimum value is ``NaN`` (i.e., ``NaN`` values propagate). Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, -1], [-2, 0]])) >>> o = sparse.min(a, axis=1) >>> o.todense() array([-1, -2]) """ return x.min(axis=axis, keepdims=keepdims) def prod(x, /, *, axis=None, dtype=None, keepdims=False): """ Calculates the product of input array ``x`` elements. Parameters ---------- x: array input array of a numeric data type. axis: Optional[Union[int, Tuple[int, ...]]] axis or axes along which products is computed. By default, the product are computed over the entire array. If a tuple of integers, products are computed over multiple axes. Default: ``None``. dtype: Optional[dtype] data type of the returned array. If ``None``, the returned array has the same data type as ``x``, unless ``x`` has an integer data type supporting a smaller range of values than the default integer data type (e.g., ``x`` has an ``int16`` or ``uint32`` data type and the default integer data type is ``int64``). In those latter cases: - if ``x`` has a signed integer data type (e.g., ``int16``), the returned array has the default integer data type. - if ``x`` has an unsigned integer data type (e.g., ``uint16``), the returned array has an unsigned integer data type having the same number of bits as the default integer data type (e.g., if the default integer data type is ``int32``, the returned array must have a ``uint32`` data type). If the data type (either specified or resolved) differs from the data type of ``x``, the input array is cast to the specified data type before computing the sum (rationale: the ``dtype`` keyword argument is intended to help prevent overflows). Default: ``None``. keepdims: bool if ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions. Accordingly, the result are compatible with the input array. Otherwise, if ``False``, the reduced axes (dimensions) are not included in the result. Default: ``False``. Returns ------- out: array if the product was computed over the entire array, a zero-dimensional array containing the product. Otherwise, a non-zero-dimensional array containing the products. The returned array has a data type as described by the ``dtype`` parameter above. Notes ----- Special Cases ------------- Let ``N`` equal the number of elements over which to compute the product. - If ``N`` is ``0``, the product is `1` (i.e., the empty product). Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 2], [-1, 1]])) >>> o = sparse.prod(a, axis=1) >>> o.todense() array([ 0, -1]) """ return x.prod(axis=axis, keepdims=keepdims, dtype=dtype) def std(x, /, *, axis=None, correction=0.0, keepdims=False): """ Calculates the standard deviation of the input array ``x``. Parameters ---------- x: array input array of a real-valued floating-point data type. axis: Optional[Union[int, Tuple[int, ...]]] axis or axes along which standard deviations are computed. By default, the standard deviation is computed over the entire array. If a tuple of integers, standard deviations are computed over multiple axes. Default: ``None``. correction: Union[int, float] degrees of freedom adjustment. Setting this parameter to a value other than ``0`` has the effect of adjusting the divisor during the calculation of the standard deviation according to ``N-c`` where ``N`` corresponds to the total number of elements over which the standard deviation is computed and ``c`` corresponds to the provided degrees of freedom adjustment. When computing the standard deviation of a population, setting this parameter to ``0`` is the standard choice (i.e., the provided array contains data constituting an entire population). When computing the corrected sample standard deviation, setting this parameter to ``1`` is the standard choice (i.e., the provided array contains data sampled from a larger population; this is commonly referred to as Bessel's correction). Default: ``0``. keepdims: bool if ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions, and, accordingly, the result must be compatible with the input array. Otherwise, if ``False``, the reduced axes (dimensions) must not be included in the result. Default: ``False``. Returns ------- out: array if the standard deviation was computed over the entire array, a zero-dimensional array containing the standard deviation; otherwise, a non-zero-dimensional array containing the standard deviations. The returned array has the same data type as ``x``. Special Cases ------------- Let ``N`` equal the number of elements over which to compute the standard deviation. - If ``N - correction`` is less than or equal to ``0``, the standard deviation is ``NaN``. - If ``x_i`` is ``NaN``, the standard deviation is ``NaN`` (i.e., ``NaN`` values propagate). Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 2], [-1, 1]])) >>> o = sparse.std(a, axis=1) >>> o.todense() array([1., 1.]) """ return x.std(axis=axis, ddof=correction, keepdims=keepdims) def sum(x, /, *, axis=None, dtype=None, keepdims=False): """ Calculates the sum of the input array ``x``. Parameters ---------- x: array input array of a numeric data type. axis: Optional[Union[int, Tuple[int, ...]]] axis or axes along which sums are computed. By default, the sum is computed over the entire array. If a tuple of integers, sums must are computed over multiple axes. Default: ``None``. dtype: Optional[dtype] data type of the returned array. If ``None``, the returned array has the same data type as ``x``, unless ``x`` has an integer data type supporting a smaller range of values than the default integer data type (e.g., ``x`` has an ``int16`` or ``uint32`` data type and the default integer data type is ``int64``). In those latter cases: - if ``x`` has a signed integer data type (e.g., ``int16``), the returned array has the default integer data type. - if ``x`` has an unsigned integer data type (e.g., ``uint16``), the returned array has an unsigned integer data type having the same number of bits as the default integer data type (e.g., if the default integer data type is ``int32``, the returned array must have a ``uint32`` data type). If the data type (either specified or resolved) differs from the data type of ``x``, the input array is cast to the specified data type before computing the sum. Rationale: the ``dtype`` keyword argument is intended to help prevent overflows. Default: ``None``. keepdims: bool If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions. Accordingly, the result is compatible with the input array. Otherwise, if ``False``, the reduced axes (dimensions) are not included in the result. Default: ``False``. Returns ------- out: array if the sum was computed over the entire array, a zero-dimensional array containing the sum. Otherwise, an array containing the sums. The returned array has the data type as described by the ``dtype`` parameter above. Special Cases ------------- Let ``N`` equal the number of elements over which to compute the sum. - If ``N`` is ``0``, the sum is ``0`` (i.e., the empty sum). Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> o = sparse.sum(a, axis=1) >>> o.todense() array([1, 2]) """ return x.sum(axis=axis, keepdims=keepdims, dtype=dtype) def var(x, /, *, axis=None, correction=0.0, keepdims=False): """ Calculates the variance of the input array ``x``. Parameters ---------- x: array input array of a real-valued floating-point data type. axis: Optional[Union[int, Tuple[int, ...]]] axis or axes along which variances are computed. By default, the variance is computed over the entire array. If a tuple of integers, variances are computed over multiple axes. Default: ``None``. correction: Union[int, float] degrees of freedom adjustment. Setting this parameter to a value other than ``0`` has the effect of adjusting the divisor during the calculation of the variance according to ``N-c`` where ``N`` corresponds to the total number of elements over which the variance is computed and ``c`` corresponds to the provided degrees of freedom adjustment. When computing the variance of a population, setting this parameter to ``0`` is the standard choice (i.e., the provided array contains data constituting an entire population). When computing the unbiased sample variance, setting this parameter to ``1`` is the standard choice (i.e., the provided array contains data sampled from a larger population; this is commonly referred to as Bessel's correction). Default: ``0``. keepdims: bool if ``True``, the reduced axes are included in the result as singleton dimensions, and, accordingly, the result is compatible with the input array. Otherwise, if ``False``, the reduced axes (dimensions) are not included in the result. Default: ``False``. Returns ------- out: array if the variance was computed over the entire array, a zero-dimensional array containing the variance; otherwise, a non-zero-dimensional array containing the variances. The returned array must have the same data type as ``x``. Special Cases ------------- Let ``N`` equal the number of elements over which to compute the variance. - If ``N - correction`` is less than or equal to ``0``, the variance is ``NaN``. - If ``x_i`` is ``NaN``, the variance is ``NaN`` (i.e., ``NaN`` values propagate). Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 2], [-1, 1]])) >>> o = sparse.var(a, axis=1) >>> o.todense() array([1., 1.]) """ return x.var(axis=axis, ddof=correction, keepdims=keepdims) def abs(x, /): """ Calculates the absolute value for each element ``x_i`` of the input array ``x``. For real-valued input arrays, the element-wise result has the same magnitude as the respective element in ``x`` but has positive sign. For complex floating-point operands, the complex absolute value is known as the norm, modulus, or magnitude and, for a complex number :math:`z = a + bj` is computed as $$ operatorname{abs}(z) = sqrt{a^2 + b^2} $$ Parameters ---------- x: array input array of a numeric data type. Returns ------- out: array an array containing the absolute value of each element in ``x``. If ``x`` has a real-valued data type, the returned array has the same data type as ``x``. If ``x`` has a complex floating-point data type, the returned array has a real-valued floating-point data type whose precision matches the precision of ``x`` (e.g., if ``x`` is ``complex128``, then the returned array must has a ``float64`` data type). Special Cases ------------- For real-valued floating-point operands, - If ``x_i`` is ``NaN``, the result is ``NaN``. - If ``x_i`` is ``-0``, the result is ``+0``. - If ``x_i`` is ``-infinity``, the result is ``+infinity``. For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is any value (including ``NaN``), the result is ``+infinity``. - If ``a`` is any value (including ``NaN``) and ``b`` is either ``+infinity`` or ``-infinity``, the result is ``+infinity``. - If ``a`` is either ``+0`` or ``-0``, the result is equal to ``abs(b)``. - If ``b`` is either ``+0`` or ``-0``, the result is equal to ``abs(a)``. - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN``. - If ``a`` is a finite number and ``b`` is ``NaN``, the result is ``NaN``. - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN``. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, -1], [-2, 0]])) >>> o = sparse.abs(a) >>> o.todense() array([[0, 1], [2, 0]]) """ return x.__abs__() def reshape(x, /, shape, *, copy=None): """ Reshapes an array without changing its data. Parameters ---------- x: array input array to reshape. shape: Tuple[int, ...] a new shape compatible with the original shape. One shape dimension is allowed to be ``-1``. When a shape dimension is ``-1``, the corresponding output array shape dimension must be inferred from the length of the array and the remaining dimensions. copy: Optional[bool] whether or not to copy the input array. If ``True``, the function always copies. If ``False``, the function must never copies. If ``None``, the function avoids copying, if possible. Default: ``None``. Returns ------- out: array an output array having the same data type and elements as ``x``. Raises ------ ValueError If ``copy=False`` and a copy would be necessary, a ``ValueError`` will be raised. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> o = sparse.reshape(a, shape=(1, 4)) >>> o.todense() array([[0, 1, 2, 0]]) """ return x.reshape(shape=shape) @_check_device def astype(x, dtype, /, *, copy=True, device=None): """ Copies an array to a specified data type irrespective of type-promotion rules. Parameters ---------- x: array array to cast. dtype: dtype desired data type. copy: bool specifies whether to copy an array when the specified ``dtype`` matches the data type of the input array ``x``. If ``True``, a newly allocated array is always returned. If ``False`` and the specified ``dtype`` matches the data type of the input array, the input array is returned; otherwise, a newly allocated array is returned. Default: ``True``. Notes ----- - When casting a boolean input array to a real-valued data type, a value of ``True`` is cast to a real-valued number equal to ``1``, and a value of ``False`` must cast to a real-valued number equal to ``0``. - When casting a boolean input array to a complex floating-point data type, a value of ``True`` is cast to a complex number equal to ``1 + 0j``, and a value of ``False`` is cast to a complex number equal to ``0 + 0j``. - When casting a real-valued input array to ``bool``, a value of ``0`` is cast to ``False``, and a non-zero value is cast to ``True``. - When casting a complex floating-point array to ``bool``, a value of ``0 + 0j`` is cast to ``False``, and all other values are cast to ``True``. Returns ------- out: array an array having the specified data type. The returned array has the same shape as ``x``. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> o = sparse.astype(a, "float32") >>> o.todense() # doctest: +NORMALIZE_WHITESPACE array([[0., 1.], [2., 0.]], dtype=float32) """ return x.astype(dtype, copy=copy) @_support_numpy def squeeze(x, /, axis=None): """Remove singleton dimensions from array. Parameters ---------- x : SparseArray Input array. axis : int or tuple[int, ...], optional The singleton axes to remove. By default all singleton axes are removed. Returns ------- output : SparseArray Array with singleton dimensions removed. """ return x.squeeze(axis=axis) @_support_numpy def broadcast_to(x, /, shape): """ Broadcasts an array to a specified shape. Parameters ---------- x: array array to broadcast. shape: Tuple[int, ...] array shape. Must be compatible with ``x``. If the array is incompatible with the specified shape, the function raises an exception. Returns ------- out: array an array having a specified shape and having the same data type as ``x``. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> o = sparse.broadcast_to(a, shape=(1, 2, 2)) >>> o.todense() # doctest: +NORMALIZE_WHITESPACE array([[[0, 1], [2, 0]]]) """ return x.broadcast_to(shape) def broadcast_arrays(*arrays): """ Broadcasts one or more arrays against one another. Parameters ---------- arrays: array an arbitrary number of to-be broadcasted arrays. Returns ------- out: List[array] a list of broadcasted arrays. Each array has the same shape. Each array has the same dtype as its corresponding input array. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1]])) >>> b = sparse.COO.from_numpy(np.array([[0], [2]])) >>> oa, ob = sparse.broadcast_arrays(a, b) >>> oa.todense() # doctest: +NORMALIZE_WHITESPACE array([[0, 1], [0, 1]]) >>> ob.todense() # doctest: +NORMALIZE_WHITESPACE array([[0, 0], [2, 2]]) """ shape = np.broadcast_shapes(*[a.shape for a in arrays]) return [a.broadcast_to(shape) for a in arrays] def equal(x1, x2, /): """ Computes the truth value of ``x1_i == x2_i`` for each element ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input array ``x2``. Parameters ---------- x1: array first input array. May have any data type. x2: array second input array. Must be compatible with ``x1``. May have any data type. Returns ------- out: array an array containing the element-wise results. The returned array is of data type of ``bool``. Special Cases ------------- For real-valued floating-point operands, - If ``x1_i`` is ``NaN`` or ``x2_i`` is ``NaN``, the result is ``False``. - If ``x1_i`` is ``+infinity`` and ``x2_i`` is ``+infinity``, the result is ``True``. - If ``x1_i`` is ``-infinity`` and ``x2_i`` is ``-infinity``, the result is ``True``. - If ``x1_i`` is ``-0`` and ``x2_i`` is either ``+0`` or ``-0``, the result is ``True``. - If ``x1_i`` is ``+0`` and ``x2_i`` is either ``+0`` or ``-0``, the result is ``True``. - If ``x1_i`` is a finite number, ``x2_i`` is a finite number, and ``x1_i`` equals ``x2_i``, the result is ``True``. - In the remaining cases, the result is ``False``. For complex floating-point operands, let ``a = real(x1_i)``, ``b = imag(x1_i)``, ``c = real(x2_i)``, ``d = imag(x2_i)``, and - If ``a``, ``b``, ``c``, or ``d`` is ``NaN``, the result is ``False``. - In the remaining cases, the result is the logical AND of the equality comparison between the real values ``a`` and ``c`` (real components) and between the real values ``b`` and ``d`` (imaginary components), as described above for real-valued floating-point operands (i.e., ``a == c AND b == d``). Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> b = sparse.COO.from_numpy(np.array([[0, 1], [1, 0]])) >>> o = sparse.equal(a, b) # doctest: +SKIP >>> o.todense() # doctest: +SKIP array([[ True, True], [ False, True]]) """ return x1 == x2 @_support_numpy def round(x, /, decimals=0, out=None): return x.round(decimals=decimals, out=out) @_support_numpy def isinf(x, /): """ Tests each element ``x_i`` of the input array ``x`` to determine if equal to positive or negative infinity. Parameters ---------- x: array input array of a numeric data type. Returns ------- out: array an array containing test results. The returned array has a data type of ``bool``. Special Cases ------------- For real-valued floating-point operands, - If ``x_i`` is either ``+infinity`` or ``-infinity``, the result is ``True``. - In the remaining cases, the result is ``False``. For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is any value (including ``NaN``), the result is ``True``. - If ``a`` is either a finite number or ``NaN`` and ``b`` is either ``+infinity`` or ``-infinity``, the result is ``True``. - In the remaining cases, the result is ``False``. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, np.inf]])) >>> o = sparse.isinf(a) # doctest: +SKIP >>> o.todense() # doctest: +SKIP array([[False, False], [False, True]]) """ return x.isinf() @_support_numpy def isnan(x, /): """ Tests each element ``x_i`` of the input array ``x`` to determine whether the element is ``NaN``. Parameters ---------- x: array input array with a numeric data type. Returns ------- out: array an array containing test results. The returned array has data type ``bool``. Notes ----- For real-valued floating-point operands, - If ``x_i`` is ``NaN``, the result is ``True``. - In the remaining cases, the result is ``False``. For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - If ``a`` or ``b`` is ``NaN``, the result is ``True``. - In the remaining cases, the result is ``False``. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, np.nan]])) >>> o = sparse.isnan(a) >>> o.todense() # doctest: +NORMALIZE_WHITESPACE array([[False, False], [False, True]]) """ return x.isnan() def nonzero(x, /): """ Returns the indices of the array elements which are non-zero. If ``x`` has a complex floating-point data type, non-zero elements are those elements having at least one component (real or imaginary) which is non-zero. If ``x`` has a boolean data type, non-zero elements are those elements which are equal to ``True``. Parameters ---------- x: array input array having a positive rank. If ``x`` is zero-dimensional, the function raises an exception. Returns ------- out: Tuple[array, ...] a tuple of ``k`` arrays, one for each dimension of ``x`` and each of size ``n`` (where ``n`` is the total number of non-zero elements), containing the indices of the non-zero elements in that dimension. The indices must are returned in row-major, C-style order. Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) >>> o = sparse.nonzero(a) >>> o (array([0, 1]), array([1, 0])) """ return x.nonzero() def imag(x, /): """ Returns the imaginary component of a complex number for each element ``x_i`` of the input array ``x``. Parameters ---------- x: array input array of a complex floating-point data type. Returns ------- out: array an array containing the element-wise results. The returned array has a floating-point data type with the same floating-point precision as ``x`` (e.g., if ``x`` is ``complex64``, the returned array has the floating-point data type ``float32``). Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0 + 1j, 2 + 0j], [0 + 0j, 3 + 1j]])) >>> o = sparse.imag(a) >>> o.todense() # doctest: +NORMALIZE_WHITESPACE array([[1., 0.], [0., 1.]]) """ return x.imag def real(x, /): """ Returns the real component of a complex number for each element ``x_i`` of the input array ``x``. Parameters ---------- x: array input array of a complex floating-point data type. Returns ------- out: array an array containing the element-wise results. The returned array has a floating-point data type with the same floating-point precision as ``x`` (e.g., if ``x`` is ``complex64``, the returned array has the floating-point data type ``float32``). Examples -------- >>> a = sparse.COO.from_numpy(np.array([[0 + 1j, 2 + 0j], [0 + 0j, 3 + 1j]])) >>> o = sparse.real(a) >>> o.todense() # doctest: +NORMALIZE_WHITESPACE array([[0., 2.], [0., 3.]]) """ return x.real def vecdot(x1, x2, /, *, axis=-1): """ Computes the (vector) dot product of two arrays. Parameters ---------- x1, x2 : array_like Input sparse arrays axis : int The axis to reduce over. Returns ------- out : Union[SparseArray, numpy.ndarray] Sparse or 0-D array containing dot product. """ ndmin = builtins.min((x1.ndim, x2.ndim)) if not (-ndmin <= axis < ndmin) or x1.shape[axis] != x2.shape[axis]: raise ValueError("Shapes must match along `axis`.") if np.issubdtype(x1.dtype, np.complexfloating): x1 = np.conjugate(x1) return np.sum(x1 * x2, axis=axis, dtype=np.result_type(x1, x2)) def repeat(a, repeats, axis=None): """ Repeat each element of an array after themselves Parameters ---------- a : SparseArray Input sparse arrays repeats : int The number of repetitions for each element. (Uneven repeats are not yet Implemented.) axis : int, optional The axis along which to repeat values. Returns a flattened sparse array if not specified. Returns ------- out : SparseArray A sparse array which has the same shape as a, except along the given axis. """ if not isinstance(a, SparseArray): raise TypeError("`a` must be a SparseArray.") if not isinstance(repeats, int): raise ValueError("`repeats` must be an integer, uneven repeats are not yet Implemented.") axes = list(range(a.ndim)) new_shape = list(a.shape) axis_is_none = False if axis is None: a = a.reshape(-1) axis = 0 axis_is_none = True if axis < 0: axis = a.ndim + axis axes[a.ndim - 1], axes[axis] = axes[axis], axes[a.ndim - 1] new_shape[axis] *= repeats a = expand_dims(a, axis=axis + 1) shape_to_broadcast = a.shape[: axis + 1] + (a.shape[axis + 1] * repeats,) + a.shape[axis + 2 :] a = broadcast_to(a, shape_to_broadcast) if not axis_is_none: return a.reshape(new_shape) return a.reshape(new_shape).flatten() def tile(a, reps): """ Constructs an array by tiling an input array. Parameters ---------- a : SparseArray Input sparse arrays. reps : int or tuple[int, ...] The number of repetitions for each dimension. If an integer, the same number of repetitions is applied to all dimensions. Returns ------- out : SparseArray A tiled output array. """ if not isinstance(a, SparseArray): a = as_coo(a) if isinstance(reps, int): reps = (reps,) reps = tuple(reps) if a.ndim == 0: a = a.reshape((1,)) if len(reps) < a.ndim: reps = (1,) * (a.ndim - len(reps)) + reps elif len(reps) > a.ndim: a = a.reshape((1,) * (len(reps) - a.ndim) + a.shape) shape = a.shape ndim = len(reps) a = a.reshape(tuple(np.column_stack(([1] * ndim, shape)).reshape(-1))) a = a.broadcast_to(tuple(np.column_stack((reps, shape)).reshape(-1))) return a.reshape(tuple(np.multiply(reps, shape))) def unstack(x, axis=0): """ Splits an array into a sequence of arrays along the given axis. Parameters ---------- x : SparseArray Input sparse arrays. axis : int Axis along which the array will be split Returns ------- out : Tuple[SparseArray,...] Tuple of slices along the given dimension. All the arrays have the same shape. """ ndim = x.ndim if not (-ndim <= axis < ndim): raise ValueError(f"axis must be in range [-{ndim}, {ndim}), got {axis}") if not isinstance(x, SparseArray): raise TypeError("`a` must be a SparseArray.") if axis < 0: axis = ndim + axis new_order = (axis,) + tuple(i for i in range(ndim) if i != axis) x = x.transpose(new_order) return (*x,) def diff(x, axis=-1, n=1, prepend=None, append=None): """ Calculates the n-th discrete difference along the given axis. Parameters ---------- x : SparseArray Input sparse arrays. n : int The number of times values are differenced. Default: 1. axis : int The axis along which the difference is taken. Default: -1. Returns ------- out : SparseArray An array containing the n-th discrete difference along the given axis. """ if not isinstance(x, SparseArray): raise TypeError("`x` must be a SparseArray.") if axis < 0: axis = x.ndim + axis if prepend is not None: x = concatenate([prepend, x], axis=axis) if append is not None: x = concatenate([x, append], axis=axis) result = x for _ in range(n): result = result[(slice(None),) * axis + (slice(1, None),)] - result[(slice(None),) * axis + (slice(None, -1),)] return result def interp(x, xp, fp, left=None, right=None, period=None): """ An implementation of ``numpy.interp`` for sparse arrays. Thanks to the function dispatch of numpy, this enables interpolation on sparse arrays using the numpy universal function. This function effectively wraps ``np.interp`` by calling it on the array data and the fill value. See the numpy documentation for details on the parameters. Parameters ---------- x : SparseArray The x-coordinates at which to evaluate the interpolated values. xp : 1-D sequence or SparseArray The x-coordinates of the data points. fp : 1-D sequence or SparseArray The y-coordinates of the data points, same length as ``xp``. left : float or complex, optional Value to return for ``x < xp[0]``, default is ``fp[0]``. right : float or complex, optional Value to return for ``x > xp[-1]``, default is ``fp[-1]``. period : None or float, optional A period for the x-coordinates. Returns ------- out : SparseArray The interpolated values, same shape as x. See Also -------- https://numpy.org/doc/stable/reference/generated/numpy.interp.html Examples -------- When interpolating a sparse array, its data and the fill value are interpolated. The returned array is pruned. Therefore, the fill value and the number of nonzero elements might change. >>> import numpy as np >>> xp = [1, 2, 3] >>> fp = [3, 2, 0] >>> y = np.interp(sparse.COO.from_numpy(np.array([0, 1, 1.5, 2.72, 3.14])), xp, fp) >>> y.todense() array([3. , 3. , 2.5 , 0.56, 0. ]) >>> y.fill_value np.float64(3.0) >>> y.nnz 3 """ from ._compressed import GCXS from ._coo import COO from ._dok import DOK # Densify sparse interpolants if isinstance(xp, SparseArray): xp = xp.todense() if isinstance(fp, SparseArray): fp = fp.todense() def interp_func(xx): return np.interp(xx, xp, fp, left=left, right=right, period=period) # Shortcut for dense arrays if not isinstance(x, SparseArray): return interp_func(x) # Define output type out_kwargs = {} out_type = COO if isinstance(x, GCXS): out_type = GCXS out_kwargs["compressed_axes"] = x.compressed_axes elif isinstance(x, DOK): out_type = DOK # Perform interpolation on sparse object arr = as_coo(x) data = interp_func(arr.data) fill_value = interp_func(arr.fill_value) return COO(data=data, coords=arr.coords, shape=arr.shape, fill_value=fill_value, prune=True).asformat( out_type, **out_kwargs ) sparse-0.18.0/sparse/numba_backend/_compressed/000077500000000000000000000000001514474157100214575ustar00rootroot00000000000000sparse-0.18.0/sparse/numba_backend/_compressed/__init__.py000066400000000000000000000002101514474157100235610ustar00rootroot00000000000000from .common import concatenate, stack from .compressed import CSC, CSR, GCXS __all__ = ["GCXS", "CSR", "CSC", "concatenate", "stack"] sparse-0.18.0/sparse/numba_backend/_compressed/common.py000066400000000000000000000073111514474157100233230ustar00rootroot00000000000000import numpy as np from .._utils import can_store, check_consistent_fill_value, normalize_axis def concatenate(arrays, axis=0, compressed_axes=None): from .compressed import GCXS check_consistent_fill_value(arrays) arrays = [arr if isinstance(arr, GCXS) else GCXS(arr, compressed_axes=(axis,)) for arr in arrays] axis = normalize_axis(axis, arrays[0].ndim) dim = sum(x.shape[axis] for x in arrays) shape = list(arrays[0].shape) shape[axis] = dim assert all(x.shape[ax] == arrays[0].shape[ax] for x in arrays for ax in set(range(arrays[0].ndim)) - {axis}) if compressed_axes is None: compressed_axes = (axis,) if arrays[0].ndim == 1: from .._coo.common import concatenate as coo_concat arrays = [arr.tocoo() for arr in arrays] return coo_concat(arrays, axis=axis) # arrays may have different compressed_axes # concatenating becomes easy when compressed_axes are the same arrays = [arr.change_compressed_axes((axis,)) for arr in arrays] ptr_list = [] for i, arr in enumerate(arrays): if i == 0: ptr_list.append(arr.indptr) continue ptr_list.append(arr.indptr[1:]) indptr = np.concatenate(ptr_list) indices = np.concatenate([arr.indices for arr in arrays]) data = np.concatenate([arr.data for arr in arrays]) ptr_len = arrays[0].indptr.shape[0] nnz = arrays[0].nnz total_nnz = sum(int(arr.nnz) for arr in arrays) if not can_store(indptr.dtype, total_nnz): indptr = indptr.astype(np.min_scalar_type(total_nnz)) for i in range(1, len(arrays)): indptr[ptr_len:] += nnz nnz = arrays[i].nnz ptr_len += arrays[i].indptr.shape[0] - 1 return GCXS( (data, indices, indptr), shape=tuple(shape), compressed_axes=arrays[0].compressed_axes, fill_value=arrays[0].fill_value, ).change_compressed_axes(compressed_axes) def stack(arrays, axis=0, compressed_axes=None): from .compressed import GCXS check_consistent_fill_value(arrays) arrays = [arr if isinstance(arr, GCXS) else GCXS(arr, compressed_axes=(axis,)) for arr in arrays] axis = normalize_axis(axis, arrays[0].ndim + 1) assert all(x.shape[ax] == arrays[0].shape[ax] for x in arrays for ax in set(range(arrays[0].ndim)) - {axis}) if compressed_axes is None: compressed_axes = (axis,) if arrays[0].ndim == 1: from .._coo.common import stack as coo_stack arrays = [arr.tocoo() for arr in arrays] return coo_stack(arrays, axis=axis) # arrays may have different compressed_axes # stacking becomes easy when compressed_axes are the same ptr_list = [] for i in range(len(arrays)): shape = list(arrays[i].shape) shape.insert(axis, 1) arrays[i] = arrays[i].reshape(shape).change_compressed_axes((axis,)) if i == 0: ptr_list.append(arrays[i].indptr) continue ptr_list.append(arrays[i].indptr[1:]) shape[axis] = len(arrays) indptr = np.concatenate(ptr_list) indices = np.concatenate([arr.indices for arr in arrays]) data = np.concatenate([arr.data for arr in arrays]) ptr_len = arrays[0].indptr.shape[0] nnz = arrays[0].nnz total_nnz = sum(int(arr.nnz) for arr in arrays) if not can_store(indptr.dtype, total_nnz): indptr = indptr.astype(np.min_scalar_type(total_nnz)) for i in range(1, len(arrays)): indptr[ptr_len:] += nnz nnz = arrays[i].nnz ptr_len += arrays[i].indptr.shape[0] - 1 return GCXS( (data, indices, indptr), shape=tuple(shape), compressed_axes=arrays[0].compressed_axes, fill_value=arrays[0].fill_value, ).change_compressed_axes(compressed_axes) sparse-0.18.0/sparse/numba_backend/_compressed/compressed.py000066400000000000000000000762151514474157100242100ustar00rootroot00000000000000import copy as _copy import operator from collections.abc import Iterable from functools import reduce from typing import Union import numpy as np from numpy.lib.mixins import NDArrayOperatorsMixin from .._coo.common import linear_loc from .._coo.core import COO from .._sparse_array import SparseArray from .._utils import ( _zero_of_dtype, can_store, check_compressed_axes, check_fill_value, equivalent, normalize_axis, ) from .convert import _1d_reshape, _transpose, uncompress_dimension from .indexing import getitem def _from_coo(x, compressed_axes=None, idx_dtype=None): if x.ndim == 0: if compressed_axes is not None: raise ValueError("no axes to compress for 0d array") return ((x.data, x.coords, []), x.shape, None, x.fill_value) if x.ndim == 1: if compressed_axes is not None: raise ValueError("no axes to compress for 1d array") return ((x.data, x.coords[0], ()), x.shape, None, x.fill_value) compressed_axes = normalize_axis(compressed_axes, x.ndim) if compressed_axes is None: # defaults to best compression ratio compressed_axes = (np.argmin(x.shape),) check_compressed_axes(x.shape, compressed_axes) axis_order = list(compressed_axes) # array location where the uncompressed dimensions start axisptr = len(compressed_axes) axis_order.extend(np.setdiff1d(np.arange(len(x.shape)), compressed_axes)) reordered_shape = tuple(x.shape[i] for i in axis_order) row_size = np.prod(reordered_shape[:axisptr]) col_size = np.prod(reordered_shape[axisptr:]) compressed_shape = (row_size, col_size) shape = x.shape if idx_dtype and not can_store(idx_dtype, max(max(compressed_shape), x.nnz)): raise ValueError( f"cannot store array with the compressed shape {compressed_shape} and nnz {x.nnz} with dtype {idx_dtype}." ) if not idx_dtype: idx_dtype = x.coords.dtype if not can_store(idx_dtype, max(max(compressed_shape), x.nnz)): idx_dtype = np.min_scalar_type(max(max(compressed_shape), x.nnz)) # transpose axes, linearize, reshape, and compress linear = linear_loc(x.coords[axis_order], reordered_shape) order = np.argsort(linear) linear = linear[order] coords = np.empty((2, x.nnz), dtype=idx_dtype) strides = 1 for i, d in enumerate(compressed_shape[::-1]): coords[-(i + 1), :] = (linear // strides) % d strides *= d indptr = np.empty(row_size + 1, dtype=idx_dtype) indptr[0] = 0 np.cumsum(np.bincount(coords[0], minlength=row_size), out=indptr[1:]) indices = coords[1] data = x.data[order] return ((data, indices, indptr), shape, compressed_axes, x.fill_value) class GCXS(SparseArray, NDArrayOperatorsMixin): r""" A sparse multidimensional array. This is stored in GCXS format, a generalization of the GCRS/GCCS formats from [Efficient storage scheme for n-dimensional sparse array: GCRS/GCCS]( https://ieeexplore.ieee.org/document/7237032). GCXS generalizes the CRS/CCS sparse matrix formats. For arrays with ndim == 2, GCXS is the same CSR/CSC. For arrays with ndim >2, any combination of axes can be compressed, significantly reducing storage. GCXS consists of 3 arrays. Let the 3 arrays be RO, CO and VL. The first element of array RO is the integer 0 and later elements are the number of cumulative non-zero elements in each row for GCRS, column for GCCS. CO stores column indexes of non-zero elements at each row for GCRS, column for GCCS. VL stores the values of the non-zero array elements. The superiority of the GCRS/GCCS over traditional (CRS/CCS) is shown by both theoretical analysis and experimental results, outlined in the linked research paper. Parameters ---------- arg : tuple (data, indices, indptr) A tuple of arrays holding the data, indices, and index pointers for the nonzero values of the array. shape : tuple[int] (COO.ndim,) The shape of the array. compressed_axes : Iterable[int] The axes to compress. prune : bool, optional A flag indicating whether or not we should prune any fill-values present in the data array. fill_value: scalar, optional The fill value for this array. Attributes ---------- data : numpy.ndarray (nnz,) An array holding the nonzero values corresponding to `indices`. indices : numpy.ndarray (nnz,) An array holding the coordinates of every nonzero element along uncompressed dimensions. indptr : numpy.ndarray An array holding the cumulative sums of the nonzeros along the compressed dimensions. shape : tuple[int] (ndim,) The dimensions of this array. See Also -------- [`sparse.DOK`][] : A mostly write-only sparse array. """ __array_priority__ = 12 def __init__( self, arg, shape=None, compressed_axes=None, prune=False, fill_value=None, idx_dtype=None, ): from .._common import _is_scipy_sparse_obj if _is_scipy_sparse_obj(arg): arg = self.from_scipy_sparse(arg) if isinstance(arg, np.ndarray): (arg, shape, compressed_axes, fill_value) = _from_coo(COO(arg), compressed_axes) elif isinstance(arg, COO): (arg, shape, compressed_axes, fill_value) = _from_coo(arg, compressed_axes, idx_dtype) elif isinstance(arg, GCXS): if compressed_axes is not None and arg.compressed_axes != compressed_axes: arg = arg.change_compressed_axes(compressed_axes) (arg, shape, compressed_axes, fill_value) = ( (arg.data, arg.indices, arg.indptr), arg.shape, arg.compressed_axes, arg.fill_value, ) if shape is None: raise ValueError("missing `shape` argument") check_compressed_axes(len(shape), compressed_axes) if len(shape) == 1: compressed_axes = None self.data, self.indices, self.indptr = arg if self.data.ndim != 1: raise ValueError("data must be a scalar or 1-dimensional.") self.shape = shape if fill_value is None: fill_value = _zero_of_dtype(self.data.dtype) self._compressed_axes = tuple(compressed_axes) if isinstance(compressed_axes, Iterable) else None self.fill_value = self.data.dtype.type(fill_value) if prune: self._prune() def copy(self, deep=True): """Return a copy of the array. Parameters ---------- deep : boolean, optional If True (default), the internal coords and data arrays are also copied. Set to ``False`` to only make a shallow copy. """ return _copy.deepcopy(self) if deep else _copy.copy(self) @classmethod def from_numpy(cls, x, compressed_axes=None, fill_value=None, idx_dtype=None): coo = COO.from_numpy(x, fill_value=fill_value, idx_dtype=idx_dtype) return cls.from_coo(coo, compressed_axes, idx_dtype) @classmethod def from_coo(cls, x, compressed_axes=None, idx_dtype=None): (arg, shape, compressed_axes, fill_value) = _from_coo(x, compressed_axes, idx_dtype) return cls(arg, shape=shape, compressed_axes=compressed_axes, fill_value=fill_value) @classmethod def from_scipy_sparse(cls, x, /, *, fill_value=None): is_csc = x.format == "csc" ca = (1,) if is_csc else (0,) if not is_csc: x = x.asformat("csr") if not x.has_canonical_format: x.eliminate_zeros() x.sum_duplicates() return cls((x.data, x.indices, x.indptr), shape=x.shape, compressed_axes=ca, fill_value=fill_value) @classmethod def from_iter(cls, x, shape=None, compressed_axes=None, fill_value=None, idx_dtype=None): return cls.from_coo( COO.from_iter(x, shape, fill_value), compressed_axes, idx_dtype, ) @property def dtype(self): """ The datatype of this array. Returns ------- numpy.dtype The datatype of this array. See Also -------- - [`numpy.ndarray.dtype`][] : Numpy equivalent property. - [`scipy.sparse.csr_array.dtype`][] : Scipy equivalent property. """ return self.data.dtype @property def nnz(self): """ The number of nonzero elements in this array. Returns ------- int The number of nonzero elements in this array. See Also -------- - [`sparse.COO.nnz`][] : Equivalent [`sparse.COO`][] array property. - [`sparse.DOK.nnz`][] : Equivalent [`sparse.DOK`][] array property. - [`numpy.count_nonzero`][] : A similar Numpy function. - [`scipy.sparse.coo_array.nnz`][] : The Scipy equivalent property. """ return self.data.shape[0] @property def format(self): """ The storage format of this array. Returns ------- str The storage format of this array. See Also ------- [`scipy.sparse.dok_matrix.format`][] : The Scipy equivalent property. Examples ------- >>> import sparse >>> s = sparse.random((5, 5), density=0.2, format="dok") >>> s.format 'dok' >>> t = sparse.random((5, 5), density=0.2, format="coo") >>> t.format 'coo' """ return "gcxs" @property def nbytes(self): """ The number of bytes taken up by this object. Note that for small arrays, this may undercount the number of bytes due to the large constant overhead. Returns ------- int The approximate bytes of memory taken by this object. See Also -------- [`numpy.ndarray.nbytes`][] : The equivalent Numpy property. """ return self.data.nbytes + self.indices.nbytes + self.indptr.nbytes @property def _axis_order(self): axis_order = list(self.compressed_axes) axis_order.extend(np.setdiff1d(np.arange(len(self.shape)), self.compressed_axes)) return axis_order @property def _axisptr(self): # array location where the uncompressed dimensions start return len(self.compressed_axes) @property def _compressed_shape(self): row_size = np.prod(self._reordered_shape[: self._axisptr]) col_size = np.prod(self._reordered_shape[self._axisptr :]) return (row_size, col_size) @property def _reordered_shape(self): return tuple(self.shape[i] for i in self._axis_order) @property def T(self): return self.transpose() @property def mT(self): if self.ndim < 2: raise ValueError("Cannot compute matrix transpose if `ndim < 2`.") axis = list(range(self.ndim)) axis[-1], axis[-2] = axis[-2], axis[-1] return self.transpose(axis) def __str__(self): summary = ( f"" ) return self._str_impl(summary) __repr__ = __str__ __getitem__ = getitem def _reduce_calc(self, method, axis, keepdims=False, **kwargs): if axis[0] is None or np.array_equal(axis, np.arange(self.ndim, dtype=np.intp)): x = self.flatten().tocoo() out = x.reduce(method, axis=None, keepdims=keepdims, **kwargs) if keepdims: return (out.reshape(np.ones(self.ndim, dtype=np.intp)),) return (out,) r = np.arange(self.ndim, dtype=np.intp) compressed_axes = [a for a in r if a not in set(axis)] x = self.change_compressed_axes(compressed_axes) idx = np.diff(x.indptr) != 0 indptr = x.indptr[:-1][idx] indices = (np.arange(x._compressed_shape[0], dtype=self.indptr.dtype))[idx] data = method.reduceat(x.data, indptr, **kwargs) counts = x.indptr[1:][idx] - x.indptr[:-1][idx] arr_attrs = (x, compressed_axes, indices) n_cols = x._compressed_shape[1] return (data, counts, axis, n_cols, arr_attrs) def _reduce_return(self, data, arr_attrs, result_fill_value): x, compressed_axes, indices = arr_attrs # prune data mask = ~equivalent(data, result_fill_value) data = data[mask] indices = indices[mask] out = GCXS( (data, indices, []), shape=(x._compressed_shape[0],), fill_value=result_fill_value, compressed_axes=None, ) return out.reshape(tuple(self.shape[d] for d in compressed_axes)) def change_compressed_axes(self, new_compressed_axes): """ Returns a new array with specified compressed axes. This operation is similar to converting a scipy.sparse.csc_array to a scipy.sparse.csr_array. Returns ------- GCXS A new instance of the input array with compression along the specified dimensions. """ if new_compressed_axes == self.compressed_axes: return self if self.ndim == 1: raise NotImplementedError("no axes to compress for 1d array") new_compressed_axes = tuple( normalize_axis(new_compressed_axes[i], self.ndim) for i in range(len(new_compressed_axes)) ) if new_compressed_axes == self.compressed_axes: return self if len(new_compressed_axes) >= len(self.shape): raise ValueError("cannot compress all axes") if len(set(new_compressed_axes)) != len(new_compressed_axes): raise ValueError("repeated axis in compressed_axes") arg = _transpose(self, self.shape, np.arange(self.ndim), new_compressed_axes) return GCXS( arg, shape=self.shape, compressed_axes=new_compressed_axes, fill_value=self.fill_value, ) def tocoo(self): """ Convert this [`sparse.GCXS`][] array to a [`sparse.COO`][]. Returns ------- sparse.COO The converted COO array. """ if self.ndim == 0: return COO( np.array([]), self.data, shape=self.shape, fill_value=self.fill_value, ) if self.ndim == 1: return COO( self.indices[None, :], self.data, shape=self.shape, fill_value=self.fill_value, ) uncompressed = uncompress_dimension(self.indptr) coords = np.vstack((uncompressed, self.indices)) order = np.argsort(self._axis_order) return ( COO( coords, self.data, shape=self._compressed_shape, fill_value=self.fill_value, ) .reshape(self._reordered_shape) .transpose(order) ) def todense(self): """ Convert this [`sparse.GCXS`][] array to a dense [`numpy.ndarray`][]. Note that this may take a large amount of memory if the [`sparse.GCXS`][] object's `shape` is large. Returns ------- numpy.ndarray The converted dense array. See Also -------- - [`sparse.DOK.todense`][] : Equivalent [`sparse.DOK`][] array method. - [`sparse.COO.todense`][] : Equivalent [`sparse.COO`][] array method. - [`scipy.sparse.coo_array.todense`][] : Equivalent Scipy method. """ if self.compressed_axes is None: out = np.full(self.shape, self.fill_value, self.dtype) if len(self.indices) != 0: out[self.indices] = self.data else: if len(self.data) != 0: out[()] = self.data[0] return out return self.tocoo().todense() def todok(self): from .. import DOK return DOK.from_coo(self.tocoo()) # probably a temporary solution def to_scipy_sparse(self, accept_fv=None): """ Converts this [`sparse.GCXS`][] object into a [`scipy.sparse.csr_array`][] or [`scipy.sparse.csc_array`][]. Parameters ---------- accept_fv : scalar or list of scalar, optional The list of accepted fill-values. The default accepts only zero. Returns ------- scipy.sparse.csr_array or scipy.sparse.csc_array The converted Scipy sparse matrix. Raises ------ ValueError If the array is not two-dimensional. ValueError If all the array doesn't zero fill-values. """ import scipy.sparse check_fill_value(self, accept_fv=accept_fv) if self.ndim != 2: raise ValueError("Can only convert a 2-dimensional array to a Scipy sparse matrix.") if 0 in self.compressed_axes: return scipy.sparse.csr_array((self.data, self.indices, self.indptr), shape=self.shape) return scipy.sparse.csc_array((self.data, self.indices, self.indptr), shape=self.shape) def asformat(self, format, **kwargs): """ Convert this sparse array to a given format. Parameters ---------- format : str A format string. Returns ------- out : SparseArray The converted array. Raises ------ NotImplementedError If the format isn't supported. """ from .._utils import convert_format format = convert_format(format) ret = None if format == "coo": ret = self.tocoo() elif format == "dok": ret = self.todok() elif format == "csr": ret = CSR(self) elif format == "csc": ret = CSC(self) elif format == "gcxs": compressed_axes = kwargs.pop("compressed_axes", self.compressed_axes) return self.change_compressed_axes(compressed_axes) if len(kwargs) != 0: raise TypeError(f"Invalid keyword arguments provided: {kwargs}") if ret is None: raise NotImplementedError(f"The given format is not supported: {format}") return ret def maybe_densify(self, max_size=1000, min_density=0.25): """ Converts this [`sparse.GCXS`][] array to a [`numpy.ndarray`][] if not too costly. Parameters ---------- max_size : int Maximum number of elements in output min_density : float Minimum density of output Returns ------- numpy.ndarray The dense array. See Also -------- - [sparse.GCXS.todense][]: Converts to Numpy function without checking the cost. - [sparse.COO.maybe_densify][]: The equivalent COO function. Raises ------- ValueError If the returned array would be too large. """ if self.size > max_size and self.density < min_density: raise ValueError("Operation would require converting large sparse array to dense") return self.todense() def flatten(self, order="C"): """ Returns a new [`sparse.GCXS`][] array that is a flattened version of this array. Returns ------- GCXS The flattened output array. Notes ----- The `order` parameter is provided just for compatibility with Numpy and isn't actually supported. """ if order not in {"C", None}: raise NotImplementedError("The `order` parameter is not supported.") return self.reshape(-1) def reshape(self, shape, order="C", compressed_axes=None): """ Returns a new [`sparse.GCXS`][] array that is a reshaped version of this array. Parameters ---------- shape : tuple[int] The desired shape of the output array. compressed_axes : Iterable[int], optional The axes to compress to store the array. Finds the most efficient storage by default. Returns ------- GCXS The reshaped output array. See Also -------- - [`numpy.ndarray.reshape`][] : The equivalent Numpy function. - [sparse.COO.reshape][] : The equivalent COO function. Notes ----- The `order` parameter is provided just for compatibility with Numpy and isn't actually supported. """ shape = tuple(shape) if isinstance(shape, Iterable) else (shape,) if order not in {"C", None}: raise NotImplementedError("The 'order' parameter is not supported") if any(d == -1 for d in shape): extra = int(self.size / np.prod([d for d in shape if d != -1])) shape = tuple([d if d != -1 else extra for d in shape]) if self.shape == shape: return self if self.size != reduce(operator.mul, shape, 1): raise ValueError(f"cannot reshape array of size {self.size} into shape {shape}") if len(shape) == 0: return self.tocoo().reshape(shape).asformat("gcxs") if compressed_axes is None: if len(shape) == self.ndim: compressed_axes = self.compressed_axes elif len(shape) == 1: compressed_axes = None else: compressed_axes = (np.argmin(shape),) if self.ndim == 1: arg = _1d_reshape(self, shape, compressed_axes) else: arg = _transpose(self, shape, np.arange(self.ndim), compressed_axes) return GCXS( arg, shape=tuple(shape), compressed_axes=compressed_axes, fill_value=self.fill_value, ) @property def compressed_axes(self): return self._compressed_axes def transpose(self, axes=None, compressed_axes=None): """ Returns a new array which has the order of the axes switched. Parameters ---------- axes : Iterable[int], optional The new order of the axes compared to the previous one. Reverses the axes by default. compressed_axes : Iterable[int], optional The axes to compress to store the array. Finds the most efficient storage by default. Returns ------- GCXS The new array with the axes in the desired order. See Also -------- - [`sparse.GCXS.T`][] : A quick property to reverse the order of the axes. - [`numpy.ndarray.transpose`][] : Numpy equivalent function. """ if axes is None: axes = list(reversed(range(self.ndim))) # Normalize all axes indices to positive values axes = normalize_axis(axes, self.ndim) if len(np.unique(axes)) < len(axes): raise ValueError("repeated axis in transpose") if not len(axes) == self.ndim: raise ValueError("axes don't match array") axes = tuple(axes) if axes == tuple(range(self.ndim)): return self if self.ndim == 2: return self._2d_transpose() shape = tuple(self.shape[ax] for ax in axes) if compressed_axes is None: compressed_axes = (np.argmin(shape),) arg = _transpose(self, shape, axes, compressed_axes, transpose=True) return GCXS( arg, shape=shape, compressed_axes=compressed_axes, fill_value=self.fill_value, ) def _2d_transpose(self): """ A function for performing constant-time transposes on 2d GCXS arrays. Returns ------- GCXS The new transposed array with the opposite compressed axes as the input. See Also -------- scipy.sparse.csr_array.transpose : Scipy equivalent function. scipy.sparse.csc_array.transpose : Scipy equivalent function. numpy.ndarray.transpose : Numpy equivalent function. """ if self.ndim != 2: raise ValueError(f"cannot perform 2d transpose on array with dimension {self.ndim}") compressed_axes = [(self.compressed_axes[0] + 1) % 2] shape = self.shape[::-1] return GCXS( (self.data, self.indices, self.indptr), shape=shape, compressed_axes=compressed_axes, fill_value=self.fill_value, ) def dot(self, other): """ Performs the equivalent of `x.dot(y)` for [`sparse.GCXS`][]. Parameters ---------- other : Union[GCXS, COO, numpy.ndarray, scipy.sparse.spmatrix] The second operand of the dot product operation. Returns ------- {GCXS, numpy.ndarray} The result of the dot product. If the result turns out to be dense, then a dense array is returned, otherwise, a sparse array. Raises ------ ValueError If all arguments don't have zero fill-values. See Also -------- - [`sparse.dot`][] : Equivalent function for two arguments. - [`numpy.dot`][] : Numpy equivalent function. - [`scipy.sparse.coo_array.dot`][] : Scipy equivalent function. """ from .._common import dot return dot(self, other) def __matmul__(self, other): from .._common import matmul try: return matmul(self, other) except NotImplementedError: return NotImplemented def __rmatmul__(self, other): from .._common import matmul try: return matmul(other, self) except NotImplementedError: return NotImplemented def _prune(self): """ Prunes data so that if any fill-values are present, they are removed from both indices and data. Examples -------- >>> coords = np.array([[0, 1, 2, 3]]) >>> data = np.array([1, 0, 1, 2]) >>> s = COO(coords, data, shape=(4,)).asformat("gcxs") >>> s._prune() >>> s.nnz 3 """ mask = ~equivalent(self.data, self.fill_value) self.data = self.data[mask] if len(self.indptr): coords = np.stack((uncompress_dimension(self.indptr), self.indices)) coords = coords[:, mask] self.indices = coords[1] row_size = self._compressed_shape[0] indptr = np.empty(row_size + 1, dtype=self.indptr.dtype) indptr[0] = 0 np.cumsum(np.bincount(coords[0], minlength=row_size), out=indptr[1:]) self.indptr = indptr else: self.indices = self.indices[mask] def isinf(self): return self.tocoo().isinf().asformat("gcxs", compressed_axes=self.compressed_axes) def isnan(self): return self.tocoo().isnan().asformat("gcxs", compressed_axes=self.compressed_axes) class _Compressed2d(GCXS): class_compressed_axes: tuple[int] def __init__(self, arg, shape=None, compressed_axes=None, prune=False, fill_value=0): if not hasattr(arg, "shape") and shape is None: raise ValueError("missing `shape` argument") if shape is not None and hasattr(arg, "shape"): raise NotImplementedError("Cannot change shape in constructor") nd = len(shape if shape is not None else arg.shape) if nd != 2: raise ValueError(f"{type(self).__name__} must be 2-d, passed {nd}-d shape.") super().__init__( arg, shape=shape, compressed_axes=compressed_axes, prune=prune, fill_value=fill_value, ) def __str__(self): summary = ( f"<{type(self).__name__}: shape={self.shape}, dtype={self.dtype}, nnz={self.nnz}, " f"fill_value={self.fill_value}>" ) return self._str_impl(summary) __repr__ = __str__ @property def ndim(self) -> int: return 2 @classmethod def from_numpy(cls, x, fill_value=0, idx_dtype=None): coo = COO.from_numpy(x, fill_value=fill_value, idx_dtype=idx_dtype) return cls.from_coo(coo, cls.class_compressed_axes, idx_dtype) class CSR(_Compressed2d): """ The CSR or CRS scheme stores a n-dimensional array using n+1 one-dimensional arrays. The 3 arrays are same as GCRS. The remaining n-2 arrays are for storing the indices of the non-zero values of the sparse matrix. CSR is simply the transpose of CSC. Sparse supports 2-D CSR. """ class_compressed_axes: tuple[int] = (0,) def __init__(self, arg, shape=None, compressed_axes=class_compressed_axes, prune=False, fill_value=0): if compressed_axes != self.class_compressed_axes: raise ValueError(f"CSR only accepts rows as compressed axis but got: {compressed_axes}") super().__init__(arg, shape=shape, compressed_axes=compressed_axes, fill_value=fill_value) @classmethod def from_scipy_sparse(cls, x, /, *, fill_value=None): x = x.asformat("csr", copy=False) if not x.has_canonical_format: x.eliminate_zeros() x.sum_duplicates() return cls((x.data, x.indices, x.indptr), shape=x.shape, fill_value=fill_value) def transpose(self, axes: None = None, copy: bool = False) -> Union["CSC", "CSR"]: axes = normalize_axis(axes, self.ndim) if axes not in [(0, 1), (1, 0), None]: raise ValueError(f"Invalid transpose axes: {axes}") if copy: self = self.copy() if axes == (0, 1): return self return CSC((self.data, self.indices, self.indptr), self.shape[::-1], fill_value=self.fill_value) class CSC(_Compressed2d): """ The CSC or CCS scheme stores a n-dimensional array using n+1 one-dimensional arrays. The 3 arrays are same as GCCS. The remaining n-2 arrays are for storing the indices of the non-zero values of the sparse matrix. CSC is simply the transpose of CSR. Sparse supports 2-D CSC. """ class_compressed_axes: tuple[int] = (1,) def __init__(self, arg, shape=None, compressed_axes=class_compressed_axes, prune=False, fill_value=0): if compressed_axes != self.class_compressed_axes: raise ValueError(f"CSC only accepts columns as compressed axis but got: {compressed_axes}") super().__init__(arg, shape=shape, compressed_axes=compressed_axes, fill_value=fill_value) @classmethod def from_scipy_sparse(cls, x, /, *, fill_value=None): x = x.asformat("csc", copy=False) if not x.has_canonical_format: x.eliminate_zeros() x.sum_duplicates() return cls((x.data, x.indices, x.indptr), shape=x.shape, fill_value=fill_value) def transpose(self, axes: None = None, copy: bool = False) -> Union["CSC", "CSR"]: axes = normalize_axis(axes, self.ndim) if axes not in [(0, 1), (1, 0), None]: raise ValueError(f"Invalid transpose axes: {axes}") if copy: self = self.copy() if axes == (0, 1): return self return CSR((self.data, self.indices, self.indptr), self.shape[::-1], fill_value=self.fill_value) sparse-0.18.0/sparse/numba_backend/_compressed/convert.py000066400000000000000000000250761514474157100235230ustar00rootroot00000000000000import operator from functools import reduce import numba from numba.typed import List import numpy as np from .._coo.common import linear_loc from .._utils import check_compressed_axes, get_out_dtype @numba.jit(nopython=True, nogil=True) def convert_to_flat(inds, shape, dtype): """ Converts the indices of either the compressed or uncompressed axes into a linearized form. Prepares the inputs for compute_flat. """ shape_bins = transform_shape(np.asarray(shape)) increments = List() for i in range(len(inds)): increments.append((inds[i] * shape_bins[i]).astype(dtype)) operations = 1 for inc in increments[:-1]: operations *= inc.shape[0] if operations == 0: return np.empty(0, dtype=dtype) cols = increments[-1].repeat(operations).reshape((-1, operations)).T.flatten() if len(increments) == 1: return cols return compute_flat(increments, cols, operations) @numba.jit(nopython=True, nogil=True) def compute_flat(increments, cols, operations): # pragma: no cover """ Iterates through indices and calculates the linearized indices. """ start = 0 end = increments[-1].shape[0] positions = np.zeros(len(increments) - 1, dtype=np.intp) pos = len(increments) - 2 for _ in range(operations): to_add = 0 for j in range(len(increments) - 1): to_add += increments[j][positions[j]] cols[start:end] += to_add start += increments[-1].shape[0] end += increments[-1].shape[0] for j in range(pos, -1, -1): positions[j] += 1 if positions[j] == increments[j].shape[0]: positions[j] = 0 else: break return cols @numba.jit(nopython=True, nogil=True) def transform_shape(shape): # pragma: no cover """ turns a shape into the linearized increments that it represents. For example, given (5,5,5), it returns np.array([25,5,1]). """ shape_bins = np.empty(len(shape), dtype=np.intp) shape_bins[-1] = 1 for i in range(len(shape) - 1): shape_bins[i] = np.prod(shape[i + 1 :]) return shape_bins @numba.jit(nopython=True, nogil=True) def uncompress_dimension(indptr): # pragma: no cover """converts an index pointer array into an array of coordinates""" uncompressed = np.empty(indptr[-1], dtype=indptr.dtype) for i in range(len(indptr) - 1): uncompressed[indptr[i] : indptr[i + 1]] = i return uncompressed @numba.jit(nopython=True, nogil=True) def is_sorted(arr): # pragma: no cover """ function to check if an indexing array is sorted without repeats. If it is, we can use the faster slicing algorithm. """ # numba doesn't recognize the new all(...) format for i in range(len(arr) - 1): # noqa: SIM110 if arr[i + 1] <= arr[i]: return False return True @numba.jit(nopython=True, nogil=True) def _linearize( x_indices, shape, new_axis_order, new_reordered_shape, new_compressed_shape, new_linear, new_coords, ): # pragma: no cover for i, n in enumerate(x_indices): current = unravel_index(n, shape) current_t = current[new_axis_order] new_linear[i] = ravel_multi_index(current_t, new_reordered_shape) new_coords[:, i] = unravel_index(new_linear[i], new_compressed_shape) def _1d_reshape(x, shape, compressed_axes): check_compressed_axes(shape, compressed_axes) new_size = np.prod(shape) end_idx = np.searchsorted(x.indices, new_size, side="left") # for resizeing in one dimension if len(shape) == 1: return (x.data[:end_idx], x.indices[:end_idx], []) new_axis_order = list(compressed_axes) new_axis_order.extend(np.setdiff1d(np.arange(len(shape)), compressed_axes)) new_axis_order = np.asarray(new_axis_order) new_reordered_shape = np.array(shape)[new_axis_order] axisptr = len(compressed_axes) row_size = np.prod(new_reordered_shape[:axisptr]) col_size = np.prod(new_reordered_shape[axisptr:]) new_compressed_shape = np.array((row_size, col_size)) x_indices = x.indices[:end_idx] new_nnz = x_indices.size new_linear = np.empty(new_nnz, dtype=np.intp) coords_dtype = get_out_dtype(x.indices, max(max(new_compressed_shape), x.nnz)) new_coords = np.empty((2, new_nnz), dtype=coords_dtype) _linearize( x_indices, np.array(shape), new_axis_order, new_reordered_shape, new_compressed_shape, new_linear, new_coords, ) order = np.argsort(new_linear) new_coords = new_coords[:, order] indptr = np.empty(row_size + 1, dtype=coords_dtype) indptr[0] = 0 np.cumsum(np.bincount(new_coords[0], minlength=row_size), out=indptr[1:]) indices = new_coords[1] data = x.data[:end_idx][order] return (data, indices, indptr) def _resize(x, shape, compressed_axes): from .compressed import GCXS check_compressed_axes(shape, compressed_axes) size = reduce(operator.mul, shape, 1) if x.ndim == 1: end_idx = np.searchsorted(x.indices, size, side="left") indices = x.indices[:end_idx] data = x.data[:end_idx] out = GCXS((data, indices, []), shape=(size,), fill_value=x.fill_value) return _1d_reshape(out, shape, compressed_axes) uncompressed = uncompress_dimension(x.indptr) coords = np.stack((uncompressed, x.indices)) linear = linear_loc(coords, x._compressed_shape) sorted_axis_order = np.argsort(x._axis_order) linear_dtype = get_out_dtype(x.indices, np.prod(shape)) c_linear = np.empty(x.nnz, dtype=linear_dtype) _c_ordering( linear, c_linear, np.asarray(x._reordered_shape), np.asarray(sorted_axis_order), np.asarray(x.shape), ) order = np.argsort(c_linear, kind="mergesort") data = x.data[order] indices = c_linear[order] end_idx = np.searchsorted(indices, size, side="left") indices = indices[:end_idx] data = data[:end_idx] out = GCXS((data, indices, []), shape=(size,), fill_value=x.fill_value) return _1d_reshape(out, shape, compressed_axes) @numba.jit(nopython=True, nogil=True) def _c_ordering(linear, c_linear, reordered_shape, sorted_axis_order, shape): # pragma: no cover for i, n in enumerate(linear): # c ordering current_coords = unravel_index(n, reordered_shape)[sorted_axis_order] c_linear[i] = ravel_multi_index(current_coords, shape) def _transpose(x, shape, axes, compressed_axes, transpose=False): """ An algorithm for reshaping, resizing, changing compressed axes, and transposing. """ check_compressed_axes(shape, compressed_axes) uncompressed = uncompress_dimension(x.indptr) coords = np.stack((uncompressed, x.indices)) linear = linear_loc(coords, x._compressed_shape) sorted_axis_order = np.argsort(x._axis_order) if len(shape) == 1: dtype = get_out_dtype(x.indices, shape[0]) c_linear = np.empty(x.nnz, dtype=dtype) _c_ordering( linear, c_linear, np.asarray(x._reordered_shape), np.asarray(sorted_axis_order), np.asarray(x.shape), ) order = np.argsort(c_linear, kind="mergesort") data = x.data[order] indices = c_linear[order] return (data, indices, []) new_axis_order = list(compressed_axes) new_axis_order.extend(np.setdiff1d(np.arange(len(shape)), compressed_axes)) new_linear = np.empty(x.nnz, dtype=np.intp) new_reordered_shape = np.array(shape)[new_axis_order] axisptr = len(compressed_axes) row_size = np.prod(new_reordered_shape[:axisptr]) col_size = np.prod(new_reordered_shape[axisptr:]) new_compressed_shape = np.array((row_size, col_size)) coords_dtype = get_out_dtype(x.indices, max(max(new_compressed_shape), x.nnz)) new_coords = np.empty((2, x.nnz), dtype=coords_dtype) _convert_coords( linear, np.asarray(x.shape), np.asarray(x._reordered_shape), sorted_axis_order, np.asarray(axes), np.asarray(shape), np.asarray(new_axis_order), new_reordered_shape, new_linear, new_coords, new_compressed_shape, transpose, ) order = np.argsort(new_linear, kind="mergesort") new_coords = new_coords[:, order] if len(shape) == 1: indptr = [] indices = coords[0, :] else: indptr = np.empty(row_size + 1, dtype=coords_dtype) indptr[0] = 0 np.cumsum(np.bincount(new_coords[0], minlength=row_size), out=indptr[1:]) indices = new_coords[1] data = x.data[order] return (data, indices, indptr) @numba.jit(nopython=True, nogil=True) def unravel_index(n, shape): # pragma: no cover """ implements a subset of the functionality of np.unravel_index. """ out = np.zeros(len(shape), dtype=np.intp) i = 1 while i < len(shape) and n > 0: cur = np.prod(shape[i:]) out[i - 1] = n // cur n -= out[i - 1] * cur i += 1 out[-1] = n return out @numba.jit(nopython=True, nogil=True) def ravel_multi_index(arr, shape): # pragma: no cover """ implements a subset of the functionality of np.ravel_multi_index. """ total = 0 for i, a in enumerate(arr[:-1], 1): total += a * np.prod(shape[i:]) total += arr[-1] return total @numba.jit(nopython=True, nogil=True) def _convert_coords( linear, old_shape, reordered_shape, sorted_axis_order, axes, shape, new_axis_order, new_reordered_shape, new_linear, new_coords, new_compressed_shape, transpose, ): # pragma: no cover if transpose: for i, n in enumerate(linear): # c ordering current_coords = unravel_index(n, reordered_shape)[sorted_axis_order] # transpose current_coords_t = current_coords[axes][new_axis_order] new_linear[i] = ravel_multi_index(current_coords_t, new_reordered_shape) # reshape new_coords[:, i] = unravel_index(new_linear[i], new_compressed_shape) else: for i, n in enumerate(linear): # c ordering current_coords = unravel_index(n, reordered_shape)[sorted_axis_order] # linearize c_current = ravel_multi_index(current_coords, old_shape) # compress c_compressed = unravel_index(c_current, shape) c_compressed = c_compressed[new_axis_order] new_linear[i] = ravel_multi_index(c_compressed, new_reordered_shape) # reshape new_coords[:, i] = unravel_index(new_linear[i], new_compressed_shape) sparse-0.18.0/sparse/numba_backend/_compressed/indexing.py000066400000000000000000000242711514474157100236440ustar00rootroot00000000000000from collections.abc import Iterable from itertools import zip_longest from numbers import Integral import numba from numba.typed import List import numpy as np from .._slicing import normalize_index from .convert import convert_to_flat, is_sorted, uncompress_dimension def getitem(x, key): """ GCXS arrays are stored by transposing and reshaping them into csr matrices. For indexing, we first convert the n-dimensional key to its corresponding 2-dimensional key and then iterate through each of the relevent rows and columns. """ from .compressed import GCXS if x.ndim == 1: result = x.tocoo()[key] if np.isscalar(result): return result return GCXS.from_coo(result) key = list(normalize_index(key, x.shape)) # zip_longest so things like x[..., None] are picked up. if len(key) != 0 and all(isinstance(k, slice) and k == slice(0, dim, 1) for k, dim in zip_longest(key, x.shape)): return x # return a single element if all(isinstance(k, int) for k in key): return get_single_element(x, key) shape = [] compressed_inds = np.zeros(len(x.shape), dtype=np.bool_) uncompressed_inds = np.zeros(len(x.shape), dtype=np.bool_) # which axes will be compressed in the resulting array shape_key = np.zeros(len(x.shape), dtype=np.intp) # remove Nones from key, evaluate them at the end Nones_removed = [k for k in key if k is not None] count = 0 for i, ind in enumerate(Nones_removed): if isinstance(ind, Integral): continue if isinstance(ind, slice): shape_key[i] = count shape.append(len(range(ind.start, ind.stop, ind.step))) if i in x.compressed_axes: compressed_inds[i] = True else: uncompressed_inds[i] = True elif isinstance(ind, Iterable): shape_key[i] = count shape.append(len(ind)) if i in x.compressed_axes: compressed_inds[i] = True else: uncompressed_inds[i] = True count += 1 # reorder the key according to the axis_order of the array reordered_key = [Nones_removed[i] for i in x._axis_order] # if all slices have a positive step and all # iterables are sorted without repeats, we can # use the quicker slicing algorithm pos_slice = True for ind in reordered_key[x._axisptr :]: if isinstance(ind, slice): if ind.step < 0: pos_slice = False elif isinstance(ind, Iterable) and not is_sorted(ind): pos_slice = False # convert all ints and slices to iterables before flattening for i, ind in enumerate(reordered_key): if isinstance(ind, Integral): reordered_key[i] = np.array([ind]) elif isinstance(ind, slice): reordered_key[i] = np.arange(ind.start, ind.stop, ind.step) elif isinstance(ind, np.ndarray) and ind.ndim > 1: raise IndexError("Only one-dimensional iterable indices supported.") reordered_key[i] = reordered_key[i].astype(x.indices.dtype, copy=False) reordered_key = List(reordered_key) shape = np.array(shape) # convert all indices of compressed axes to a single array index # this tells us which 'rows' of the underlying csr matrix to iterate through rows = convert_to_flat( reordered_key[: x._axisptr], x._reordered_shape[: x._axisptr], x.indices.dtype, ) # convert all indices of uncompressed axes to a single array index # this tells us which 'columns' of the underlying csr matrix to iterate through cols = convert_to_flat( reordered_key[x._axisptr :], x._reordered_shape[x._axisptr :], x.indices.dtype, ) starts = x.indptr[:-1][rows] # find the start and end of each of the rows ends = x.indptr[1:][rows] if np.any(compressed_inds): compressed_axes = shape_key[compressed_inds] row_size = shape[compressed_axes] if len(compressed_axes) == 1 else np.prod(shape[compressed_axes]) # if only indexing through uncompressed axes else: compressed_axes = (0,) # defaults to 0 row_size = 1 # this doesn't matter if not np.any(uncompressed_inds): # only indexing compressed axes compressed_axes = (0,) # defaults to 0 row_size = starts.size indptr = np.empty(row_size + 1, dtype=x.indptr.dtype) indptr[0] = 0 if pos_slice: arg = get_slicing_selection(x.data, x.indices, indptr, starts, ends, cols) else: arg = get_array_selection(x.data, x.indices, indptr, starts, ends, cols) data, indices, indptr = arg size = np.prod(shape[1:]) if not np.any(uncompressed_inds): # only indexing compressed axes uncompressed = uncompress_dimension(indptr) if len(shape) == 1: indices = uncompressed indptr = None else: indices = uncompressed % size indptr = np.empty(shape[0] + 1, dtype=x.indptr.dtype) indptr[0] = 0 np.cumsum(np.bincount(uncompressed // size, minlength=shape[0]), out=indptr[1:]) if not np.any(compressed_inds): if len(shape) == 1: indptr = None else: uncompressed = indices // size indptr = np.empty(shape[0] + 1, dtype=x.indptr.dtype) indptr[0] = 0 np.cumsum(np.bincount(uncompressed, minlength=shape[0]), out=indptr[1:]) indices %= size arg = (data, indices, indptr) # if there were Nones in the key, we insert them back here compressed_axes = np.array(compressed_axes) shape = shape.tolist() for i in range(len(key)): if key[i] is None: shape.insert(i, 1) compressed_axes[compressed_axes >= i] += 1 compressed_axes = tuple(compressed_axes) shape = tuple(shape) if len(shape) == 1: compressed_axes = None return GCXS(arg, shape=shape, compressed_axes=compressed_axes, fill_value=x.fill_value) @numba.jit(nopython=True, nogil=True) def get_slicing_selection(arr_data, arr_indices, indptr, starts, ends, col): # pragma: no cover """ When the requested elements come in a strictly ascending order, as is the case with acsending slices, we can iteratively reduce the search space, leading to better performance. We loop through the starts and ends, each time evaluating whether to use a linear filtering procedure or a binary-search-based method. """ indices = [] ind_list = [] for i, (start, end) in enumerate(zip(starts, ends)): # noqa: B905 inds = [] current_row = arr_indices[start:end] if current_row.size < col.size: # linear filtering count = 0 col_count = 0 nnz = 0 while col_count < col.size and count < current_row.size: if current_row[-1] < col[col_count] or current_row[count] > col[-1]: break if current_row[count] == col[col_count]: nnz += 1 ind_list.append(count + start) indices.append(col_count) count += 1 col_count += 1 elif current_row[count] < col[col_count]: count += 1 else: col_count += 1 indptr[i + 1] = indptr[i] + nnz else: # binary searches prev = 0 size = 0 col_count = 0 while col_count < len(col): while ( col_count < len(col) and size < len(current_row) and col[col_count] < current_row[size] ): # skip needless searches col_count += 1 if col_count >= len(col): # check again because of previous loop break if current_row[-1] < col[col_count] or current_row[size] > col[-1]: break s = np.searchsorted(current_row[size:], col[col_count]) size += s s += prev if not (s >= current_row.size or current_row[s] != col[col_count]): s += start inds.append(s) indices.append(col_count) size += 1 prev = size col_count += 1 ind_list.extend(inds) indptr[i + 1] = indptr[i] + len(inds) ind_list = np.array(ind_list, dtype=np.intp) indices = np.array(indices, dtype=indptr.dtype) data = arr_data[ind_list] return (data, indices, indptr) @numba.jit(nopython=True, nogil=True) def get_array_selection(arr_data, arr_indices, indptr, starts, ends, col): # pragma: no cover """ This is a very general algorithm to be used when more optimized methods don't apply. It performs a binary search for each of the requested elements. Consequently it roughly scales by O(n log avg(nnz)). """ indices = [] ind_list = [] for i, (start, end) in enumerate(zip(starts, ends)): # noqa: B905 inds = [] current_row = arr_indices[start:end] if len(current_row) == 0: indptr[i + 1] = indptr[i] continue for c in range(len(col)): s = np.searchsorted(current_row, col[c]) if not (s >= current_row.size or current_row[s] != col[c]): s += start inds.append(s) indices.append(c) ind_list.extend(inds) indptr[i + 1] = indptr[i] + len(inds) ind_list = np.array(ind_list, dtype=np.intp) indices = np.array(indices, dtype=indptr.dtype) data = arr_data[ind_list] return (data, indices, indptr) def get_single_element(x, key): """ A convience function for indexing when returning a single element. """ key = np.array(key)[x._axis_order] # reordering the input ind = np.ravel_multi_index(key, x._reordered_shape) row, col = np.unravel_index(ind, x._compressed_shape) current_row = x.indices[x.indptr[row] : x.indptr[row + 1]] item = np.searchsorted(current_row, col) if not (item >= current_row.size or current_row[item] != col): item += x.indptr[row] return x.data[item] return x.fill_value sparse-0.18.0/sparse/numba_backend/_coo/000077500000000000000000000000001514474157100200735ustar00rootroot00000000000000sparse-0.18.0/sparse/numba_backend/_coo/__init__.py000066400000000000000000000015601514474157100222060ustar00rootroot00000000000000from .common import ( argmax, argmin, argwhere, clip, concatenate, diagonal, diagonalize, expand_dims, flip, isneginf, isposinf, kron, nanmax, nanmean, nanmin, nanprod, nanreduce, nansum, result_type, roll, sort, stack, take, tril, triu, unique_counts, unique_values, where, ) from .core import COO, as_coo __all__ = [ "COO", "as_coo", "argmax", "argmin", "argwhere", "clip", "concatenate", "diagonal", "diagonalize", "expand_dims", "flip", "isneginf", "isposinf", "kron", "nanmax", "nanmean", "nanmin", "nanprod", "nanreduce", "nansum", "result_type", "roll", "sort", "stack", "take", "tril", "triu", "unique_counts", "unique_values", "where", ] sparse-0.18.0/sparse/numba_backend/_coo/common.py000066400000000000000000001267241514474157100217510ustar00rootroot00000000000000import operator import warnings from collections.abc import Iterable from functools import reduce from typing import Any, NamedTuple import numba import numpy as np from .._sparse_array import SparseArray from .._utils import ( can_store, check_consistent_fill_value, check_zero_fill_value, is_unsigned_dtype, isscalar, normalize_axis, ) def asCOO(x, name="asCOO", check=True): """ Convert the input to [`sparse.COO`][]. Passes through [`sparse.COO`][] objects as-is. Parameters ---------- x : Union[SparseArray, scipy.sparse.spmatrix, numpy.ndarray] The input array to convert. name : str, optional The name of the operation to use in the exception. check : bool, optional Whether to check for a dense input. Returns ------- COO The converted [`sparse.COO`][] array. Raises ------ ValueError If `check` is true and a dense input is supplied. """ from .._common import _is_sparse from .core import COO if check and not _is_sparse(x): raise ValueError(f"Performing this operation would produce a dense result: {name}") if not isinstance(x, COO): x = COO(x) return x def linear_loc(coords, shape): if shape == () and len(coords) == 0: # `np.ravel_multi_index` is not aware of arrays, so cannot produce a # sensible result here (https://github.com/numpy/numpy/issues/15690). # Since `coords` is an array and not a sequence, we know the correct # dimensions. return np.zeros(coords.shape[1:], dtype=np.intp) return np.ravel_multi_index(coords, shape) def kron(a, b): """Kronecker product of 2 sparse arrays. Parameters ---------- a, b : SparseArray, scipy.sparse.spmatrix, or np.ndarray The arrays over which to compute the Kronecker product. Returns ------- res : COO The kronecker product Raises ------ ValueError If all arguments are dense or arguments have nonzero fill-values. Examples -------- >>> from sparse import eye >>> a = eye(3, dtype="i8") >>> b = np.array([1, 2, 3], dtype="i8") >>> res = kron(a, b) >>> res.todense() # doctest: +SKIP array([[1, 2, 3, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 2, 3, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 2, 3]], dtype=int64) """ from .._common import _is_sparse from .._umath import _cartesian_product from .core import COO check_zero_fill_value(a, b) a_sparse = _is_sparse(a) b_sparse = _is_sparse(b) a_ndim = np.ndim(a) b_ndim = np.ndim(b) if not (a_sparse or b_sparse): raise ValueError("Performing this operation would produce a dense result: kron") if a_ndim == 0 or b_ndim == 0: return a * b a = asCOO(a, check=False) b = asCOO(b, check=False) # Match dimensions max_dim = max(a.ndim, b.ndim) a = a.reshape((1,) * (max_dim - a.ndim) + a.shape) b = b.reshape((1,) * (max_dim - b.ndim) + b.shape) a_idx, b_idx = _cartesian_product(np.arange(a.nnz), np.arange(b.nnz)) a_expanded_coords = a.coords[:, a_idx] b_expanded_coords = b.coords[:, b_idx] o_coords = a_expanded_coords * np.asarray(b.shape)[:, None] + b_expanded_coords o_data = a.data[a_idx] * b.data[b_idx] o_shape = tuple(i * j for i, j in zip(a.shape, b.shape, strict=True)) return COO(o_coords, o_data, shape=o_shape, has_duplicates=False) def concatenate(arrays, axis=0): """ Concatenate the input arrays along the given dimension. Parameters ---------- arrays : Iterable[SparseArray] The input arrays to concatenate. axis : int, optional The axis along which to concatenate the input arrays. The default is zero. Returns ------- COO The output concatenated array. Raises ------ ValueError If all elements of `arrays` don't have the same fill-value. See Also -------- [`numpy.concatenate`][] : NumPy equivalent function """ from .core import COO check_consistent_fill_value(arrays) if axis is None: axis = 0 arrays = [x.flatten() for x in arrays] arrays = [x if isinstance(x, COO) else COO(x) for x in arrays] axis = normalize_axis(axis, arrays[0].ndim) assert all(x.shape[ax] == arrays[0].shape[ax] for x in arrays for ax in set(range(arrays[0].ndim)) - {axis}) nnz = 0 dim = sum(x.shape[axis] for x in arrays) shape = list(arrays[0].shape) shape[axis] = dim data = np.concatenate([x.data for x in arrays]) coords = np.concatenate([x.coords for x in arrays], axis=1) if not can_store(coords.dtype, max(shape)): coords = coords.astype(np.min_scalar_type(max(shape))) dim = 0 for x in arrays: if dim: coords[axis, nnz : x.nnz + nnz] += dim dim += x.shape[axis] nnz += x.nnz return COO( coords, data, shape=shape, has_duplicates=False, sorted=(axis == 0), fill_value=arrays[0].fill_value, ) def stack(arrays, axis=0): """ Stack the input arrays along the given dimension. Parameters ---------- arrays : Iterable[SparseArray] The input arrays to stack. axis : int, optional The axis along which to stack the input arrays. Returns ------- COO The output stacked array. Raises ------ ValueError If all elements of `arrays` don't have the same fill-value. See Also -------- [`numpy.stack`][] : NumPy equivalent function """ from .core import COO check_consistent_fill_value(arrays) assert len({x.shape for x in arrays}) == 1 arrays = [x if isinstance(x, COO) else COO(x) for x in arrays] axis = normalize_axis(axis, arrays[0].ndim + 1) data = np.concatenate([x.data for x in arrays]) coords = np.concatenate([x.coords for x in arrays], axis=1) shape = list(arrays[0].shape) shape.insert(axis, len(arrays)) nnz = 0 new = np.empty(shape=(coords.shape[1],), dtype=np.intp) for dim, x in enumerate(arrays): new[nnz : x.nnz + nnz] = dim nnz += x.nnz coords = [coords[i] for i in range(coords.shape[0])] coords.insert(axis, new) coords = np.stack(coords, axis=0) return COO( coords, data, shape=shape, has_duplicates=False, sorted=(axis == 0), fill_value=arrays[0].fill_value, ) def triu(x, k=0): """ Returns an array with all elements below the k-th diagonal set to zero. Parameters ---------- x : COO The input array. k : int, optional The diagonal below which elements are set to zero. The default is zero, which corresponds to the main diagonal. Returns ------- COO The output upper-triangular matrix. Raises ------ ValueError If `x` doesn't have zero fill-values. See Also -------- - [`numpy.triu`][] : NumPy equivalent function """ from .core import COO check_zero_fill_value(x) if not x.ndim >= 2: raise NotImplementedError("sparse.triu is not implemented for scalars or 1-D arrays.") mask = x.coords[-2] + k <= x.coords[-1] coords = x.coords[:, mask] data = x.data[mask] return COO(coords, data, shape=x.shape, has_duplicates=False, sorted=True) def tril(x, k=0): """ Returns an array with all elements above the k-th diagonal set to zero. Parameters ---------- x : COO The input array. k : int, optional The diagonal above which elements are set to zero. The default is zero, which corresponds to the main diagonal. Returns ------- COO The output lower-triangular matrix. Raises ------ ValueError If `x` doesn't have zero fill-values. See Also -------- - [`numpy.tril`][] : NumPy equivalent function """ from .core import COO check_zero_fill_value(x) if not x.ndim >= 2: raise NotImplementedError("sparse.tril is not implemented for scalars or 1-D arrays.") mask = x.coords[-2] + k >= x.coords[-1] coords = x.coords[:, mask] data = x.data[mask] return COO(coords, data, shape=x.shape, has_duplicates=False, sorted=True) def nansum(x, axis=None, keepdims=False, dtype=None, out=None): """ Performs a ``NaN`` skipping sum operation along the given axes. Uses all axes by default. Parameters ---------- x : SparseArray The array to perform the reduction on. axis : Union[int, Iterable[int]], optional The axes along which to sum. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. dtype : numpy.dtype The data type of the output array. Returns ------- COO The reduced output sparse array. See Also -------- - [`sparse.COO.sum`][] : Function without ``NaN`` skipping. - [`numpy.nansum`][] : Equivalent Numpy function. """ assert out is None x = asCOO(x, name="nansum") return nanreduce(x, np.add, axis=axis, keepdims=keepdims, dtype=dtype) def nanmean(x, axis=None, keepdims=False, dtype=None, out=None): """ Performs a `NaN` skipping mean operation along the given axes. Uses all axes by default. Parameters ---------- x : SparseArray The array to perform the reduction on. axis : Union[int, Iterable[int]], optional The axes along which to compute the mean. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. dtype : numpy.dtype The data type of the output array. Returns ------- COO The reduced output sparse array. See Also -------- - [`sparse.COO.mean`][] : Function without `NaN` skipping. - [`numpy.nanmean`][] : Equivalent Numpy function. """ assert out is None x = asCOO(x, name="nanmean") if not (np.issubdtype(x.dtype, np.floating) or np.issubdtype(x.dtype, np.complexfloating)): return x.mean(axis=axis, keepdims=keepdims, dtype=dtype) mask = np.isnan(x) x2 = where(mask, 0, x) # Count the number non-nan elements along axis nancount = mask.sum(axis=axis, dtype="i8", keepdims=keepdims) if axis is None: axis = tuple(range(x.ndim)) elif not isinstance(axis, tuple): axis = (axis,) den = reduce(operator.mul, (x.shape[i] for i in axis), 1) den -= nancount if (den == 0).any(): warnings.warn("Mean of empty slice", RuntimeWarning, stacklevel=1) num = np.sum(x2, axis=axis, dtype=dtype, keepdims=keepdims) with np.errstate(invalid="ignore", divide="ignore"): if num.ndim: return np.true_divide(num, den, casting="unsafe") return (num / den).astype(dtype if dtype is not None else x.dtype) def nanmax(x, axis=None, keepdims=False, dtype=None, out=None): """ Maximize along the given axes, skipping `NaN` values. Uses all axes by default. Parameters ---------- x : SparseArray The array to perform the reduction on. axis : Union[int, Iterable[int]], optional The axes along which to maximize. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. dtype : numpy.dtype The data type of the output array. Returns ------- COO The reduced output sparse array. See Also -------- - [`sparse.COO.max`][] : Function without `NaN` skipping. - [`numpy.nanmax`][] : Equivalent Numpy function. """ assert out is None x = asCOO(x, name="nanmax") ar = x.reduce(np.fmax, axis=axis, keepdims=keepdims, dtype=dtype) if (isscalar(ar) and np.isnan(ar)) or np.isnan(ar.data).any(): warnings.warn("All-NaN slice encountered", RuntimeWarning, stacklevel=1) return ar def nanmin(x, axis=None, keepdims=False, dtype=None, out=None): """ Minimize along the given axes, skipping ``NaN`` values. Uses all axes by default. Parameters ---------- x : SparseArray The array to perform the reduction on. axis : Union[int, Iterable[int]], optional The axes along which to minimize. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. dtype : numpy.dtype The data type of the output array. Returns ------- COO The reduced output sparse array. See Also -------- - [`sparse.COO.min`][] : Function without `NaN` skipping. - [`numpy.nanmin`][] : Equivalent Numpy function. """ assert out is None x = asCOO(x, name="nanmin") ar = x.reduce(np.fmin, axis=axis, keepdims=keepdims, dtype=dtype) if (isscalar(ar) and np.isnan(ar)) or np.isnan(ar.data).any(): warnings.warn("All-NaN slice encountered", RuntimeWarning, stacklevel=1) return ar def nanprod(x, axis=None, keepdims=False, dtype=None, out=None): """ Performs a product operation along the given axes, skipping `NaN` values. Uses all axes by default. Parameters ---------- x : SparseArray The array to perform the reduction on. axis : Union[int, Iterable[int]], optional The axes along which to multiply. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. dtype : numpy.dtype The data type of the output array. Returns ------- COO The reduced output sparse array. See Also -------- - [`sparse.COO.prod`][] : Function without `NaN` skipping. - [`numpy.nanprod`][] : Equivalent Numpy function. """ assert out is None x = asCOO(x) return nanreduce(x, np.multiply, axis=axis, keepdims=keepdims, dtype=dtype) def where(condition, x=None, y=None): """ Select values from either ``x`` or ``y`` depending on ``condition``. If ``x`` and ``y`` are not given, returns indices where ``condition`` is nonzero. Performs the equivalent of [`numpy.where`][]. Parameters ---------- condition : SparseArray The condition based on which to select values from either ``x`` or ``y``. x : SparseArray, optional The array to select values from if ``condition`` is nonzero. y : SparseArray, optional The array to select values from if ``condition`` is zero. Returns ------- COO The output array with selected values if `x` and `y` are given; else where the array is nonzero. Raises ------ ValueError If the operation would produce a dense result; or exactly one of `x` and `y` are given. See Also -------- [`numpy.where`][] : Equivalent Numpy function. """ from .._umath import elemwise x_given = x is not None y_given = y is not None if not (x_given or y_given): check_zero_fill_value(condition) condition = asCOO(condition, name=str(np.where)) return tuple(condition.coords) if x_given != y_given: raise ValueError("either both or neither of x and y should be given") return elemwise(np.where, condition, x, y) def argwhere(a): """ Find the indices of array elements that are non-zero, grouped by element. Parameters ---------- a : array_like Input data. Returns ------- index_array : numpy.ndarray See Also -------- [`sparse.where`][], [`sparse.COO.nonzero`][] Examples -------- >>> import sparse >>> x = sparse.COO(np.arange(6).reshape((2, 3))) >>> sparse.argwhere(x > 1) array([[0, 2], [1, 0], [1, 1], [1, 2]]) """ return np.transpose(a.nonzero()) def argmax(x, /, *, axis=None, keepdims=False): """ Returns the indices of the maximum values along a specified axis. When the maximum value occurs multiple times, only the indices corresponding to the first occurrence are returned. Parameters ---------- x : SparseArray Input array. The fill value must be ``0.0`` and all non-zero values must be greater than ``0.0``. axis : int, optional Axis along which to search. If ``None``, the function must return the index of the maximum value of the flattened array. Default: ``None``. keepdims : bool, optional If ``True``, the reduced axes (dimensions) must be included in the result as singleton dimensions, and, accordingly, the result must be compatible with the input array. Otherwise, if ``False``, the reduced axes (dimensions) must not be included in the result. Default: ``False``. Returns ------- out : numpy.ndarray If ``axis`` is ``None``, a zero-dimensional array containing the index of the first occurrence of the maximum value. Otherwise, a non-zero-dimensional array containing the indices of the maximum values. """ return _arg_minmax_common(x, axis=axis, keepdims=keepdims, mode="max") def argmin(x, /, *, axis=None, keepdims=False): """ Returns the indices of the minimum values along a specified axis. When the minimum value occurs multiple times, only the indices corresponding to the first occurrence are returned. Parameters ---------- x : SparseArray Input array. The fill value must be ``0.0`` and all non-zero values must be less than ``0.0``. axis : int, optional Axis along which to search. If ``None``, the function must return the index of the minimum value of the flattened array. Default: ``None``. keepdims : bool, optional If ``True``, the reduced axes (dimensions) must be included in the result as singleton dimensions, and, accordingly, the result must be compatible with the input array. Otherwise, if ``False``, the reduced axes (dimensions) must not be included in the result. Default: ``False``. Returns ------- out : numpy.ndarray If ``axis`` is ``None``, a zero-dimensional array containing the index of the first occurrence of the minimum value. Otherwise, a non-zero-dimensional array containing the indices of the minimum values. """ return _arg_minmax_common(x, axis=axis, keepdims=keepdims, mode="min") def _replace_nan(array, value): """ Replaces ``NaN``s in ``array`` with ``value``. Parameters ---------- array : COO The input array. value : numpy.number The values to replace ``NaN`` with. Returns ------- COO A copy of ``array`` with the ``NaN``s replaced. """ if not np.issubdtype(array.dtype, np.floating): return array return where(np.isnan(array), value, array) def nanreduce(x, method, identity=None, axis=None, keepdims=False, **kwargs): """ Performs an `NaN` skipping reduction on this array. See the documentation on [`sparse.COO.reduce`][] for examples. Parameters ---------- x : COO The array to reduce. method : numpy.ufunc The method to use for performing the reduction. identity : numpy.number The identity value for this reduction. Inferred from ``method`` if not given. Note that some ``ufunc`` objects don't have this, so it may be necessary to give it. axis : Union[int, Iterable[int]], optional The axes along which to perform the reduction. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. **kwargs : dict Any extra arguments to pass to the reduction operation. Returns ------- COO The result of the reduction operation. Raises ------ ValueError If reducing an all-zero axis would produce a nonzero result. See Also -------- [`sparse.COO.reduce`][] : Similar method without `NaN` skipping functionality. """ arr = _replace_nan(x, method.identity if identity is None else identity) return arr.reduce(method, axis, keepdims, **kwargs) def roll(a, shift, axis=None): """ Shifts elements of an array along specified axis. Elements that roll beyond the last position are circulated and re-introduced at the first. Parameters ---------- a : COO Input array shift : int or tuple of ints Number of index positions that elements are shifted. If a tuple is provided, then axis must be a tuple of the same size, and each of the given axes is shifted by the corresponding number. If an int while axis is a tuple of ints, then broadcasting is used so the same shift is applied to all axes. axis : int or tuple of ints, optional Axis or tuple specifying multiple axes. By default, the array is flattened before shifting, after which the original shape is restored. Returns ------- res : ndarray Output array, with the same shape as a. """ from .core import COO, as_coo a = as_coo(a) # roll flattened array if axis is None: return roll(a.reshape((-1,)), shift, 0).reshape(a.shape) # roll across specified axis # parse axis input, wrap in tuple axis = normalize_axis(axis, a.ndim) if not isinstance(axis, tuple): axis = (axis,) # make shift iterable if not isinstance(shift, Iterable): shift = (shift,) elif np.ndim(shift) > 1: raise ValueError("'shift' and 'axis' must be integers or 1D sequences.") # handle broadcasting if len(shift) == 1: shift = np.full(len(axis), shift) # check if dimensions are consistent if len(axis) != len(shift): raise ValueError("If 'shift' is a 1D sequence, 'axis' must have equal length.") if not can_store(a.coords.dtype, max(a.shape + shift)): raise ValueError( f"cannot roll with coords.dtype {a.coords.dtype} and shift {shift}. Try casting coords to a larger dtype." ) # shift elements coords, data = np.copy(a.coords), np.copy(a.data) try: for sh, ax in zip(shift, axis, strict=True): coords[ax] += sh coords[ax] %= a.shape[ax] except TypeError as e: if is_unsigned_dtype(coords.dtype): raise ValueError( f"rolling with coords.dtype as {coords.dtype} is not safe. Try using a signed dtype." ) from e return COO( coords, data=data, shape=a.shape, has_duplicates=False, fill_value=a.fill_value, ) def diagonal(a, offset=0, axis1=0, axis2=1): """ Extract diagonal from a COO array. The equivalent of [`numpy.diagonal`][]. Parameters ---------- a : COO The array to perform the operation on. offset : int, optional Offset of the diagonal from the main diagonal. Defaults to main diagonal (0). axis1 : int, optional First axis from which the diagonals should be taken. Defaults to first axis (0). axis2 : int, optional Second axis from which the diagonals should be taken. Defaults to second axis (1). Examples -------- >>> import sparse >>> x = sparse.as_coo(np.arange(9).reshape(3, 3)) >>> sparse.diagonal(x).todense() array([0, 4, 8]) >>> sparse.diagonal(x, offset=1).todense() array([1, 5]) >>> x = sparse.as_coo(np.arange(12).reshape((2, 3, 2))) >>> x_diag = sparse.diagonal(x, axis1=0, axis2=2) >>> x_diag.shape (3, 2) >>> x_diag.todense() array([[ 0, 7], [ 2, 9], [ 4, 11]]) Returns ------- out: COO The result of the operation. Raises ------ ValueError If a.shape[axis1] != a.shape[axis2] See Also -------- [`numpy.diagonal`][] : NumPy equivalent function """ from .core import COO if a.shape[axis1] != a.shape[axis2]: raise ValueError("a.shape[axis1] != a.shape[axis2]") diag_axes = [axis for axis in range(len(a.shape)) if axis != axis1 and axis != axis2] + [axis1] diag_shape = [a.shape[axis] for axis in diag_axes] diag_shape[-1] -= abs(offset) diag_idx = _diagonal_idx(a.coords, axis1, axis2, offset) diag_coords = [a.coords[axis][diag_idx] for axis in diag_axes] diag_data = a.data[diag_idx] return COO(diag_coords, diag_data, diag_shape) def diagonalize(a, axis=0): """ Diagonalize a COO array. The new dimension is appended at the end. !!! warning [`sparse.diagonalize`][] is not [numpy][] compatible as there is no direct [numpy][] equivalent. The API may change in the future. Parameters ---------- a : Union[COO, np.ndarray, scipy.sparse.spmatrix] The array to diagonalize. axis : int, optional The axis to diagonalize. Defaults to first axis (0). Examples -------- >>> import sparse >>> x = sparse.as_coo(np.arange(1, 4)) >>> sparse.diagonalize(x).todense() array([[1, 0, 0], [0, 2, 0], [0, 0, 3]]) >>> x = sparse.as_coo(np.arange(24).reshape((2, 3, 4))) >>> x_diag = sparse.diagonalize(x, axis=1) >>> x_diag.shape (2, 3, 4, 3) [`sparse.diagonalize`][] is the inverse of [`sparse.diagonal`][] >>> a = sparse.random((3, 3, 3, 3, 3), density=0.3) >>> a_diag = sparse.diagonalize(a, axis=2) >>> (sparse.diagonal(a_diag, axis1=2, axis2=5) == a.transpose([0, 1, 3, 4, 2])).all() np.True_ Returns ------- out: COO The result of the operation. See Also -------- [`numpy.diag`][] : NumPy equivalent for 1D array """ from .core import COO, as_coo a = as_coo(a) diag_shape = a.shape + (a.shape[axis],) diag_coords = np.vstack([a.coords, a.coords[axis]]) return COO(diag_coords, a.data, diag_shape) def isposinf(x, out=None): """ Test element-wise for positive infinity, return result as sparse `bool` array. Parameters ---------- x Input out, optional Output array Examples -------- >>> import sparse >>> x = sparse.as_coo(np.array([np.inf])) >>> sparse.isposinf(x).todense() array([ True]) See Also -------- [`numpy.isposinf`][] : The NumPy equivalent """ from sparse import elemwise return elemwise(lambda x, out=None, dtype=None: np.isposinf(x, out=out), x, out=out) def isneginf(x, out=None): """ Test element-wise for negative infinity, return result as sparse `bool` array. Parameters ---------- x Input out, optional Output array Examples -------- >>> import sparse >>> x = sparse.as_coo(np.array([-np.inf])) >>> sparse.isneginf(x).todense() array([ True]) See Also -------- [`numpy.isneginf`][] : The NumPy equivalent """ from sparse import elemwise return elemwise(lambda x, out=None, dtype=None: np.isneginf(x, out=out), x, out=out) def result_type(*arrays_and_dtypes): """Returns the type that results from applying the NumPy type promotion rules to the arguments. See Also -------- [`numpy.result_type`][] : The NumPy equivalent """ return np.result_type(*(_as_result_type_arg(x) for x in arrays_and_dtypes)) def _as_result_type_arg(x): if not isinstance(x, SparseArray): return x if x.ndim > 0: return x.dtype # 0-dimensional arrays give different result_type outputs than their dtypes return x.todense() @numba.jit(nopython=True, nogil=True) def _diagonal_idx(coordlist, axis1, axis2, offset): """ Utility function that returns all indices that correspond to a diagonal element. Parameters ---------- coordlist : list of lists Coordinate indices. axis1, axis2 : int The axes of the diagonal. offset : int Offset of the diagonal from the main diagonal. Defaults to main diagonal (0). """ return np.array([i for i in range(len(coordlist[axis1])) if coordlist[axis1][i] + offset == coordlist[axis2][i]]) def clip(a, min=None, max=None, out=None): """ Clip (limit) the values in the array. Return an array whose values are limited to ``[min, max]``. One of min or max must be given. Parameters ---------- a min : scalar or `SparseArray` or `None` Minimum value. If `None`, clipping is not performed on lower interval edge. max : scalar or `SparseArray` or `None` Maximum value. If `None`, clipping is not performed on upper interval edge. out : SparseArray, optional If provided, the results will be placed in this array. It may be the input array for in-place clipping. `out` must be of the right shape to hold the output. Its type is preserved. Returns ------- clipped_array : SparseArray An array with the elements of `self`, but where values < `min` are replaced with `min`, and those > `max` with `max`. Examples -------- >>> import sparse >>> x = sparse.COO.from_numpy([0, 0, 0, 1, 2, 3]) >>> sparse.clip(x, min=1).todense() # doctest: +NORMALIZE_WHITESPACE array([1, 1, 1, 1, 2, 3]) >>> sparse.clip(x, max=1).todense() # doctest: +NORMALIZE_WHITESPACE array([0, 0, 0, 1, 1, 1]) >>> sparse.clip(x, min=1, max=2).todense() # doctest: +NORMALIZE_WHITESPACE array([1, 1, 1, 1, 2, 2]) See Also -------- numpy.clip : Equivalent NumPy function """ a = asCOO(a, name="clip") return a.clip(min, max) def expand_dims(x, /, *, axis=0): """ Expands the shape of an array by inserting a new axis (dimension) of size one at the position specified by ``axis``. Parameters ---------- a : COO Input COO array. axis : int Position in the expanded axes where the new axis is placed. Returns ------- result : COO An expanded output COO array having the same data type as ``x``. Examples -------- >>> import sparse >>> x = sparse.COO.from_numpy([[1, 0, 0, 0, 2, -3]]) >>> x.shape (1, 6) >>> y1 = sparse.expand_dims(x, axis=1) >>> y1.shape (1, 1, 6) >>> y2 = sparse.expand_dims(x, axis=2) >>> y2.shape (1, 6, 1) """ x = _validate_coo_input(x) if not isinstance(axis, int): raise IndexError(f"Invalid axis position: {axis}") axis = normalize_axis(axis, x.ndim + 1) new_coords = np.insert(x.coords, obj=axis, values=np.zeros(x.nnz, dtype=np.intp), axis=0) new_shape = list(x.shape) new_shape.insert(axis, 1) new_shape = tuple(new_shape) from .core import COO return COO( new_coords, x.data, shape=new_shape, fill_value=x.fill_value, ) def flip(x, /, *, axis=None): """ Reverses the order of elements in an array along the given axis. The shape of the array is preserved. Parameters ---------- a : COO Input COO array. axis : int or tuple of ints, optional Axis (or axes) along which to flip. If ``axis`` is ``None``, the function must flip all input array axes. If ``axis`` is negative, the function must count from the last dimension. If provided more than one axis, the function must flip only the specified axes. Default: ``None``. Returns ------- result : COO An output array having the same data type and shape as ``x`` and whose elements, relative to ``x``, are reordered. """ x = _validate_coo_input(x) if axis is None: axis = range(x.ndim) if not isinstance(axis, Iterable): axis = (axis,) new_coords = x.coords.copy() for ax in axis: new_coords[ax, :] = x.shape[ax] - 1 - x.coords[ax, :] from .core import COO return COO( new_coords, x.data, shape=x.shape, fill_value=x.fill_value, ) # Array API set functions class UniqueCountsResult(NamedTuple): values: np.ndarray counts: np.ndarray def unique_counts(x, /): """ Returns the unique elements of an input array `x`, and the corresponding counts for each unique element in `x`. Parameters ---------- x : COO Input COO array. It will be flattened if it is not already 1-D. Returns ------- out : namedtuple The result containing: * values - The unique elements of an input array. * counts - The corresponding counts for each unique element. Raises ------ ValueError If the input array is in a different format than COO. Examples -------- >>> import sparse >>> x = sparse.COO.from_numpy([1, 0, 2, 1, 2, -3]) >>> sparse.unique_counts(x) UniqueCountsResult(values=array([-3, 0, 1, 2]), counts=array([1, 1, 2, 2])) """ x = _validate_coo_input(x) x = x.flatten() values, counts = np.unique(x.data, return_counts=True) if x.nnz < x.size: values = np.concatenate([[x.fill_value], values]) counts = np.concatenate([[x.size - x.nnz], counts]) sorted_indices = np.argsort(values) values[sorted_indices] = values.copy() counts[sorted_indices] = counts.copy() return UniqueCountsResult(values, counts) def unique_values(x, /): """ Returns the unique elements of an input array `x`. Parameters ---------- x : COO Input COO array. It will be flattened if it is not already 1-D. Returns ------- out : ndarray The unique elements of an input array. Raises ------ ValueError If the input array is in a different format than COO. Examples -------- >>> import sparse >>> x = sparse.COO.from_numpy([1, 0, 2, 1, 2, -3]) >>> sparse.unique_values(x) array([-3, 0, 1, 2]) """ x = _validate_coo_input(x) x = x.flatten() values = np.unique(x.data) if x.nnz < x.size: values = np.sort(np.concatenate([[x.fill_value], values])) return values def sort(x, /, *, axis=-1, descending=False, stable=False): """ Returns a sorted copy of an input array ``x``. Parameters ---------- x : SparseArray Input array. Should have a real-valued data type. axis : int Axis along which to sort. If set to ``-1``, the function must sort along the last axis. Default: ``-1``. descending : bool Sort order. If ``True``, the array must be sorted in descending order (by value). If ``False``, the array must be sorted in ascending order (by value). Default: ``False``. stable : bool Whether the sort is stable. Only ``False`` is supported currently. Returns ------- out : COO A sorted array. Raises ------ ValueError If the input array isn't and can't be converted to COO format. Examples -------- >>> import sparse >>> x = sparse.COO.from_numpy([1, 0, 2, 0, 2, -3]) >>> sparse.sort(x).todense() array([-3, 0, 0, 1, 2, 2]) >>> sparse.sort(x, descending=True).todense() array([ 2, 2, 1, 0, 0, -3]) """ from .._common import moveaxis from .core import COO x = _validate_coo_input(x) if stable: raise ValueError("`stable=True` isn't currently supported.") original_ndim = x.ndim if x.ndim == 1: x = x[None, :] axis = -1 x = moveaxis(x, source=axis, destination=-1) x_shape = x.shape x = x.reshape((-1, x_shape[-1])) new_coords, new_data = _sort_coo(x.coords, x.data, x.fill_value, sort_axis_len=x_shape[-1], descending=descending) x = COO(new_coords, new_data, x.shape, has_duplicates=False, sorted=True, fill_value=x.fill_value) x = x.reshape(x_shape[:-1] + (x_shape[-1],)) x = moveaxis(x, source=-1, destination=axis) if original_ndim == x.ndim: return x x = x.squeeze() if x.shape == (): return x[None] return x def take(x, indices, /, *, axis=None): """ Returns elements of an array along an axis. Parameters ---------- x : SparseArray Input array. indices : ndarray Array indices. The array must be one-dimensional and have an integer data type. axis : int Axis over which to select values. If ``axis`` is negative, the function must determine the axis along which to select values by counting from the last dimension. For ``None``, the flattened input array is used. Default: ``None``. Returns ------- out : COO A COO array with requested indices. Raises ------ ValueError If the input array isn't and can't be converted to COO format. """ x = _validate_coo_input(x) if axis is None: x = x.flatten() return x[indices] axis = normalize_axis(axis, x.ndim) full_index = (slice(None),) * axis + (indices, ...) return x[full_index] def _validate_coo_input(x: Any): from .._common import _is_scipy_sparse_obj from .core import COO if _is_scipy_sparse_obj(x): x = COO.from_scipy_sparse(x) elif not isinstance(x, SparseArray): raise ValueError(f"Input must be an instance of SparseArray, but it's {type(x)}.") elif not isinstance(x, COO): x = x.asformat(COO) return x @numba.jit(nopython=True, nogil=True) def _sort_coo( coords: np.ndarray, data: np.ndarray, fill_value: float, sort_axis_len: int, descending: bool ) -> tuple[np.ndarray, np.ndarray]: assert coords.shape[0] == 2 group_coords = coords[0, :] sort_coords = coords[1, :] data = data.copy() result_indices = np.empty_like(sort_coords) # We iterate through all groups and sort each one of them. # first and last index of a group is tracked. prev_group = -1 group_first_idx = -1 group_last_idx = -1 # We add `-1` sentinel to know when the last group ends for idx, group in enumerate(np.append(group_coords, -1)): if group == prev_group: continue if prev_group != -1: group_last_idx = idx group_slice = slice(group_first_idx, group_last_idx) group_size = group_last_idx - group_first_idx # SORT VALUES if group_size > 1: # np.sort in numba doesn't support `np.sort`'s arguments so `stable` # keyword can't be supported. # https://numba.pydata.org/numba-doc/latest/reference/numpysupported.html#other-methods data[group_slice] = np.sort(data[group_slice]) if descending: data[group_slice] = data[group_slice][::-1] # SORT INDICES fill_value_count = sort_axis_len - group_size indices = np.arange(group_size) # find a place where fill_value would be for pos in range(group_size): if (not descending and fill_value < data[group_slice][pos]) or ( descending and fill_value > data[group_slice][pos] ): indices[pos:] += fill_value_count break result_indices[group_first_idx:group_last_idx] = indices prev_group = group group_first_idx = idx return np.vstack((group_coords, result_indices)), data @numba.jit(nopython=True, nogil=True) def _compute_minmax_args( coords: np.ndarray, data: np.ndarray, reduce_size: int, fill_value: float, max_mode_flag: bool, ) -> tuple[np.ndarray, np.ndarray]: assert coords.shape[0] == 2 reduce_coords = coords[0, :] index_coords = coords[1, :] result_indices = np.unique(index_coords) result_data = [] # we iterate through each trace for result_index in np.nditer(result_indices): mask = index_coords == result_index masked_reduce_coords = reduce_coords[mask] masked_data = data[mask] compared_data = operator.gt(masked_data, fill_value) if max_mode_flag else operator.lt(masked_data, fill_value) if np.any(compared_data) or len(masked_data) == reduce_size: # best value is a non-fill value best_arg = np.argmax(masked_data) if max_mode_flag else np.argmin(masked_data) result_data.append(masked_reduce_coords[best_arg]) else: # best value is a fill value, find the first occurrence of it current_coord = np.array(-1, dtype=coords.dtype) found = False for idx, new_coord in enumerate(np.nditer(np.sort(masked_reduce_coords))): # there is at least one fill value between consecutive non-fill values if new_coord - current_coord > 1: result_data.append(idx) found = True break current_coord = new_coord # get the first fill value after all non-fill values if not found: result_data.append(current_coord + 1) return (result_indices, np.array(result_data, dtype=np.intp)) def _arg_minmax_common( x: SparseArray, axis: int | None, keepdims: bool, mode: str, ): """ Internal implementation for argmax and argmin functions. """ assert mode in ("max", "min") max_mode_flag = mode == "max" x = _validate_coo_input(x) if not isinstance(axis, int | type(None)): raise ValueError(f"`axis` must be `int` or `None`, but it's: {type(axis)}.") if isinstance(axis, int) and axis >= x.ndim: raise ValueError(f"`axis={axis}` is out of bounds for array of dimension {x.ndim}.") if x.ndim == 0: raise ValueError("Input array must be at least 1-D, but it's 0-D.") # If `axis` is None then we need to flatten the input array and memorize # the original dimensionality for the final reshape operation. axis_none_original_ndim: int | None = None if axis is None: axis_none_original_ndim = x.ndim x = x.reshape(-1)[:, None] axis = 0 # A 1-D array must have one more singleton dimension. if axis == 0 and x.ndim == 1: x = x[:, None] # We need to move `axis` to the front. new_transpose = list(range(x.ndim)) new_transpose.insert(0, new_transpose.pop(axis)) new_transpose = tuple(new_transpose) # And reshape it to 2-D (reduce axis, the rest of axes flattened) new_shape = list(x.shape) new_shape.insert(0, new_shape.pop(axis)) new_shape = tuple(new_shape) x = x.transpose(new_transpose) x = x.reshape((new_shape[0], np.prod(new_shape[1:]))) # Compute max/min arguments result_indices, result_data = _compute_minmax_args( x.coords.copy(), x.data.copy(), reduce_size=x.shape[0], fill_value=x.fill_value, max_mode_flag=max_mode_flag, ) from .core import COO result = COO(result_indices, result_data, shape=(x.shape[1],), fill_value=0, prune=True) # Let's reshape the result to the original shape. result = result.reshape((1, *new_shape[1:])) new_transpose = list(range(result.ndim)) new_transpose.insert(axis, new_transpose.pop(0)) result = result.transpose(new_transpose) # If `axis=None` we need to reshape flattened array into original dimensionality. if axis_none_original_ndim is not None: result = result.reshape([1 for _ in range(axis_none_original_ndim)]) return result if keepdims else result.squeeze() def matrix_transpose(x, /): """ Transposes a matrix or a stack of matrices. Parameters ---------- x : SparseArray Input array. Returns ------- out : COO Transposed COO array. Raises ------ ValueError If the input array isn't and can't be converted to COO format, or if ``x.ndim < 2``. """ if hasattr(x, "ndim") and x.ndim < 2: raise ValueError("`x.ndim >= 2` must hold.") x = _validate_coo_input(x) transpose_axes = list(range(x.ndim)) transpose_axes[-2:] = transpose_axes[-2:][::-1] return x.transpose(transpose_axes) sparse-0.18.0/sparse/numba_backend/_coo/core.py000066400000000000000000001435471514474157100214130ustar00rootroot00000000000000import copy as _copy import operator import warnings from collections import defaultdict, deque from collections.abc import Iterable, Iterator, Sized from functools import reduce import numba import numpy as np from numpy.lib.mixins import NDArrayOperatorsMixin from .._sparse_array import SparseArray from .._umath import broadcast_to from .._utils import ( _zero_of_dtype, can_store, check_fill_value, check_zero_fill_value, equivalent, normalize_axis, ) from .indexing import getitem class COO(SparseArray, NDArrayOperatorsMixin): # lgtm [py/missing-equals] """ A sparse multidimensional array. This is stored in COO format. It depends on NumPy and Scipy.sparse for computation, but supports arrays of arbitrary dimension. Parameters ---------- coords : numpy.ndarray (COO.ndim, COO.nnz) An array holding the index locations of every value Should have shape (number of dimensions, number of non-zeros). data : numpy.ndarray (COO.nnz,) An array of Values. A scalar can also be supplied if the data is the same across all coordinates. If not given, defers to [`sparse.as_coo`][]. shape : tuple[int] (COO.ndim,) The shape of the array. has_duplicates : bool, optional A value indicating whether the supplied value for [`sparse.COO.coords`][] has duplicates. Note that setting this to `False` when `coords` does have duplicates may result in undefined behaviour. sorted : bool, optional A value indicating whether the values in `coords` are sorted. Note that setting this to `True` when [`sparse.COO.coords`][] isn't sorted may result in undefined behaviour. prune : bool, optional A flag indicating whether or not we should prune any fill-values present in `data`. cache : bool, optional Whether to enable cacheing for various operations. See [`sparse.COO.enable_caching`][]. fill_value: scalar, optional The fill value for this array. Attributes ---------- coords : numpy.ndarray (ndim, nnz) An array holding the coordinates of every nonzero element. data : numpy.ndarray (nnz,) An array holding the values corresponding to [`sparse.COO.coords`][]. shape : tuple[int] (ndim,) The dimensions of this array. See Also -------- - [`sparse.DOK`][]: A mostly write-only sparse array. - [`sparse.as_coo`][]: Convert any given format to [`sparse.COO`][]. Examples -------- You can create [`sparse.COO`][] objects from Numpy arrays. >>> x = np.eye(4, dtype=np.uint8) >>> x[2, 3] = 5 >>> s = COO.from_numpy(x) >>> s >>> s.data # doctest: +NORMALIZE_WHITESPACE array([1, 1, 1, 5, 1], dtype=uint8) >>> s.coords # doctest: +NORMALIZE_WHITESPACE array([[0, 1, 2, 2, 3], [0, 1, 2, 3, 3]]) [`sparse.COO`][] objects support basic arithmetic and binary operations. >>> x2 = np.eye(4, dtype=np.uint8) >>> x2[3, 2] = 5 >>> s2 = COO.from_numpy(x2) >>> (s + s2).todense() # doctest: +NORMALIZE_WHITESPACE array([[2, 0, 0, 0], [0, 2, 0, 0], [0, 0, 2, 5], [0, 0, 5, 2]], dtype=uint8) >>> (s * s2).todense() # doctest: +NORMALIZE_WHITESPACE array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]], dtype=uint8) Binary operations support broadcasting. >>> x3 = np.zeros((4, 1), dtype=np.uint8) >>> x3[2, 0] = 1 >>> s3 = COO.from_numpy(x3) >>> (s * s3).todense() # doctest: +NORMALIZE_WHITESPACE array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 5], [0, 0, 0, 0]], dtype=uint8) [`sparse.COO`][] objects also support dot products and reductions. >>> s.dot(s.T).sum(axis=0).todense() # doctest: +NORMALIZE_WHITESPACE array([ 1, 1, 31, 6], dtype=uint64) You can use Numpy `ufunc` operations on [`sparse.COO`][] arrays as well. >>> np.sum(s, axis=1).todense() # doctest: +NORMALIZE_WHITESPACE array([1, 1, 6, 1], dtype=uint64) >>> np.round(np.sqrt(s, dtype=np.float64), decimals=1).todense() # doctest: +SKIP array([[ 1. , 0. , 0. , 0. ], [ 0. , 1. , 0. , 0. ], [ 0. , 0. , 1. , 2.2], [ 0. , 0. , 0. , 1. ]]) Operations that will result in a dense array will usually result in a different fill value, such as the following. >>> np.exp(s) You can also create [`sparse.COO`][] arrays from coordinates and data. >>> coords = [[0, 0, 0, 1, 1], [0, 1, 2, 0, 3], [0, 3, 2, 0, 1]] >>> data = [1, 2, 3, 4, 5] >>> s4 = COO(coords, data, shape=(3, 4, 5)) >>> s4 If the data is same across all coordinates, you can also specify a scalar. >>> coords = [[0, 0, 0, 1, 1], [0, 1, 2, 0, 3], [0, 3, 2, 0, 1]] >>> data = 1 >>> s5 = COO(coords, data, shape=(3, 4, 5)) >>> s5 Following scipy.sparse conventions you can also pass these as a tuple with rows and columns >>> rows = [0, 1, 2, 3, 4] >>> cols = [0, 0, 0, 1, 1] >>> data = [10, 20, 30, 40, 50] >>> z = COO((data, (rows, cols)), shape=(5, 2)) >>> z.todense() # doctest: +NORMALIZE_WHITESPACE array([[10, 0], [20, 0], [30, 0], [ 0, 40], [ 0, 50]]) You can also pass a dictionary or iterable of index/value pairs. Repeated indices imply summation: >>> d = {(0, 0, 0): 1, (1, 2, 3): 2, (1, 1, 0): 3} >>> COO(d, shape=(2, 3, 4)) >>> L = [((0, 0), 1), ((1, 1), 2), ((0, 0), 3)] >>> COO(L, shape=(2, 2)).todense() # doctest: +NORMALIZE_WHITESPACE array([[4, 0], [0, 2]]) You can convert [`sparse.DOK`][] arrays to [`sparse.COO`][] arrays. >>> from sparse import DOK >>> s6 = DOK((5, 5), dtype=np.int64) >>> s6[1:3, 1:3] = [[4, 5], [6, 7]] >>> s6 >>> s7 = s6.asformat("coo") >>> s7 >>> s7.todense() # doctest: +NORMALIZE_WHITESPACE array([[0, 0, 0, 0, 0], [0, 4, 5, 0, 0], [0, 6, 7, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]) """ __array_priority__ = 12 def __init__( self, coords, data=None, shape=None, has_duplicates=True, sorted=False, prune=False, cache=False, fill_value=None, idx_dtype=None, ): if isinstance(coords, COO): self._make_shallow_copy_of(coords) if data is not None or shape is not None: raise ValueError("If `coords` is `COO`, then no other arguments should be provided.") if fill_value is not None: self.fill_value = self.data.dtype.type(fill_value) return self._cache = None if cache: self.enable_caching() if data is None: arr = as_coo(coords, shape=shape, fill_value=fill_value, idx_dtype=idx_dtype) self._make_shallow_copy_of(arr) if cache: self.enable_caching() return self.data = np.asarray(data) self.coords = np.asarray(coords) if self.coords.ndim == 1: if self.coords.size == 0 and shape is not None: self.coords = self.coords.reshape((len(shape), len(data))) else: self.coords = self.coords[None, :] if self.data.ndim == 0: self.data = np.broadcast_to(self.data, self.coords.shape[1]) if self.data.ndim != 1: raise ValueError("`data` must be a scalar or 1-dimensional.") if shape is None: raise ValueError("`shape` was not provided.") if not isinstance(shape, Iterable): shape = (shape,) if isinstance(shape, np.ndarray): shape = tuple(shape) if shape and not self.coords.size: self.coords = np.zeros((len(shape) if isinstance(shape, Iterable) else 1, 0), dtype=np.intp) super().__init__(shape, fill_value=fill_value) if idx_dtype: if not can_store(idx_dtype, max(shape)): raise ValueError(f"cannot cast array with shape {shape} to dtype {idx_dtype}.") self.coords = self.coords.astype(idx_dtype) if self.shape: if len(self.data) != self.coords.shape[1]: msg = "The data length does not match the coordinates given.\nlen(data) = {}, but {} coords specified." raise ValueError(msg.format(len(data), self.coords.shape[1])) if len(self.shape) != self.coords.shape[0]: msg = ( "Shape specified by `shape` doesn't match the " "shape of `coords`; len(shape)={} != coords.shape[0]={}" "(and coords.shape={})" ) raise ValueError(msg.format(len(shape), self.coords.shape[0], self.coords.shape)) from .._settings import WARN_ON_TOO_DENSE if WARN_ON_TOO_DENSE and self.nbytes >= self.size * self.data.itemsize: warnings.warn( "Attempting to create a sparse array that takes no less " "memory than than an equivalent dense array. You may want to " "use a dense array here instead.", RuntimeWarning, stacklevel=1, ) if not sorted: self._sort_indices() if has_duplicates: self._sum_duplicates() if prune: self._prune() def __getstate__(self): return (self.coords, self.data, self.shape, self.fill_value) def __setstate__(self, state): self.coords, self.data, self.shape, self.fill_value = state self._cache = None def __dask_tokenize__(self): "Produce a deterministic, content-based hash for dask." from dask.base import normalize_token return normalize_token((type(self), self.coords, self.data, self.shape, self.fill_value)) def copy(self, deep=True): """Return a copy of the array. Parameters ---------- deep : boolean, optional If True (default), the internal coords and data arrays are also copied. Set to ``False`` to only make a shallow copy. """ return _copy.deepcopy(self) if deep else _copy.copy(self) def enable_caching(self): """Enable caching of reshape, transpose, and tocsr/csc operations This enables efficient iterative workflows that make heavy use of csr/csc operations, such as tensordot. This maintains a cache of recent results of reshape and transpose so that operations like tensordot (which uses both internally) store efficiently stored representations for repeated use. This can significantly cut down on computational costs in common numeric algorithms. However, this also assumes that neither this object, nor the downstream objects will have their data mutated. Examples -------- >>> s.enable_caching() # doctest: +SKIP >>> csr1 = s.transpose((2, 0, 1)).reshape((100, 120)).tocsr() # doctest: +SKIP >>> csr2 = s.transpose((2, 0, 1)).reshape((100, 120)).tocsr() # doctest: +SKIP >>> csr1 is csr2 # doctest: +SKIP True """ self._cache = defaultdict(lambda: deque(maxlen=3)) @classmethod def from_numpy(cls, x, fill_value=None, idx_dtype=None): """ Convert the given [`sparse.COO`][] object. Parameters ---------- x : np.ndarray The dense array to convert. fill_value : scalar The fill value of the constructed [`sparse.COO`][] array. Zero if unspecified. Returns ------- COO The converted COO array. Examples -------- >>> x = np.eye(5) >>> s = COO.from_numpy(x) >>> s >>> x[x == 0] = np.nan >>> COO.from_numpy(x, fill_value=np.nan) """ x = np.asanyarray(x).view(type=np.ndarray) if fill_value is None: fill_value = _zero_of_dtype(x.dtype) if x.shape else x coords = np.atleast_2d(np.flatnonzero(~equivalent(x, fill_value))) data = x.ravel()[tuple(coords)] return cls( coords, data, shape=x.size, has_duplicates=False, sorted=True, fill_value=fill_value, idx_dtype=idx_dtype, ).reshape(x.shape) def todense(self): """ Convert this [`sparse.COO`][] array to a dense [`numpy.ndarray`][]. Note that this may take a large amount of memory if the `COO` object's `shape` is large. Returns ------- numpy.ndarray The converted dense array. See Also -------- - [`sparse.DOK.todense`][] : Equivalent `DOK` array method. - [`scipy.sparse.coo_array.todense`][] : Equivalent Scipy method. Examples -------- >>> x = np.random.randint(100, size=(7, 3)) >>> s = COO.from_numpy(x) >>> x2 = s.todense() >>> np.array_equal(x, x2) True """ x = np.full(self.shape, self.fill_value, self.dtype) coords = tuple([self.coords[i, :] for i in range(self.ndim)]) data = self.data if len(coords) != 0: x[coords] = data else: if len(data) != 0: assert data.shape == (1,) x[...] = data[0] return x @classmethod def from_scipy_sparse(cls, x, /, *, fill_value=None): """ Construct a [`sparse.COO`][] array from a [`scipy.sparse.spmatrix`][] Parameters ---------- x : scipy.sparse.spmatrix The sparse matrix to construct the array from. fill_value : scalar The fill-value to use when converting. Returns ------- COO The converted [`sparse.COO`][] object. Examples -------- >>> import scipy.sparse >>> x = scipy.sparse.rand(6, 3, density=0.2) >>> s = COO.from_scipy_sparse(x) >>> np.array_equal(x.todense(), s.todense()) True """ x = x.asformat("coo") if not x.has_canonical_format: x.eliminate_zeros() x.sum_duplicates() def _coords(x): c = getattr(x, "coords", None) if c is None: # legacy support for SciPy sparse matrices c = (x.row, x.col) return c return COO( _coords(x), x.data, shape=x.shape, has_duplicates=not x.has_canonical_format, sorted=x.has_canonical_format, fill_value=fill_value, ) @classmethod def from_iter(cls, x, shape, fill_value=None, dtype=None): """ Converts an iterable in certain formats to a [`sparse.COO`][] array. See examples for details. Parameters ---------- x : Iterable or Iterator The iterable to convert to [`sparse.COO`][]. shape : tuple[int] The shape of the array. fill_value : scalar The fill value for this array. dtype : numpy.dtype The dtype of the input array. Inferred from the input if not given. Returns ------- out : COO The output [`sparse.COO`][] array. Examples -------- You can convert items of the format [`sparse.COO`][]. Here, the first part represents the coordinate and the second part represents the value. >>> x = [((0, 0), 1), ((1, 1), 1)] >>> s = COO.from_iter(x, shape=(2, 2)) >>> s.todense() array([[1, 0], [0, 1]]) You can also have a similar format with a dictionary. >>> x = {(0, 0): 1, (1, 1): 1} >>> s = COO.from_iter(x, shape=(2, 2)) >>> s.todense() array([[1, 0], [0, 1]]) The third supported format is ``(data, (..., row, col))``. >>> x = ([1, 1], ([0, 1], [0, 1])) >>> s = COO.from_iter(x, shape=(2, 2)) >>> s.todense() array([[1, 0], [0, 1]]) You can also pass in a [`collections.abc.Iterator`][] object. >>> x = [((0, 0), 1), ((1, 1), 1)].__iter__() >>> s = COO.from_iter(x, shape=(2, 2)) >>> s.todense() array([[1, 0], [0, 1]]) """ if isinstance(x, dict): x = list(x.items()) if not isinstance(x, Sized): x = list(x) if len(x) != 2 and not all(len(item) == 2 for item in x): raise ValueError("Invalid iterable to convert to COO.") if not x: ndim = 0 if shape is None else len(shape) coords = np.empty((ndim, 0), dtype=np.uint8) data = np.empty((0,), dtype=dtype) shape = () if shape is None else shape elif not isinstance(x[0][0], Iterable): coords = np.stack(x[1], axis=0) data = np.asarray(x[0], dtype=dtype) else: coords = np.array([item[0] for item in x]).T data = np.array([item[1] for item in x], dtype=dtype) if not ( coords.ndim == 2 and data.ndim == 1 and np.issubdtype(coords.dtype, np.integer) and np.all(coords >= 0) ): raise ValueError("Invalid iterable to convert to COO.") return COO(coords, data, shape=shape, fill_value=fill_value) @property def dtype(self): """ The datatype of this array. Returns ------- numpy.dtype The datatype of this array. See Also -------- - [`numpy.ndarray.dtype`][] : Numpy equivalent property. - [`scipy.sparse.coo_array.dtype`][] : Scipy equivalent property. Examples -------- >>> x = (200 * np.random.rand(5, 4)).astype(np.int32) >>> s = COO.from_numpy(x) >>> s.dtype dtype('int32') >>> x.dtype == s.dtype True """ return self.data.dtype @property def nnz(self): """ The number of nonzero elements in this array. Note that any duplicates in `coords` are counted multiple times. Returns ------- int The number of nonzero elements in this array. See Also -------- - [`sparse.DOK.nnz`][] : Equivalent [`sparse.DOK`][] array property. - [`numpy.count_nonzero`][] : A similar Numpy function. - [`scipy.sparse.coo_array.nnz`][] : The Scipy equivalent property. Examples -------- >>> x = np.array([0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 0]) >>> np.count_nonzero(x) np.int64(6) >>> s = COO.from_numpy(x) >>> s.nnz 6 >>> np.count_nonzero(x) == s.nnz np.True_ """ return self.coords.shape[1] @property def format(self): """ The storage format of this array. Returns ------- str The storage format of this array. See Also -------- [`scipy.sparse.dok_matrix.format`][] : The Scipy equivalent property. Examples ------- >>> import sparse >>> s = sparse.random((5, 5), density=0.2, format="dok") >>> s.format 'dok' >>> t = sparse.random((5, 5), density=0.2, format="coo") >>> t.format 'coo' """ return "coo" @property def nbytes(self): """ The number of bytes taken up by this object. Note that for small arrays, this may undercount the number of bytes due to the large constant overhead. Returns ------- int The approximate bytes of memory taken by this object. See Also -------- [`numpy.ndarray.nbytes`][] : The equivalent Numpy property. Examples -------- >>> data = np.arange(6, dtype=np.uint8) >>> coords = np.random.randint(1000, size=(3, 6), dtype=np.uint16) >>> s = COO(coords, data, shape=(1000, 1000, 1000)) >>> s.nbytes 42 """ return self.data.nbytes + self.coords.nbytes def __len__(self): """ Get "length" of array, which is by definition the size of the first dimension. Returns ------- int The size of the first dimension. See Also -------- numpy.ndarray.__len__ : Numpy equivalent property. Examples -------- >>> x = np.zeros((10, 10)) >>> s = COO.from_numpy(x) >>> len(s) 10 """ return self.shape[0] def __sizeof__(self): return self.nbytes __getitem__ = getitem def __str__(self): summary = f"" return self._str_impl(summary) __repr__ = __str__ def _reduce_calc(self, method, axis, keepdims=False, **kwargs): if axis == (None,): axis = tuple(range(self.ndim)) axis = tuple(a if a >= 0 else a + self.ndim for a in axis) neg_axis = tuple(ax for ax in range(self.ndim) if ax not in set(axis)) a = self.transpose(neg_axis + axis) a = a.reshape( ( np.prod([self.shape[d] for d in neg_axis], dtype=np.intp), np.prod([self.shape[d] for d in axis], dtype=np.intp), ) ) data, inv_idx, counts = _grouped_reduce(a.data, a.coords[0], method, **kwargs) n_cols = a.shape[1] arr_attrs = (a, neg_axis, inv_idx) return (data, counts, axis, n_cols, arr_attrs) def _reduce_return(self, data, arr_attrs, result_fill_value): a, neg_axis, inv_idx = arr_attrs coords = a.coords[0:1, inv_idx] out = COO( coords, data, shape=(a.shape[0],), has_duplicates=False, sorted=True, prune=True, fill_value=result_fill_value, ) return out.reshape(tuple(self.shape[d] for d in neg_axis)) def transpose(self, axes=None): """ Returns a new array which has the order of the axes switched. Parameters ---------- axes : Iterable[int], optional The new order of the axes compared to the previous one. Reverses the axes by default. Returns ------- COO The new array with the axes in the desired order. See Also -------- - [`sparse.COO.T`][] : A quick property to reverse the order of the axes. - [`numpy.ndarray.transpose`][] : Numpy equivalent function. Examples -------- We can change the order of the dimensions of any [`sparse.COO`][] array with this function. >>> x = np.add.outer(np.arange(5), np.arange(5)[::-1]) >>> x # doctest: +NORMALIZE_WHITESPACE array([[4, 3, 2, 1, 0], [5, 4, 3, 2, 1], [6, 5, 4, 3, 2], [7, 6, 5, 4, 3], [8, 7, 6, 5, 4]]) >>> s = COO.from_numpy(x) >>> s.transpose((1, 0)).todense() # doctest: +NORMALIZE_WHITESPACE array([[4, 5, 6, 7, 8], [3, 4, 5, 6, 7], [2, 3, 4, 5, 6], [1, 2, 3, 4, 5], [0, 1, 2, 3, 4]]) Note that by default, this reverses the order of the axes rather than switching the last and second-to-last axes as required by some linear algebra operations. >>> x = np.random.rand(2, 3, 4) >>> s = COO.from_numpy(x) >>> s.transpose().shape (4, 3, 2) """ if axes is None: axes = list(reversed(range(self.ndim))) # Normalize all axes indices to positive values axes = normalize_axis(axes, self.ndim) if len(np.unique(axes)) < len(axes): raise ValueError("repeated axis in transpose") if not len(axes) == self.ndim: raise ValueError("axes don't match array") axes = tuple(axes) if axes == tuple(range(self.ndim)): return self if self._cache is not None: for ax, value in self._cache["transpose"]: if ax == axes: return value shape = tuple(self.shape[ax] for ax in axes) result = COO( self.coords[axes, :], self.data, shape, has_duplicates=False, cache=self._cache is not None, fill_value=self.fill_value, ) if self._cache is not None: self._cache["transpose"].append((axes, result)) return result @property def T(self): """ Returns a new array which has the order of the axes reversed. Returns ------- COO The new array with the axes in the desired order. See Also -------- - [`sparse.COO.transpose`][] : A method where you can specify the order of the axes. - [`numpy.ndarray.T`][] : Numpy equivalent property. Examples -------- We can change the order of the dimensions of any [`sparse.COO`][] array with this function. >>> x = np.add.outer(np.arange(5), np.arange(5)[::-1]) >>> x # doctest: +NORMALIZE_WHITESPACE array([[4, 3, 2, 1, 0], [5, 4, 3, 2, 1], [6, 5, 4, 3, 2], [7, 6, 5, 4, 3], [8, 7, 6, 5, 4]]) >>> s = COO.from_numpy(x) >>> s.T.todense() # doctest: +NORMALIZE_WHITESPACE array([[4, 5, 6, 7, 8], [3, 4, 5, 6, 7], [2, 3, 4, 5, 6], [1, 2, 3, 4, 5], [0, 1, 2, 3, 4]]) Note that by default, this reverses the order of the axes rather than switching the last and second-to-last axes as required by some linear algebra operations. >>> x = np.random.rand(2, 3, 4) >>> s = COO.from_numpy(x) >>> s.T.shape (4, 3, 2) """ return self.transpose(tuple(range(self.ndim))[::-1]) @property def mT(self): """ Transpose of a matrix (or a stack of matrices). If an array instance has fewer than two dimensions, an error should be raised. Returns ------- COO array whose last two dimensions (axes) are permuted in reverse order relative to original array (i.e., for an array instance having shape (..., M, N), the returned array must have shape (..., N, M)). The returned array must have the same data type as the original array. See Also -------- - [`sparse.COO.transpose`][] : A method where you can specify the order of the axes. - [`numpy.ndarray.mT`][] : Numpy equivalent property. Examples -------- >>> x = np.arange(8).reshape((2, 2, 2)) >>> x # doctest: +NORMALIZE_WHITESPACE array([[[0, 1], [2, 3]], [[4, 5], [6, 7]]]) >>> s = COO.from_numpy(x) >>> s.mT.todense() # doctest: +NORMALIZE_WHITESPACE array([[[0, 2], [1, 3]], [[4, 6], [5, 7]]]) """ if self.ndim < 2: raise ValueError("Cannot compute matrix transpose if `ndim < 2`.") axis = list(range(self.ndim)) axis[-1], axis[-2] = axis[-2], axis[-1] return self.transpose(axis) def swapaxes(self, axis1, axis2): """Returns array that has axes axis1 and axis2 swapped. Parameters ---------- axis1 : int first axis to swap axis2 : int second axis to swap Returns ------- COO The new array with the axes axis1 and axis2 swapped. Examples -------- >>> x = COO.from_numpy(np.ones((2, 3, 4))) >>> x.swapaxes(0, 2) """ # Normalize all axis1, axis2 to positive values axis1, axis2 = normalize_axis((axis1, axis2), self.ndim) # checks if axis1,2 are in range + raises ValueError axes = list(range(self.ndim)) axes[axis1], axes[axis2] = axes[axis2], axes[axis1] return self.transpose(axes) def dot(self, other): """ Performs the equivalent of `x.dot(y)` for [`sparse.COO`][]. Parameters ---------- other : Union[COO, numpy.ndarray, scipy.sparse.spmatrix] The second operand of the dot product operation. Returns ------- {COO, numpy.ndarray} The result of the dot product. If the result turns out to be dense, then a dense array is returned, otherwise, a sparse array. Raises ------ ValueError If all arguments don't have zero fill-values. See Also -------- - [`sparse.dot`][] : Equivalent function for two arguments. - [`numpy.dot`][] : Numpy equivalent function. - [`scipy.sparse.coo_array.dot`][] : Scipy equivalent function. Examples -------- >>> x = np.arange(4).reshape((2, 2)) >>> s = COO.from_numpy(x) >>> s.dot(s) # doctest: +SKIP array([[ 2, 3], [ 6, 11]], dtype=int64) """ from .._common import dot return dot(self, other) def __matmul__(self, other): from .._common import matmul try: return matmul(self, other) except NotImplementedError: return NotImplemented def __rmatmul__(self, other): from .._common import matmul try: return matmul(other, self) except NotImplementedError: return NotImplemented def linear_loc(self): """ The nonzero coordinates of a flattened version of this array. Note that the coordinates may be out of order. Returns ------- numpy.ndarray The flattened coordinates. See Also -------- [`numpy.flatnonzero`][] : Equivalent Numpy function. Examples -------- >>> x = np.eye(5) >>> s = COO.from_numpy(x) >>> s.linear_loc() # doctest: +NORMALIZE_WHITESPACE array([ 0, 6, 12, 18, 24]) >>> np.array_equal(np.flatnonzero(x), s.linear_loc()) True """ from .common import linear_loc return linear_loc(self.coords, self.shape) def flatten(self, order="C"): """ Returns a new [`sparse.COO`][] array that is a flattened version of this array. Returns ------- COO The flattened output array. Notes ----- The `order` parameter is provided just for compatibility with Numpy and isn't actually supported. Examples -------- >>> s = COO.from_numpy(np.arange(10)) >>> s2 = s.reshape((2, 5)).flatten() >>> s2.todense() array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) """ if order not in {"C", None}: raise NotImplementedError("The `order` parameter is notsupported.") return self.reshape(-1) def reshape(self, shape, order="C"): """ Returns a new [`sparse.COO`][] array that is a reshaped version of this array. Parameters ---------- shape : tuple[int] The desired shape of the output array. Returns ------- COO The reshaped output array. See Also -------- [`numpy.ndarray.reshape`][] : The equivalent Numpy function. Notes ----- The `order` parameter is provided just for compatibility with Numpy and isn't actually supported. Examples -------- >>> s = COO.from_numpy(np.arange(25)) >>> s2 = s.reshape((5, 5)) >>> s2.todense() # doctest: +NORMALIZE_WHITESPACE array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19], [20, 21, 22, 23, 24]]) """ shape = tuple(shape) if isinstance(shape, Iterable) else (shape,) if order not in {"C", None}: raise NotImplementedError("The `order` parameter is not supported") if self.shape == shape: return self if any(d == -1 for d in shape): extra = int(self.size / np.prod([d for d in shape if d != -1])) shape = tuple([d if d != -1 else extra for d in shape]) if self.size != reduce(operator.mul, shape, 1): raise ValueError(f"cannot reshape array of size {self.size} into shape {shape}") if self._cache is not None: for sh, value in self._cache["reshape"]: if sh == shape: return value # TODO: this self.size enforces a 2**64 limit to array size linear_loc = self.linear_loc() idx_dtype = self.coords.dtype if shape != () and not can_store(idx_dtype, max(shape)): idx_dtype = np.min_scalar_type(max(shape)) coords = np.empty((len(shape), self.nnz), dtype=idx_dtype) strides = 1 for i, d in enumerate(shape[::-1]): coords[-(i + 1), :] = (linear_loc // strides) % d strides *= d result = COO( coords, self.data, shape, has_duplicates=False, sorted=True, cache=self._cache is not None, fill_value=self.fill_value, ) if self._cache is not None: self._cache["reshape"].append((shape, result)) return result def squeeze(self, axis=None): """ Removes singleton dimensions (axes) from ``x``. Parameters ---------- axis : Union[None, int, Tuple[int, ...]] The axis (or axes) to squeeze. If a specified axis has a size greater than one, a `ValueError` is raised. ``axis=None`` removes all singleton dimensions. Default: ``None``. Returns ------- COO The output array without ``axis`` dimensions. Examples -------- >>> s = COO.from_numpy(np.eye(2)).reshape((2, 1, 2, 1)) >>> s.squeeze().shape (2, 2) >>> s.squeeze(axis=1).shape (2, 2, 1) """ squeezable_dims = tuple([d for d in range(self.ndim) if self.shape[d] == 1]) if axis is None: axis = squeezable_dims if isinstance(axis, int): axis = (axis,) elif isinstance(axis, Iterable): axis = tuple(axis) else: raise ValueError(f"Invalid axis parameter: `{axis}`.") for d in axis: if d not in squeezable_dims: raise ValueError(f"Specified axis `{d}` has a size greater than one: {self.shape[d]}") retained_dims = [d for d in range(self.ndim) if d not in axis] coords = self.coords[retained_dims, :] shape = tuple([s for idx, s in enumerate(self.shape) if idx in retained_dims]) return COO( coords, self.data, shape, has_duplicates=False, sorted=True, cache=self._cache is not None, fill_value=self.fill_value, ) def to_scipy_sparse(self, /, *, accept_fv=None): """ Converts this [`sparse.COO`][] object into a [`scipy.sparse.coo_array`][]. Parameters ---------- accept_fv : scalar or list of scalar, optional The list of accepted fill-values. The default accepts only zero. Returns ------- scipy.sparse.coo_array The converted Scipy sparse matrix. Raises ------ ValueError If the array is not two-dimensional. ValueError If all the array doesn't zero fill-values. See Also -------- - [`sparse.COO.tocsr`][] : Convert to a [`scipy.sparse.csr_array`][]. - [`sparse.COO.tocsc`][] : Convert to a [`scipy.sparse.csc_array`][]. """ import scipy.sparse check_fill_value(self, accept_fv=accept_fv) result = scipy.sparse.coo_array((self.data, self.coords), shape=self.shape) result.has_canonical_format = True return result def _tocsr(self): import scipy.sparse if self.ndim != 2: raise ValueError("This array must be two-dimensional for this conversion to work.") row, col = self.coords # Pass 3: count nonzeros in each row indptr = np.zeros(self.shape[0] + 1, dtype=np.int64) np.cumsum(np.bincount(row, minlength=self.shape[0]), out=indptr[1:]) return scipy.sparse.csr_array((self.data, col, indptr), shape=self.shape) def tocsr(self): """ Converts this array to a [`scipy.sparse.csr_array`][]. Returns ------- scipy.sparse.csr_array The result of the conversion. Raises ------ ValueError If the array is not two-dimensional. ValueError If all the array doesn't have zero fill-values. See Also -------- - [`sparse.COO.tocsc`][] : Convert to a [`scipy.sparse.csc_array`][]. - [`sparse.COO.to_scipy_sparse`][] : Convert to a [`scipy.sparse.coo_array`][]. - [`scipy.sparse.coo_array.tocsr`][] : Equivalent Scipy function. """ check_zero_fill_value(self) if self._cache is not None: try: return self._csr except AttributeError: pass try: self._csr = self._csc.tocsr() return self._csr except AttributeError: pass self._csr = csr = self._tocsr() else: csr = self._tocsr() return csr def tocsc(self): """ Converts this array to a [`scipy.sparse.csc_array`][]. Returns ------- scipy.sparse.csc_array The result of the conversion. Raises ------ ValueError If the array is not two-dimensional. ValueError If the array doesn't have zero fill-values. See Also -------- - [`sparse.COO.tocsr`][] : Convert to a [`scipy.sparse.csr_array`][]. - [`sparse.COO.to_scipy_sparse`][] : Convert to a [`scipy.sparse.coo_array`][]. - [`scipy.sparse.coo_array.tocsc`][] : Equivalent Scipy function. """ check_zero_fill_value(self) if self._cache is not None: try: return self._csc except AttributeError: pass try: self._csc = self._csr.tocsc() return self._csc except AttributeError: pass self._csc = csc = self.tocsr().tocsc() else: csc = self.tocsr().tocsc() return csc def _sort_indices(self): """ Sorts the :obj:`COO.coords` attribute. Also sorts the data in :obj:`COO.data` to match. Examples -------- >>> coords = np.array([[1, 2, 0]], dtype=np.uint8) >>> data = np.array([4, 1, 3], dtype=np.uint8) >>> s = COO(coords, data, shape=(3,)) >>> s._sort_indices() >>> s.coords # doctest: +NORMALIZE_WHITESPACE array([[0, 1, 2]], dtype=uint8) >>> s.data # doctest: +NORMALIZE_WHITESPACE array([3, 4, 1], dtype=uint8) """ linear = self.linear_loc() if (np.diff(linear) >= 0).all(): # already sorted return order = np.argsort(linear, kind="mergesort") self.coords = self.coords[:, order] self.data = self.data[order] def _sum_duplicates(self): """ Sums data corresponding to duplicates in :obj:`COO.coords`. See Also -------- scipy.sparse.coo_array.sum_duplicates : Equivalent Scipy function. Examples -------- >>> coords = np.array([[0, 1, 1, 2]], dtype=np.uint8) >>> data = np.array([6, 5, 2, 2], dtype=np.uint8) >>> s = COO(coords, data, shape=(3,)) >>> s._sum_duplicates() >>> s.coords # doctest: +NORMALIZE_WHITESPACE array([[0, 1, 2]], dtype=uint8) >>> s.data # doctest: +NORMALIZE_WHITESPACE array([6, 7, 2], dtype=uint8) """ # Inspired by scipy/sparse/coo.py::sum_duplicates # See https://github.com/scipy/scipy/blob/main/LICENSE.txt linear = self.linear_loc() unique_mask = np.diff(linear) != 0 if unique_mask.sum() == len(unique_mask): # already unique return unique_mask = np.append(True, unique_mask) coords = self.coords[:, unique_mask] (unique_inds,) = np.nonzero(unique_mask) data = np.add.reduceat(self.data, unique_inds, dtype=self.data.dtype) self.data = data self.coords = coords def _prune(self): """ Prunes data so that if any fill-values are present, they are removed from both coordinates and data. Examples -------- >>> coords = np.array([[0, 1, 2, 3]]) >>> data = np.array([1, 0, 1, 2]) >>> s = COO(coords, data, shape=(4,)) >>> s._prune() >>> s.nnz 3 """ mask = ~equivalent(self.data, self.fill_value) self.coords = self.coords[:, mask] self.data = self.data[mask] def broadcast_to(self, shape): """ Performs the equivalent of [`sparse.COO`][]. Note that this function returns a new array instead of a view. Parameters ---------- shape : tuple[int] The shape to broadcast the data to. Returns ------- COO The broadcasted sparse array. Raises ------ ValueError If the operand cannot be broadcast to the given shape. See Also -------- [`numpy.broadcast_to`][] : NumPy equivalent function """ return broadcast_to(self, shape) def maybe_densify(self, max_size=1000, min_density=0.25): """ Converts this [`sparse.COO`][] array to a [`numpy.ndarray`][] if not too costly. Parameters ---------- max_size : int Maximum number of elements in output min_density : float Minimum density of output Returns ------- numpy.ndarray The dense array. Raises ------ ValueError If the returned array would be too large. Examples -------- Convert a small sparse array to a dense array. >>> s = COO.from_numpy(np.random.rand(2, 3, 4)) >>> x = s.maybe_densify() >>> np.allclose(x, s.todense()) True You can also specify the minimum allowed density or the maximum number of output elements. If both conditions are unmet, this method will throw an error. >>> x = np.zeros((5, 5), dtype=np.uint8) >>> x[2, 2] = 1 >>> s = COO.from_numpy(x) >>> s.maybe_densify(max_size=5, min_density=0.25) Traceback (most recent call last): ... ValueError: Operation would require converting large sparse array to dense """ if self.size > max_size and self.density < min_density: raise ValueError("Operation would require converting large sparse array to dense") return self.todense() def nonzero(self): """ Get the indices where this array is nonzero. Returns ------- idx : tuple[`numpy.ndarray`] The indices where this array is nonzero. See Also -------- [`numpy.ndarray.nonzero`][] : NumPy equivalent function Raises ------ ValueError If the array doesn't have zero fill-values. Examples -------- >>> s = COO.from_numpy(np.eye(5)) >>> s.nonzero() (array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4])) """ check_zero_fill_value(self) if self.ndim == 0: raise ValueError("`nonzero` is undefined for `self.ndim == 0`.") return tuple(self.coords) def asformat(self, format, **kwargs): """ Convert this sparse array to a given format. Parameters ---------- format : str A format string. Returns ------- out : SparseArray The converted array. Raises ------ NotImplementedError If the format isn't supported. """ from .._utils import convert_format format = convert_format(format) if format == "gcxs": from .._compressed import GCXS return GCXS.from_coo(self, **kwargs) if len(kwargs) != 0: raise TypeError(f"Invalid keyword arguments provided: {kwargs}") if format == "coo": return self if format == "dok": from .._dok import DOK return DOK.from_coo(self, **kwargs) return self.asformat("gcxs", **kwargs).asformat(format, **kwargs) def isinf(self): """ Tests each element ``x_i`` of the array to determine if equal to positive or negative infinity. """ new_fill_value = bool(np.isinf(self.fill_value)) new_data = np.isinf(self.data) return COO( self.coords, new_data, shape=self.shape, fill_value=new_fill_value, prune=True, ) def isnan(self): """ Tests each element ``x_i`` of the array to determine whether the element is ``NaN``. """ new_fill_value = bool(np.isnan(self.fill_value)) new_data = np.isnan(self.data) return COO( self.coords, new_data, shape=self.shape, fill_value=new_fill_value, prune=True, ) def as_coo(x, shape=None, fill_value=None, idx_dtype=None): """ Converts any given format to [`sparse.COO`][]. See the "See Also" section for details. Parameters ---------- x : SparseArray or numpy.ndarray or scipy.sparse.spmatrix or Iterable. The item to convert. shape : tuple[int], optional The shape of the output array. Can only be used in case of Iterable. Returns ------- out : COO The converted [`sparse.COO`][] array. See Also -------- - [`sparse.SparseArray.asformat`][] : A utility function to convert between formats in this library. - [`sparse.COO.from_numpy`][] : Convert a Numpy array to [`sparse.COO`][]. - [`sparse.COO.from_scipy_sparse`][] : Convert a SciPy sparse matrix to [`sparse.COO`][]. - [`sparse.COO.from_iter`][] : Convert an iterable to [`sparse.COO`][]. """ from .._common import _is_scipy_sparse_obj if hasattr(x, "shape") and shape is not None: raise ValueError("Cannot provide a shape in combination with something that already has a shape.") if hasattr(x, "fill_value") and fill_value is not None: raise ValueError("Cannot provide a fill-value in combination with something that already has a fill-value.") if isinstance(x, SparseArray): return x.asformat("coo") if isinstance(x, np.ndarray) or np.isscalar(x): return COO.from_numpy(x, fill_value=fill_value, idx_dtype=idx_dtype) if _is_scipy_sparse_obj(x): return COO.from_scipy_sparse(x) if isinstance(x, Iterable | Iterator): return COO.from_iter(x, shape=shape, fill_value=fill_value) raise NotImplementedError( f"Format not supported for conversion. Supplied type is " f"{type(x)}, see help(sparse.as_coo) for supported formats." ) @numba.jit(nopython=True, nogil=True) # pragma: no cover def _calc_counts_invidx(groups): inv_idx = [] counts = [] if len(groups) == 0: return ( np.array(inv_idx, dtype=groups.dtype), np.array(counts, dtype=groups.dtype), ) inv_idx.append(0) last_group = groups[0] for i in range(1, len(groups)): if groups[i] != last_group: counts.append(i - inv_idx[-1]) inv_idx.append(i) last_group = groups[i] counts.append(len(groups) - inv_idx[-1]) return (np.array(inv_idx, dtype=groups.dtype), np.array(counts, dtype=groups.dtype)) def _grouped_reduce(x, groups, method, **kwargs): """ Performs a :code:`ufunc` grouped reduce. Parameters ---------- x : np.ndarray The data to reduce. groups : np.ndarray The groups the data belongs to. The groups must be contiguous. method : np.ufunc The :code:`ufunc` to use to perform the reduction. **kwargs : dict The kwargs to pass to the :code:`ufunc`'s :code:`reduceat` function. Returns ------- result : np.ndarray The result of the grouped reduce operation. inv_idx : np.ndarray The index of the first element where each group is found. counts : np.ndarray The number of elements in each group. """ # Partial credit to @shoyer # Ref: https://gist.github.com/shoyer/f538ac78ae904c936844 inv_idx, counts = _calc_counts_invidx(groups) result = method.reduceat(x, inv_idx, **kwargs) return result, inv_idx, counts sparse-0.18.0/sparse/numba_backend/_coo/indexing.py000066400000000000000000000502771514474157100222650ustar00rootroot00000000000000from itertools import zip_longest from numbers import Integral import numba import numpy as np from .._slicing import normalize_index from .._utils import _zero_of_dtype, equivalent def getitem(x, index): """ This function implements the indexing functionality for COO. The overall algorithm has three steps: 1. Normalize the index to canonical form. Function: normalize_index 2. Get the mask, which is a list of integers corresponding to the indices in coords/data for the output data. Function: _mask 3. Transform the coordinates to what they will be in the output. Parameters ---------- x : COO The array to apply the indexing operation on. index : {tuple, str} The index into the array. """ from .core import COO # If string, this is an index into an np.void # Custom dtype. if isinstance(index, str): data = x.data[index] idx = np.where(data) data = data[idx].flatten() coords = list(x.coords[:, idx[0]]) coords.extend(idx[1:]) fill_value_idx = np.asarray(x.fill_value[index]).flatten() fill_value = fill_value_idx[0] if fill_value_idx.size else _zero_of_dtype(data.dtype)[()] if not equivalent(fill_value, fill_value_idx).all(): raise ValueError("Fill-values in the array are inconsistent.") return COO( coords, data, shape=x.shape + x.data.dtype[index].shape, has_duplicates=False, sorted=True, fill_value=fill_value, ) # Otherwise, convert into a tuple. if not isinstance(index, tuple): index = (index,) # Check if the last index is an ellipsis. last_ellipsis = len(index) > 0 and index[-1] is Ellipsis # Normalize the index into canonical form. index = normalize_index(index, x.shape) # zip_longest so things like x[..., None] are picked up. if len(index) != 0 and all( isinstance(ind, slice) and ind == slice(0, dim, 1) for ind, dim in zip_longest(index, x.shape) ): return x # Get the mask mask, adv_idx = _mask(x.coords, index, x.shape) # Get the length of the mask n = len(range(mask.start, mask.stop, mask.step)) if isinstance(mask, slice) else len(mask) coords = [] shape = [] i = 0 sorted = adv_idx is None or adv_idx.pos == 0 adv_idx_added = False for ind in index: # Nothing is added to shape or coords if the index is an integer. if isinstance(ind, Integral): i += 1 continue # Add to the shape and transform the coords in the case of a slice. if isinstance(ind, slice): shape.append(len(range(ind.start, ind.stop, ind.step))) coords.append((x.coords[i, mask] - ind.start) // ind.step) i += 1 if ind.step < 0: sorted = False # Add the index and shape for the advanced index. if isinstance(ind, np.ndarray): if not adv_idx_added: shape.append(adv_idx.length) coords.append(adv_idx.idx) adv_idx_added = True i += 1 # Add a dimension for None. if ind is None: coords.append(np.zeros(n, dtype=np.intp)) shape.append(1) # Join all the transformed coords. if coords: coords = np.stack(coords, axis=0) else: # If index result is a scalar, return a 0-d COO or # a scalar depending on whether the last index is an ellipsis. if last_ellipsis: coords = np.empty((0, n), dtype=np.uint8) else: if n != 0: return x.data[mask][0] return x.fill_value shape = tuple(shape) data = x.data[mask] return COO( coords, data, shape=shape, has_duplicates=False, sorted=sorted, fill_value=x.fill_value, ) def _mask(coords, indices, shape): indices = _prune_indices(indices, shape) indices, adv_idx, adv_idx_pos = _separate_adv_indices(indices) if len(adv_idx) != 0: if len(adv_idx) != 1: # Ensure if multiple advanced indices are passed, all are of the same length # Also check each advanced index to ensure each is only a one-dimensional iterable adv_ix_len = len(adv_idx[0]) for ai in adv_idx: if len(ai) != adv_ix_len: raise IndexError( "shape mismatch: indexing arrays could not be broadcast together. Ensure all indexing arrays " "are of the same length." ) if ai.ndim != 1: raise IndexError("Only one-dimensional iterable indices supported.") mask, aidxs = _compute_multi_axis_multi_mask( coords, _ind_ar_from_indices(indices), np.array(adv_idx, dtype=np.intp), np.array(adv_idx_pos, dtype=np.intp), ) return mask, _AdvIdxInfo(aidxs, adv_idx_pos, adv_ix_len) adv_idx = adv_idx[0] adv_idx_pos = adv_idx_pos[0] if adv_idx.ndim != 1: raise IndexError("Only one-dimensional iterable indices supported.") mask, aidxs = _compute_multi_mask(coords, _ind_ar_from_indices(indices), adv_idx, adv_idx_pos) return mask, _AdvIdxInfo(aidxs, adv_idx_pos, len(adv_idx)) mask, is_slice = _compute_mask(coords, _ind_ar_from_indices(indices)) if is_slice: return slice(mask[0], mask[1], 1), None return mask, None def _ind_ar_from_indices(indices): """ Computes an index "array" from indices, such that ``indices[i]`` is transformed to ``ind_ar[i]`` and ``ind_ar[i].shape == (3,)``. It has the format ``[start, stop, step]``. Integers are converted into steps as well. Parameters ---------- indices : Iterable Input indices (slices and integers) Returns ------- ind_ar : np.ndarray The output array. Examples -------- >>> _ind_ar_from_indices([1]) array([[1, 2, 1]]) >>> _ind_ar_from_indices([slice(5, 7, 2)]) array([[5, 7, 2]]) """ ind_ar = np.empty((len(indices), 3), dtype=np.intp) for i, idx in enumerate(indices): if isinstance(idx, slice): ind_ar[i] = [idx.start, idx.stop, idx.step] elif isinstance(idx, Integral): ind_ar[i] = [idx, idx + 1, 1] return ind_ar def _prune_indices(indices, shape, prune_none=True): """ Gets rid of the indices that do not contribute to the overall mask, e.g. None and full slices. Parameters ---------- indices : tuple The indices to the array. shape : tuple[int] The shape of the array. Returns ------- indices : tuple The filtered indices. Examples -------- >>> _prune_indices((None, 5), (10,)) # None won't affect the mask [5] >>> _prune_indices((slice(0, 10, 1),), (10,)) # Full slices don't affect the mask [] """ if prune_none: indices = [idx for idx in indices if idx is not None] i = 0 for idx, sh in zip(indices[::-1], shape[::-1], strict=True): if not isinstance(idx, slice): break if idx.start == 0 and idx.stop == sh and idx.step == 1: i += 1 continue if idx.start == sh - 1 and idx.stop == -1 and idx.step == -1: i += 1 continue break if i != 0: indices = indices[:-i] return indices def _separate_adv_indices(indices): """ Separates advanced from normal indices. Parameters ---------- indices : list The input indices Returns ------- new_idx : list The normal indices. adv_idx : list The advanced indices. adv_idx_pos : list The positions of the advanced indices. """ adv_idx_pos = [] new_idx = [] adv_idx = [] for i, idx in enumerate(indices): if isinstance(idx, np.ndarray): adv_idx.append(idx) adv_idx_pos.append(i) else: new_idx.append(idx) return new_idx, adv_idx, adv_idx_pos @numba.jit(nopython=True, nogil=True) def _compute_multi_axis_multi_mask(coords, indices, adv_idx, adv_idx_pos): # pragma: no cover """ Computes a mask with the advanced index, and also returns the advanced index dimension. Parameters ---------- coords : np.ndarray Coordinates of the input array. indices : np.ndarray The indices in slice format. adv_idx : np.ndarray List of advanced indices. adv_idx_pos : np.ndarray The position of the advanced indices. Returns ------- mask : np.ndarray The mask. aidxs : np.ndarray The advanced array index. """ n_adv_idx = len(adv_idx_pos) mask = numba.typed.List.empty_list(numba.types.intp) a_indices = numba.typed.List.empty_list(numba.types.intp) full_idx = np.empty((len(indices) + len(adv_idx_pos), 3), dtype=np.intp) # Get location of non-advanced indices if len(indices) != 0: ixx = 0 for ix in range(coords.shape[0]): isin = False for ax in adv_idx_pos: if ix == ax: isin = True break if not isin: full_idx[ix] = indices[ixx] ixx += 1 for i in range(len(adv_idx[0])): for ii in range(n_adv_idx): full_idx[adv_idx_pos[ii]] = [adv_idx[ii][i], adv_idx[ii][i] + 1, 1] partial_mask, is_slice = _compute_mask(coords, full_idx) if is_slice: slice_mask = numba.typed.List.empty_list(numba.types.intp) for j in range(partial_mask[0], partial_mask[1]): slice_mask.append(j) partial_mask = array_from_list_intp(slice_mask) for j in range(len(partial_mask)): mask.append(partial_mask[j]) a_indices.append(i) return array_from_list_intp(mask), array_from_list_intp(a_indices) @numba.jit(nopython=True, nogil=True) def _compute_multi_mask(coords, indices, adv_idx, adv_idx_pos): # pragma: no cover """ Computes a mask with the advanced index, and also returns the advanced index dimension. Parameters ---------- coords : np.ndarray Coordinates of the input array. indices : np.ndarray The indices in slice format. adv_idx : list(int) The advanced index. adv_idx_pos : list(int) The position of the advanced index. Returns ------- mask : np.ndarray The mask. aidxs : np.ndarray The advanced array index. """ mask = numba.typed.List.empty_list(numba.types.intp) a_indices = numba.typed.List.empty_list(numba.types.intp) full_idx = np.empty((len(indices) + 1, 3), dtype=np.intp) full_idx[:adv_idx_pos] = indices[:adv_idx_pos] full_idx[adv_idx_pos + 1 :] = indices[adv_idx_pos:] for i, aidx in enumerate(adv_idx): full_idx[adv_idx_pos] = [aidx, aidx + 1, 1] partial_mask, is_slice = _compute_mask(coords, full_idx) if is_slice: slice_mask = numba.typed.List.empty_list(numba.types.intp) for j in range(partial_mask[0], partial_mask[1]): slice_mask.append(j) partial_mask = array_from_list_intp(slice_mask) for j in range(len(partial_mask)): mask.append(partial_mask[j]) a_indices.append(i) return array_from_list_intp(mask), array_from_list_intp(a_indices) @numba.jit(nopython=True, nogil=True) def _compute_mask(coords, indices): # pragma: no cover """ Gets the mask for the coords given the indices in slice format. Works with either start-stop ranges of matching indices into coords called "pairs" (start-stop pairs) or filters the mask directly, based on which is faster. Exploits the structure in sorted coords, which is that for a constant value of coords[i - 1], coords[i - 2] and so on, coords[i] is sorted. Concretely, ``coords[i, coords[i - 1] == v1 & coords[i - 2] = v2, ...]`` is always sorted. It uses this sortedness to find sub-pairs for each dimension given the previous, and so on. This is efficient for small slices or ints, but not for large ones. After it detects that working with pairs is rather inefficient (or after going through each possible index), it constructs a filtered mask from the start-stop pairs. Parameters ---------- coords : np.ndarray The coordinates of the array. indices : np.ndarray The indices in the form of slices such that indices[:, 0] are starts, indices[:, 1] are stops and indices[:, 2] are steps. Returns ------- mask : np.ndarray The starts and stops in the mask. is_slice : bool Whether or not the array represents a continuous slice. Examples -------- Let's create some mock coords and indices >>> import numpy as np >>> coords = np.array([[0, 0, 1, 1, 2, 2]]) >>> indices = np.array([[0, 3, 2]]) # Equivalent to slice(0, 3, 2) Now let's get the mask. Notice that the indices of ``0`` and ``2`` are matched. >>> _compute_mask(coords, indices) (array([0, 1, 4, 5]), False) Now, let's try with a more "continuous" slice. Matches ``0`` and ``1``. >>> indices = np.array([[0, 2, 1]]) >>> _compute_mask(coords, indices) (array([0, 4]), True) This is equivalent to mask being ``slice(0, 4, 1)``. """ # Set the initial mask to be the entire range of coordinates. starts = numba.typed.List.empty_list(numba.types.intp) starts.append(0) stops = numba.typed.List.empty_list(numba.types.intp) stops.append(coords.shape[1]) n_matches = np.intp(coords.shape[1]) i = 0 while i < len(indices): # Guesstimate whether working with pairs is more efficient or # working with the mask directly. # One side is the estimate of time taken for binary searches # (n_searches * log(avg_length)) # The other is an estimated time of a linear filter for the mask. n_pairs = len(starts) n_current_slices = len(range(indices[i, 0], indices[i, 1], indices[i, 2])) * n_pairs + 2 if n_current_slices * np.log(n_current_slices / max(n_pairs, 1)) > n_matches + n_pairs: break # For each of the pairs, search inside the coordinates for other # matching sub-pairs. # This gets the start-end coordinates in coords for each 'sub-array' # Which would come out of indexing a single integer. starts, stops, n_matches = _get_mask_pairs(starts, stops, coords[i], indices[i]) i += 1 # Combine adjacent pairs starts, stops = _join_adjacent_pairs(starts, stops) # If just one pair is left over, treat it as a slice. if i == len(indices) and len(starts) == 1: return np.array([starts[0], stops[0]]), True # Convert start-stop pairs into mask, filtering by remaining # coordinates. mask = _filter_pairs(starts, stops, coords[i:], indices[i:]) return array_from_list_intp(mask), False @numba.jit(nopython=True, nogil=True) def _get_mask_pairs(starts_old, stops_old, c, idx): # pragma: no cover """ Gets the pairs for a following dimension given the pairs for a dimension. For each pair, it searches in the following dimension for matching coords and returns those. The total combined length of all pairs is returned to help with the performance guesstimate. Parameters ---------- starts_old, stops_old : list[int] The starts and stops from the previous index. c : np.ndarray The coords for this index's dimension. idx : np.ndarray The index in the form of a slice. idx[0], idx[1], idx[2] = start, stop, step Returns ------- starts, stops: list The starts and stops after applying the current index. n_matches : int The sum of elements in all ranges. Examples -------- >>> c = np.array([1, 2, 1, 2, 1, 1, 2, 2]) >>> starts_old = numba.typed.List() >>> starts_old.append(4) >>> stops_old = numba.typed.List() >>> stops_old.append(8) >>> idx = np.array([1, 2, 1]) >>> _get_mask_pairs(starts_old, stops_old, c, idx) (ListType[int64]([4]), ListType[int64]([6]), 2) """ starts = numba.typed.List.empty_list(numba.types.intp) stops = numba.typed.List.empty_list(numba.types.intp) n_matches = np.intp(0) for j in range(len(starts_old)): # For each matching "integer" in the slice, search within the "sub-coords" # Using binary search. for p_match in range(idx[0], idx[1], idx[2]): start = np.searchsorted(c[starts_old[j] : stops_old[j]], p_match, side="left") + starts_old[j] stop = np.searchsorted(c[starts_old[j] : stops_old[j]], p_match, side="right") + starts_old[j] if start != stop: starts.append(start) stops.append(stop) n_matches += stop - start return starts, stops, n_matches @numba.jit(nopython=True, nogil=True) def _filter_pairs(starts, stops, coords, indices): # pragma: no cover """ Converts all the pairs into a single integer mask, additionally filtering by the indices. Parameters ---------- starts, stops : list[int] The starts and stops to convert into an array. coords : np.ndarray The coordinates to filter by. indices : np.ndarray The indices in the form of slices such that indices[:, 0] are starts, indices[:, 1] are stops and indices[:, 2] are steps. Returns ------- mask : list The output integer mask. Examples -------- >>> import numpy as np >>> starts = numba.typed.List() >>> starts.append(2) >>> stops = numba.typed.List() >>> stops.append(7) >>> coords = np.array([[0, 1, 2, 3, 4, 5, 6, 7]]) >>> indices = np.array([[2, 8, 2]]) # Start, stop, step pairs >>> _filter_pairs(starts, stops, coords, indices) ListType[int64]([2, 4, 6]) """ mask = numba.typed.List.empty_list(numba.types.intp) # For each pair, for i in range(len(starts)): # For each element match within the pair range for j in range(starts[i], stops[i]): match = True # Check if it matches all indices for k in range(len(indices)): idx = indices[k] elem = coords[k, j] match &= (elem - idx[0]) % idx[2] == 0 and ( (idx[2] > 0 and idx[0] <= elem < idx[1]) or (idx[2] < 0 and idx[0] >= elem > idx[1]) ) # and append to the mask if so. if match: mask.append(j) return mask @numba.jit(nopython=True, nogil=True) def _join_adjacent_pairs(starts_old, stops_old): # pragma: no cover """ Joins adjacent pairs into one. For example, 2-5 and 5-7 will reduce to 2-7 (a single pair). This may help in returning a slice in the end which could be faster. Parameters ---------- starts_old, stops_old : list[int] The input starts and stops Returns ------- starts, stops : list[int] The reduced starts and stops. Examples -------- >>> starts = numba.typed.List() >>> starts.append(2) >>> starts.append(5) >>> stops = numba.typed.List() >>> stops.append(5) >>> stops.append(7) >>> _join_adjacent_pairs(starts, stops) (ListType[int64]([2]), ListType[int64]([7])) """ if len(starts_old) <= 1: return starts_old, stops_old starts = numba.typed.List.empty_list(numba.types.intp) starts.append(starts_old[0]) stops = numba.typed.List.empty_list(numba.types.intp) for i in range(1, len(starts_old)): if starts_old[i] != stops_old[i - 1]: starts.append(starts_old[i]) stops.append(stops_old[i - 1]) stops.append(stops_old[-1]) return starts, stops @numba.jit(nopython=True, nogil=True) def array_from_list_intp(x): # pragma: no cover n = len(x) a = np.empty(n, dtype=np.intp) for i in range(n): a[i] = x[i] return a class _AdvIdxInfo: def __init__(self, idx, pos, length): self.idx = idx self.pos = pos self.length = length sparse-0.18.0/sparse/numba_backend/_coo/numba_extension.py000066400000000000000000000226351514474157100236530ustar00rootroot00000000000000""" Numba support for COO objects. For now, this just supports attribute access """ import contextlib import numba from numba.core import cgutils, types from numba.core.imputils import impl_ret_borrowed, lower_builtin, lower_constant from numba.core.typing.typeof import typeof_impl from numba.extending import ( NativeValue, box, make_attribute_wrapper, models, register_model, type_callable, unbox, ) import numpy as np from .._utils import _zero_of_dtype from . import COO __all__ = ["COOType"] class COOType(types.Type): def __init__(self, data_dtype: np.dtype, coords_dtype: np.dtype, ndim: int): assert isinstance(data_dtype, np.dtype) assert isinstance(coords_dtype, np.dtype) self.data_dtype = data_dtype self.coords_dtype = coords_dtype self.ndim = ndim super().__init__( name=f"COOType[{numba.from_dtype(data_dtype)!r}, {numba.from_dtype(coords_dtype)!r}, {ndim!r}]" ) @property def key(self): return self.data_dtype, self.coords_dtype, self.ndim @property def data_type(self): return numba.from_dtype(self.data_dtype)[:] @property def coords_type(self): return numba.from_dtype(self.coords_dtype)[:, :] @property def shape_type(self): dt = numba.np.numpy_support.from_dtype(self.coords_dtype) return types.UniTuple(dt, self.ndim) @property def fill_value_type(self): return numba.from_dtype(self.data_dtype) @typeof_impl.register(COO) def _typeof_COO(val: COO, c) -> COOType: return COOType(data_dtype=val.data.dtype, coords_dtype=val.coords.dtype, ndim=val.ndim) @register_model(COOType) class COOModel(models.StructModel): def __init__(self, dmm, fe_type): members = [ ("data", fe_type.data_type), ("coords", fe_type.coords_type), ("shape", fe_type.shape_type), ("fill_value", fe_type.fill_value_type), ] models.StructModel.__init__(self, dmm, fe_type, members) @type_callable(COO) def type_COO(context): # TODO: accept a fill_value kwarg def typer(coords, data, shape): return COOType( coords_dtype=numba.np.numpy_support.as_dtype(coords.dtype), data_dtype=numba.np.numpy_support.as_dtype(data.dtype), ndim=len(shape), ) return typer @lower_builtin(COO, types.Any, types.Any, types.Any) def impl_COO(context, builder, sig, args): typ = sig.return_type coords, data, shape = args coo = cgutils.create_struct_proxy(typ)(context, builder) coo.coords = coords coo.data = data coo.shape = shape coo.fill_value = context.get_constant_generic(builder, typ.fill_value_type, _zero_of_dtype(typ.data_dtype)) return impl_ret_borrowed(context, builder, sig.return_type, coo._getvalue()) @lower_constant(COOType) def lower_constant_COO(context, builder, typ, pyval): coords = context.get_constant_generic(builder, typ.coords_type, pyval.coords) data = context.get_constant_generic(builder, typ.data_type, pyval.data) shape = context.get_constant_generic(builder, typ.shape_type, pyval.shape) fill_value = context.get_constant_generic(builder, typ.fill_value_type, pyval.fill_value) return impl_ret_borrowed( context, builder, typ, cgutils.pack_struct(builder, (data, coords, shape, fill_value)), ) @contextlib.contextmanager def local_return(builder): """ Create a scope which can be broken from locally. Used as:: with local_return(c.builder) as ret: with c.builder.if(abort_cond): ret() do_some_other_stuff # no ret needed at the end, it's implied stuff_that_runs_unconditionally """ end_blk = builder.append_basic_block("end") def return_(): builder.branch(end_blk) yield return_ builder.branch(end_blk) # make sure all remaining code goes to the next block builder.position_at_end(end_blk) def _unbox_native_field(typ, obj, field_name: str, c): ret_ptr = cgutils.alloca_once(c.builder, c.context.get_value_type(typ)) is_error_ptr = cgutils.alloca_once_value(c.builder, cgutils.false_bit) fail_obj = c.context.get_constant_null(typ) with local_return(c.builder) as ret: fail_blk = c.builder.append_basic_block("fail") with c.builder.goto_block(fail_blk): c.builder.store(cgutils.true_bit, is_error_ptr) c.builder.store(fail_obj, ret_ptr) ret() field_obj = c.pyapi.object_getattr_string(obj, field_name) with cgutils.if_unlikely(c.builder, cgutils.is_null(c.builder, field_obj)): c.builder.branch(fail_blk) field_native = c.unbox(typ, field_obj) c.pyapi.decref(field_obj) with cgutils.if_unlikely(c.builder, field_native.is_error): c.builder.branch(fail_blk) c.builder.store(cgutils.false_bit, is_error_ptr) c.builder.store(field_native.value, ret_ptr) return NativeValue(c.builder.load(ret_ptr), is_error=c.builder.load(is_error_ptr)) @unbox(COOType) def unbox_COO(typ: COOType, obj: COO, c) -> NativeValue: ret_ptr = cgutils.alloca_once(c.builder, c.context.get_value_type(typ)) is_error_ptr = cgutils.alloca_once_value(c.builder, cgutils.false_bit) fail_obj = c.context.get_constant_null(typ) with local_return(c.builder) as ret: fail_blk = c.builder.append_basic_block("fail") with c.builder.goto_block(fail_blk): c.builder.store(cgutils.true_bit, is_error_ptr) c.builder.store(fail_obj, ret_ptr) ret() data = _unbox_native_field(typ.data_type, obj, "data", c) with cgutils.if_unlikely(c.builder, data.is_error): c.builder.branch(fail_blk) coords = _unbox_native_field(typ.coords_type, obj, "coords", c) with cgutils.if_unlikely(c.builder, coords.is_error): c.builder.branch(fail_blk) shape = _unbox_native_field(typ.shape_type, obj, "shape", c) with cgutils.if_unlikely(c.builder, shape.is_error): c.builder.branch(fail_blk) fill_value = _unbox_native_field(typ.fill_value_type, obj, "fill_value", c) with cgutils.if_unlikely(c.builder, fill_value.is_error): c.builder.branch(fail_blk) coo = cgutils.create_struct_proxy(typ)(c.context, c.builder) coo.coords = coords.value coo.data = data.value coo.shape = shape.value coo.fill_value = fill_value.value c.builder.store(cgutils.false_bit, is_error_ptr) c.builder.store(coo._getvalue(), ret_ptr) return NativeValue(c.builder.load(ret_ptr), is_error=c.builder.load(is_error_ptr)) @box(COOType) def box_COO(typ: COOType, val, c) -> COO: ret_ptr = cgutils.alloca_once(c.builder, c.pyapi.pyobj) fail_obj = c.pyapi.get_null_object() coo = cgutils.create_struct_proxy(typ)(c.context, c.builder, value=val) with local_return(c.builder) as ret: data_obj = c.box(typ.data_type, coo.data) with cgutils.if_unlikely(c.builder, cgutils.is_null(c.builder, data_obj)): c.builder.store(fail_obj, ret_ptr) ret() coords_obj = c.box(typ.coords_type, coo.coords) with cgutils.if_unlikely(c.builder, cgutils.is_null(c.builder, coords_obj)): c.pyapi.decref(data_obj) c.builder.store(fail_obj, ret_ptr) ret() shape_obj = c.box(typ.shape_type, coo.shape) with cgutils.if_unlikely(c.builder, cgutils.is_null(c.builder, shape_obj)): c.pyapi.decref(coords_obj) c.pyapi.decref(data_obj) c.builder.store(fail_obj, ret_ptr) ret() fill_value_obj = c.box(typ.fill_value_type, coo.fill_value) with cgutils.if_unlikely(c.builder, cgutils.is_null(c.builder, fill_value_obj)): c.pyapi.decref(shape_obj) c.pyapi.decref(coords_obj) c.pyapi.decref(data_obj) c.builder.store(fail_obj, ret_ptr) ret() class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(COO)) with cgutils.if_unlikely(c.builder, cgutils.is_null(c.builder, class_obj)): c.pyapi.decref(shape_obj) c.pyapi.decref(coords_obj) c.pyapi.decref(data_obj) c.pyapi.decref(fill_value_obj) c.builder.store(fail_obj, ret_ptr) ret() args = c.pyapi.tuple_pack([coords_obj, data_obj, shape_obj]) c.pyapi.decref(shape_obj) c.pyapi.decref(coords_obj) c.pyapi.decref(data_obj) with cgutils.if_unlikely(c.builder, cgutils.is_null(c.builder, args)): c.pyapi.decref(fill_value_obj) c.pyapi.decref(class_obj) c.builder.store(fail_obj, ret_ptr) ret() kwargs = c.pyapi.dict_pack([("fill_value", fill_value_obj)]) c.pyapi.decref(fill_value_obj) with cgutils.if_unlikely(c.builder, cgutils.is_null(c.builder, kwargs)): c.pyapi.decref(class_obj) c.builder.store(fail_obj, ret_ptr) ret() c.builder.store(c.pyapi.call(class_obj, args, kwargs), ret_ptr) c.pyapi.decref(class_obj) c.pyapi.decref(args) c.pyapi.decref(kwargs) return c.builder.load(ret_ptr) make_attribute_wrapper(COOType, "data", "data") make_attribute_wrapper(COOType, "coords", "coords") make_attribute_wrapper(COOType, "shape", "shape") make_attribute_wrapper(COOType, "fill_value", "fill_value") sparse-0.18.0/sparse/numba_backend/_dok.py000066400000000000000000000400401514474157100204400ustar00rootroot00000000000000from collections.abc import Iterable from numbers import Integral import numpy as np from numpy.lib.mixins import NDArrayOperatorsMixin from ._slicing import normalize_index from ._sparse_array import SparseArray from ._utils import equivalent class DOK(SparseArray, NDArrayOperatorsMixin): """ A class for building sparse multidimensional arrays. Parameters ---------- shape : tuple[int] (DOK.ndim,) The shape of the array. data : dict, optional The key-value pairs for the data in this array. dtype : np.dtype, optional The data type of this array. If left empty, it is inferred from the first element. fill_value : scalar, optional The fill value of this array. Attributes ---------- dtype : numpy.dtype The datatype of this array. Can be `None` if no elements have been set yet. shape : tuple[int] The shape of this array. data : dict The keys of this dictionary contain all the indices and the values contain the nonzero entries. See Also -------- [`sparse.COO`][] : A read-only sparse array. Examples -------- You can create [`sparse.DOK`][] objects from Numpy arrays. >>> x = np.eye(5, dtype=np.uint8) >>> x[2, 3] = 5 >>> s = DOK.from_numpy(x) >>> s You can also create them from just shapes, and use slicing assignment. >>> s2 = DOK((5, 5), dtype=np.int64) >>> s2[1:3, 1:3] = [[4, 5], [6, 7]] >>> s2 You can convert [`sparse.DOK`][] arrays to [`sparse.COO`][] arrays, or [`numpy.ndarray`][] objects. >>> from sparse import COO >>> s3 = COO(s2) >>> s3 >>> s2.todense() # doctest: +NORMALIZE_WHITESPACE array([[0, 0, 0, 0, 0], [0, 4, 5, 0, 0], [0, 6, 7, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]) >>> s4 = COO.from_numpy(np.eye(4, dtype=np.uint8)) >>> s4 >>> s5 = DOK.from_coo(s4) >>> s5 You can also create [`sparse.DOK`][] arrays from a shape and a dict of values. Zeros are automatically ignored. >>> values = { ... (1, 2, 3): 4, ... (3, 2, 1): 0, ... } >>> s6 = DOK((5, 5, 5), values) >>> s6 """ def __init__(self, shape, data=None, dtype=None, fill_value=None): from ._common import _is_scipy_sparse_obj from ._coo import COO self.data = {} if isinstance(shape, COO): ar = DOK.from_coo(shape) self._make_shallow_copy_of(ar) return if isinstance(shape, np.ndarray): ar = DOK.from_numpy(shape) self._make_shallow_copy_of(ar) return if _is_scipy_sparse_obj(shape): ar = DOK.from_scipy_sparse(shape) self._make_shallow_copy_of(ar) return self.dtype = np.dtype(dtype) if not data: data = {} super().__init__(shape, fill_value=fill_value) if isinstance(data, dict): if not dtype: if not len(data): self.dtype = np.dtype("float64") else: self.dtype = np.result_type(*(np.asarray(x).dtype for x in data.values())) for c, d in data.items(): self[c] = d else: raise ValueError("data must be a dict.") @classmethod def from_scipy_sparse(cls, x, /, *, fill_value=None): """ Create a [`sparse.DOK`][] array from a [`scipy.sparse.spmatrix`][]. Parameters ---------- x : scipy.sparse.spmatrix The matrix to convert. fill_value : scalar The fill-value to use when converting. Returns ------- DOK The equivalent [`sparse.DOK`][] array. Examples -------- >>> import scipy.sparse >>> x = scipy.sparse.rand(6, 3, density=0.2) >>> s = DOK.from_scipy_sparse(x) >>> np.array_equal(x.todense(), s.todense()) True """ from sparse import COO return COO.from_scipy_sparse(x, fill_value=fill_value).asformat(cls) @classmethod def from_coo(cls, x): """ Get a [`sparse.DOK`][] array from a [`sparse.COO`][] array. Parameters ---------- x : COO The array to convert. Returns ------- DOK The equivalent [`sparse.DOK`][] array. Examples -------- >>> from sparse import COO >>> s = COO.from_numpy(np.eye(4)) >>> s2 = DOK.from_coo(s) >>> s2 """ ar = cls(x.shape, dtype=x.dtype, fill_value=x.fill_value) for c, d in zip(x.coords.T, x.data, strict=True): ar.data[tuple(c)] = d return ar def to_coo(self): """ Convert this [`sparse.DOK`][] array to a [`sparse.COO`][] array. Returns ------- COO The equivalent [`sparse.COO`][] array. Examples -------- >>> s = DOK((5, 5)) >>> s[1:3, 1:3] = [[4, 5], [6, 7]] >>> s >>> s2 = s.to_coo() >>> s2 """ from ._coo import COO return COO(self) @classmethod def from_numpy(cls, x): """ Get a [`sparse.DOK`][] array from a Numpy array. Parameters ---------- x : np.ndarray The array to convert. Returns ------- DOK The equivalent [`sparse.DOK`][] array. Examples -------- >>> s = DOK.from_numpy(np.eye(4)) >>> s """ ar = cls(x.shape, dtype=x.dtype) coords = np.nonzero(x) data = x[coords] for c in zip(data, *coords, strict=True): d, c = c[0], c[1:] ar.data[c] = d return ar @property def nnz(self): """ The number of nonzero elements in this array. Returns ------- int The number of nonzero elements. See Also -------- - [`sparse.COO.nnz`][] : Equivalent [`sparse.COO`][] array property. - [`numpy.count_nonzero`][] : A similar Numpy function. - [`scipy.sparse.coo_array.nnz`][] : The Scipy equivalent property. Examples -------- >>> values = { ... (1, 2, 3): 4, ... (3, 2, 1): 0, ... } >>> s = DOK((5, 5, 5), values) >>> s.nnz 1 """ return len(self.data) @property def format(self): """ The storage format of this array. Returns ------- str The storage format of this array. See Also ------- [`scipy.sparse.dok_matrix.format`][] : The Scipy equivalent property. Examples ------- >>> import sparse >>> s = sparse.random((5, 5), density=0.2, format="dok") >>> s.format 'dok' >>> t = sparse.random((5, 5), density=0.2, format="coo") >>> t.format 'coo' """ return "dok" @property def nbytes(self): """ The number of bytes taken up by this object. Note that for small arrays, this may undercount the number of bytes due to the large constant overhead. Returns ------- int The approximate bytes of memory taken by this object. See Also -------- [`numpy.ndarray.nbytes`][] : The equivalent Numpy property. Examples -------- >>> import sparse >>> x = sparse.random((100, 100), density=0.1, format="dok") >>> x.nbytes 8000 """ return self.nnz * self.dtype.itemsize def __getitem__(self, key): if not isinstance(key, tuple): key = (key,) if all(isinstance(k, Iterable) for k in key): if len(key) != self.ndim: raise NotImplementedError(f"Index sequences for all {self.ndim} array dimensions needed!") if not all(len(key[0]) == len(k) for k in key): raise IndexError("Unequal length of index sequences!") return self._fancy_getitem(key) key = normalize_index(key, self.shape) ret = self.asformat("coo")[key] if isinstance(ret, SparseArray): ret = ret.asformat("dok") return ret def _fancy_getitem(self, key): """Subset of fancy indexing, when all dimensions are accessed""" new_data = {} for i, k in enumerate(zip(*key, strict=True)): if k in self.data: new_data[i] = self.data[k] return DOK( shape=(len(key[0])), data=new_data, dtype=self.dtype, fill_value=self.fill_value, ) def __setitem__(self, key, value): value = np.asarray(value, dtype=self.dtype) # 1D fancy indexing if self.ndim == 1 and isinstance(key, Iterable) and all(isinstance(i, int | np.integer) for i in key): key = (key,) if isinstance(key, tuple) and all(isinstance(k, Iterable) for k in key): if len(key) != self.ndim: raise NotImplementedError(f"Index sequences for all {self.ndim} array dimensions needed!") if not all(len(key[0]) == len(k) for k in key): raise IndexError("Unequal length of index sequences!") self._fancy_setitem(key, value) return key = normalize_index(key, self.shape) key_list = [int(k) if isinstance(k, Integral) else k for k in key] self._setitem(key_list, value) def _fancy_setitem(self, idxs, values): idxs = tuple(np.asanyarray(idxs) for idxs in idxs) if not all(np.issubdtype(k.dtype, np.integer) for k in idxs): raise IndexError("Indices must be sequences of integer types!") if idxs[0].ndim != 1: raise IndexError("Indices are not 1d sequences!") if values.ndim == 0: values = np.full(idxs[0].size, values, self.dtype) elif values.ndim > 1: raise ValueError(f"Dimension of values ({values.ndim}) must be 0 or 1!") if not idxs[0].shape == values.shape: raise ValueError(f"Shape mismatch of indices ({idxs[0].shape}) and values ({values.shape})!") fill_value = self.fill_value data = self.data for idx, value in zip(zip(*idxs, strict=True), values, strict=True): if value != fill_value: data[idx] = value elif idx in data: del data[idx] def _setitem(self, key_list, value): value_missing_dims = len([ind for ind in key_list if isinstance(ind, slice)]) - value.ndim if value_missing_dims < 0: raise ValueError("setting an array element with a sequence.") for i, ind in enumerate(key_list): if isinstance(ind, slice): step = ind.step if ind.step is not None else 1 if step > 0: start = ind.start if ind.start is not None else 0 start = max(start, 0) stop = ind.stop if ind.stop is not None else self.shape[i] stop = min(stop, self.shape[i]) if start > stop: start = stop else: start = ind.start or self.shape[i] - 1 stop = ind.stop if ind.stop is not None else -1 start = min(start, self.shape[i] - 1) stop = max(stop, -1) if start < stop: start = stop key_list_temp = key_list[:] for v_idx, ki in enumerate(range(start, stop, step)): key_list_temp[i] = ki vi = value if value_missing_dims > 0 else (value[0] if value.shape[0] == 1 else value[v_idx]) self._setitem(key_list_temp, vi) return if not isinstance(ind, Integral): raise IndexError("All indices must be slices or integers when setting an item.") key = tuple(key_list) if not equivalent(value, self.fill_value): self.data[key] = value[()] elif key in self.data: del self.data[key] def __str__(self): summary = f"" return self._str_impl(summary) __repr__ = __str__ def todense(self): """ Convert this [`sparse.DOK`][] array into a Numpy array. Returns ------- numpy.ndarray The equivalent dense array. See Also -------- - [`sparse.COO.todense`][] : Equivalent `COO` array method. - [`scipy.sparse.coo_array.todense`][] : Equivalent Scipy method. Examples -------- >>> s = DOK((5, 5)) >>> s[1:3, 1:3] = [[4, 5], [6, 7]] >>> s.todense() # doctest: +SKIP array([[0., 0., 0., 0., 0.], [0., 4., 5., 0., 0.], [0., 6., 7., 0., 0.], [0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.]]) """ result = np.full(self.shape, self.fill_value, self.dtype) for c, d in self.data.items(): result[c] = d return result def asformat(self, format, **kwargs): """ Convert this sparse array to a given format. Parameters ---------- format : str A format string. Returns ------- out : SparseArray The converted array. Raises ------ NotImplementedError If the format isn't supported. """ from ._utils import convert_format format = convert_format(format) if format == "dok": return self if format == "coo": from ._coo import COO if len(kwargs) != 0: raise ValueError(f"Extra kwargs found: {kwargs}") return COO.from_iter( self.data, shape=self.shape, fill_value=self.fill_value, dtype=self.dtype, ) return self.asformat("coo").asformat(format, **kwargs) def reshape(self, shape, order="C"): """ Returns a new [`sparse.DOK`][] array that is a reshaped version of this array. Parameters ---------- shape : tuple[int] The desired shape of the output array. Returns ------- DOK The reshaped output array. See Also -------- [`numpy.ndarray.reshape`][] : The equivalent Numpy function. Notes ----- The `order` parameter is provided just for compatibility with Numpy and isn't actually supported. Examples -------- >>> s = DOK.from_numpy(np.arange(25)) >>> s2 = s.reshape((5, 5)) >>> s2.todense() # doctest: +NORMALIZE_WHITESPACE array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19], [20, 21, 22, 23, 24]]) """ if order not in {"C", None}: raise NotImplementedError("The 'order' parameter is not supported") return DOK.from_coo(self.to_coo().reshape(shape)) def to_slice(k): """Convert integer indices to one-element slices for consistency""" if isinstance(k, Integral): return slice(k, k + 1, 1) return k sparse-0.18.0/sparse/numba_backend/_io.py000066400000000000000000000074321514474157100203020ustar00rootroot00000000000000import numpy as np from ._compressed import GCXS from ._coo.core import COO def save_npz(filename, matrix, compressed=True): """Save a sparse matrix to disk in numpy's `.npz` format. Note: This is not binary compatible with scipy's `save_npz()`. This binary format is not currently stable. Will save a file that can only be opend with this package's `load_npz()`. Parameters ---------- filename : string or file Either the file name (string) or an open file (file-like object) where the data will be saved. If file is a string or a Path, the `.npz` extension will be appended to the file name if it is not already there matrix : SparseArray The matrix to save to disk compressed : bool Whether to save in compressed or uncompressed mode Examples -------- Store sparse matrix to disk, and load it again: >>> import os >>> import sparse >>> import numpy as np >>> dense_mat = np.array([[[0.0, 0.0], [0.0, 0.70677779]], [[0.0, 0.0], [0.0, 0.86522495]]]) >>> mat = sparse.COO(dense_mat) >>> mat >>> sparse.save_npz("mat.npz", mat) >>> loaded_mat = sparse.load_npz("mat.npz") >>> loaded_mat >>> os.remove("mat.npz") See Also -------- - [`sparse.load_npz`][] - [`scipy.sparse.save_npz`][] - [`scipy.sparse.load_npz`][] - [`numpy.savez`][] - [`numpy.load`][] """ nodes = { "data": matrix.data, "shape": matrix.shape, "fill_value": matrix.fill_value, } if type(matrix) is COO: nodes["coords"] = matrix.coords elif type(matrix) is GCXS: nodes["indices"] = matrix.indices nodes["indptr"] = matrix.indptr nodes["compressed_axes"] = matrix.compressed_axes if compressed: np.savez_compressed(filename, **nodes) else: np.savez(filename, **nodes) def load_npz(filename): """Load a sparse matrix in numpy's `.npz` format from disk. Note: This is not binary compatible with scipy's `save_npz()` output. This binary format is not currently stable. Will only load files saved by this package. Parameters ---------- filename : file-like object, string, or pathlib.Path The file to read. File-like objects must support the `seek()` and `read()` methods. Returns ------- SparseArray The sparse matrix at path `filename`. Examples -------- See [`sparse.save_npz`][] for usage examples. See Also -------- - [`sparse.save_npz`][] - [`scipy.sparse.save_npz`][] - [`scipy.sparse.load_npz`][] - [`numpy.savez`][] - [`numpy.load`][] """ with np.load(filename) as fp: try: coords = fp["coords"] data = fp["data"] shape = tuple(fp["shape"]) fill_value = fp["fill_value"][()] return COO( coords=coords, data=data, shape=shape, sorted=True, has_duplicates=False, fill_value=fill_value, ) except KeyError: pass try: data = fp["data"] indices = fp["indices"] indptr = fp["indptr"] comp_axes = fp["compressed_axes"] shape = tuple(fp["shape"]) fill_value = fp["fill_value"][()] return GCXS( (data, indices, indptr), shape=shape, fill_value=fill_value, compressed_axes=comp_axes, ) except KeyError as e: raise RuntimeError(f"The file {filename!s} does not contain a valid sparse matrix") from e sparse-0.18.0/sparse/numba_backend/_numba_extension.py000066400000000000000000000002701514474157100230620ustar00rootroot00000000000000def _init_extension(): """ Load extensions when numba is loaded. This name must match the one in pyproject.toml """ from ._coo import numba_extension # noqa: F401 sparse-0.18.0/sparse/numba_backend/_settings.py000066400000000000000000000024301514474157100215240ustar00rootroot00000000000000import os import numpy as np AUTO_DENSIFY = bool(int(os.environ.get("SPARSE_AUTO_DENSIFY", "0"))) WARN_ON_TOO_DENSE = bool(int(os.environ.get("SPARSE_WARN_ON_TOO_DENSE", "0"))) IS_NUMPY2 = np.lib.NumpyVersion(np.__version__) >= "2.0.0a1" def _is_nep18_enabled(): class A: def __array_function__(self, *args, **kwargs): return True try: return np.concatenate([A()]) except ValueError: return False NEP18_ENABLED = _is_nep18_enabled() class ArrayNamespaceInfo: def __init__(self): self.np_info = np.__array_namespace_info__() def capabilities(self): np_capabilities = self.np_info.capabilities() return { "boolean indexing": False, "data-dependent shapes": True, "max dimensions": np_capabilities.get("max dimensions", 64) - 1, } def default_device(self): return self.np_info.default_device() def default_dtypes(self, *, device=None): return self.np_info.default_dtypes(device=device) def devices(self): return self.np_info.devices() def dtypes(self, *, device=None, kind=None): return self.np_info.dtypes(device=device, kind=kind) def __array_namespace_info__() -> ArrayNamespaceInfo: return ArrayNamespaceInfo() sparse-0.18.0/sparse/numba_backend/_slicing.py000066400000000000000000000210431514474157100213150ustar00rootroot00000000000000# Most of this file is taken from https://github.com/dask/dask/blob/main/dask/array/slicing.py # See license at https://github.com/dask/dask/blob/main/LICENSE.txt import math from collections.abc import Iterable from numbers import Integral, Number import numpy as np def normalize_index(idx, shape): """Normalize slicing indexes 1. Replaces ellipses with many full slices 2. Adds full slices to end of index 3. Checks bounding conditions 4. Replaces numpy arrays with lists 5. Posify's slices integers and lists 6. Normalizes slices to canonical form Examples -------- >>> normalize_index(1, (10,)) (1,) >>> normalize_index(-1, (10,)) (9,) >>> normalize_index([-1], (10,)) (array([9]),) >>> normalize_index(slice(-3, 10, 1), (10,)) (slice(7, 10, 1),) >>> normalize_index((Ellipsis, None), (10,)) (slice(0, 10, 1), None) """ if not isinstance(idx, tuple): idx = (idx,) idx = replace_ellipsis(len(shape), idx) n_sliced_dims = 0 for i in idx: if hasattr(i, "ndim") and i.ndim >= 1: n_sliced_dims += i.ndim elif i is None: continue else: n_sliced_dims += 1 idx += (slice(None),) * (len(shape) - n_sliced_dims) if len([i for i in idx if i is not None]) > len(shape): raise IndexError("Too many indices for array") none_shape = [] i = 0 for ind in idx: if ind is not None: none_shape.append(shape[i]) i += 1 else: none_shape.append(None) for i, d in zip(idx, none_shape, strict=True): if d is not None: check_index(i, d) idx = tuple(map(sanitize_index, idx)) idx = tuple(map(replace_none, idx, none_shape)) idx = posify_index(none_shape, idx) return tuple(map(clip_slice, idx, none_shape)) def replace_ellipsis(n, index): """Replace ... with slices, :, : ,: >>> replace_ellipsis(4, (3, Ellipsis, 2)) (3, slice(None, None, None), slice(None, None, None), 2) >>> replace_ellipsis(2, (Ellipsis, None)) (slice(None, None, None), slice(None, None, None), None) """ # Careful about using in or index because index may contain arrays isellipsis = [i for i, ind in enumerate(index) if ind is Ellipsis] if not isellipsis: return index if len(isellipsis) > 1: raise IndexError("an index can only have a single ellipsis ('...')") loc = isellipsis[0] extra_dimensions = n - (len(index) - sum(i is None for i in index) - 1) return index[:loc] + (slice(None, None, None),) * extra_dimensions + index[loc + 1 :] def check_index(ind, dimension): """Check validity of index for a given dimension Examples -------- >>> check_index(3, 5) >>> check_index(5, 5) Traceback (most recent call last): ... IndexError: Index is not smaller than dimension 5 >= 5 >>> check_index(6, 5) Traceback (most recent call last): ... IndexError: Index is not smaller than dimension 6 >= 5 >>> check_index(-1, 5) >>> check_index(-6, 5) Traceback (most recent call last): ... IndexError: Negative index is not greater than negative dimension -6 <= -5 >>> check_index([1, 2], 5) >>> check_index([6, 3], 5) Traceback (most recent call last): ... IndexError: Index out of bounds for dimension 5 >>> check_index(slice(0, 3), 5) """ # unknown dimension, assumed to be in bounds if isinstance(ind, Iterable): x = np.asanyarray(ind) if np.issubdtype(x.dtype, np.integer) and ((x >= dimension) | (x < -dimension)).any(): raise IndexError(f"Index out of bounds for dimension {dimension:d}") if x.dtype == np.bool_ and len(x) != dimension: raise IndexError( f"boolean index did not match indexed array; dimension is {dimension:d} " f"but corresponding boolean dimension is {len(x):d}" ) elif isinstance(ind, slice): return elif not isinstance(ind, Integral): raise IndexError( "only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and " "integer or boolean arrays are valid indices" ) elif ind >= dimension: raise IndexError(f"Index is not smaller than dimension {ind:d} >= {dimension:d}") elif ind < -dimension: msg = "Negative index is not greater than negative dimension {:d} <= -{:d}" raise IndexError(msg.format(ind, dimension)) def sanitize_index(ind): """Sanitize the elements for indexing along one axis >>> sanitize_index([2, 3, 5]) array([2, 3, 5]) >>> sanitize_index([True, False, True, False]) array([0, 2]) >>> sanitize_index(np.array([1, 2, 3])) array([1, 2, 3]) >>> sanitize_index(np.array([False, True, True])) array([1, 2]) >>> type(sanitize_index(np.int32(0))) # doctest: +SKIP >>> sanitize_index(0.5) # doctest: +SKIP Traceback (most recent call last): ... IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices """ if ind is None: return None if isinstance(ind, slice): return slice( _sanitize_index_element(ind.start), _sanitize_index_element(ind.stop), _sanitize_index_element(ind.step), ) if isinstance(ind, Number): return _sanitize_index_element(ind) if not hasattr(ind, "dtype") and len(ind) == 0: ind = np.array([], dtype=np.intp) ind = np.asarray(ind) if ind.dtype == np.bool_: nonzero = np.nonzero(ind) if len(nonzero) == 1: # If a 1-element tuple, unwrap the element nonzero = nonzero[0] return np.asanyarray(nonzero) if np.issubdtype(ind.dtype, np.integer): return ind raise IndexError( "only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and " "integer or boolean arrays are valid indices" ) def _sanitize_index_element(ind): """Sanitize a one-element index.""" if ind is None: return None return int(ind) def posify_index(shape, ind): """Flip negative indices around to positive ones >>> posify_index(10, 3) 3 >>> posify_index(10, -3) 7 >>> posify_index(10, [3, -3]) array([3, 7]) >>> posify_index((10, 20), (3, -3)) (3, 17) >>> posify_index((10, 20), (3, [3, 4, -3])) # doctest: +NORMALIZE_WHITESPACE (3, array([ 3, 4, 17])) """ if isinstance(ind, tuple): return tuple(map(posify_index, shape, ind)) if isinstance(ind, Integral): if ind < 0 and not math.isnan(shape): return ind + shape return ind if isinstance(ind, np.ndarray | list) and not math.isnan(shape): ind = np.asanyarray(ind) return np.where(ind < 0, ind + shape, ind) if isinstance(ind, slice): start, stop, step = ind.start, ind.stop, ind.step if start < 0: start += shape if not (0 > stop >= step) and stop < 0: stop += shape return slice(start, stop, ind.step) return ind def clip_slice(idx, dim): """ Clip slice to its effective size given the shape. Parameters ---------- idx : The index. dim : The size along the corresponding dimension. Returns ------- idx : slice Examples -------- >>> clip_slice(slice(0, 20, 1), 10) slice(0, 10, 1) """ if not isinstance(idx, slice): return idx start, stop, step = idx.start, idx.stop, idx.step if step > 0: start = max(start, 0) stop = min(stop, dim) if start > stop: start = stop else: start = min(start, dim - 1) stop = max(stop, -1) if start < stop: start = stop return slice(start, stop, step) def replace_none(idx, dim): """ Normalize slices to canonical form, i.e. replace ``None`` with the appropriate integers. Parameters ---------- idx : slice or other index dim : dimension length Examples -------- >>> replace_none(slice(None, None, None), 10) slice(0, 10, 1) """ if not isinstance(idx, slice): return idx start, stop, step = idx.start, idx.stop, idx.step if step is None: step = 1 if step > 0: if start is None: start = 0 if stop is None: stop = dim else: if start is None: start = dim - 1 if stop is None: stop = -1 return slice(start, stop, step) sparse-0.18.0/sparse/numba_backend/_sparse_array.py000066400000000000000000000740061514474157100223670ustar00rootroot00000000000000import contextlib import operator import warnings from abc import ABCMeta, abstractmethod from collections.abc import Callable, Iterable from functools import reduce from numbers import Integral import numpy as np from ._umath import elemwise from ._utils import _zero_of_dtype, equivalent, html_table, normalize_axis _reduce_super_ufunc = {np.add: np.multiply, np.multiply: np.power} class SparseArray: """ An abstract base class for all the sparse array classes. Attributes ---------- dtype : numpy.dtype The data type of this array. fill_value : scalar The fill value of this array. """ __metaclass__ = ABCMeta def __init__(self, shape, fill_value=None): if not isinstance(shape, Iterable): shape = (shape,) if not all(isinstance(sh, Integral) and int(sh) >= 0 for sh in shape): raise ValueError("shape must be an non-negative integer or a tuple of non-negative integers.") self.shape = tuple(int(sh) for sh in shape) if fill_value is not None: if not hasattr(fill_value, "dtype") or fill_value.dtype != self.dtype: self.fill_value = self.dtype.type(fill_value) else: self.fill_value = fill_value else: self.fill_value = _zero_of_dtype(self.dtype) dtype = None @property def device(self): data = getattr(self, "data", None) return getattr(data, "device", "cpu") def to_device(self, device, /, *, stream=None): if device != "cpu": raise ValueError("Only `device='cpu'` is supported.") return self @property @abstractmethod def nnz(self): """ The number of nonzero elements in this array. Note that any duplicates in `coords` are counted multiple times. Returns ------- int The number of nonzero elements in this array. See Also -------- - [`sparse.DOK.nnz`][] : Equivalent [`sparse.DOK`][] array property. - [`numpy.count_nonzero`][] : A similar Numpy function. - [`scipy.sparse.coo_array.nnz`][] : The Scipy equivalent property. Examples -------- >>> import numpy as np >>> from sparse import COO >>> x = np.array([0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 0]) >>> np.count_nonzero(x) np.int64(6) >>> s = COO.from_numpy(x) >>> s.nnz 6 >>> np.count_nonzero(x) == s.nnz np.True_ """ @property def ndim(self): """ The number of dimensions of this array. Returns ------- int The number of dimensions of this array. See Also -------- - [`sparse.DOK.ndim`][] : Equivalent property for [`sparse.DOK`][] arrays. - [`numpy.ndarray.ndim`][] : Numpy equivalent property. Examples -------- >>> from sparse import COO >>> import numpy as np >>> x = np.random.rand(1, 2, 3, 1, 2) >>> s = COO.from_numpy(x) >>> s.ndim 5 >>> s.ndim == x.ndim True """ return len(self.shape) @property def size(self): """ The number of all elements (including zeros) in this array. Returns ------- int The number of elements. See Also -------- [`numpy.ndarray.size`][] : Numpy equivalent property. Examples -------- >>> from sparse import COO >>> import numpy as np >>> x = np.zeros((10, 10)) >>> s = COO.from_numpy(x) >>> s.size 100 """ # We use this instead of np.prod because np.prod # returns a float64 for an empty shape. return reduce(operator.mul, self.shape, 1) @property def density(self): """ The ratio of nonzero to all elements in this array. Returns ------- float The ratio of nonzero to all elements. See Also -------- - [`sparse.COO.size`][] : Number of elements. - [`sparse.COO.nnz`][] : Number of nonzero elements. Examples -------- >>> import numpy as np >>> from sparse import COO >>> x = np.zeros((8, 8)) >>> x[0, :] = 1 >>> s = COO.from_numpy(x) >>> s.density 0.125 """ with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=RuntimeWarning) return float(np.float64(self.nnz) / np.float64(self.size)) def _repr_html_(self): """ Diagnostic report about this array. Renders in Jupyter. """ try: from matrepr import to_html from matrepr.adapters.sparse_driver import PyDataSparseDriver return to_html(PyDataSparseDriver.adapt(self), notebook=True) except (ImportError, ValueError): return html_table(self) def _str_impl(self, summary): """ A human-readable representation of this array, including a metadata summary and a tabular view of the array values. Values view only included if `matrepr` is available. Parameters ---------- summary A type-specific summary of this array, used as the first line of return value. Returns ------- str A human-readable representation of this array. """ try: from matrepr import to_str from matrepr.adapters.sparse_driver import PyDataSparseDriver values = to_str( PyDataSparseDriver.adapt(self), title=False, # disable matrepr description width_str=0, # autodetect terminal width max_cols=9999, ) return f"{summary}\n{values}" except (ImportError, ValueError): return summary @abstractmethod def asformat(self, format): """ Convert this sparse array to a given format. Parameters ---------- format : str A format string. Returns ------- out : SparseArray The converted array. Raises ------ NotImplementedError If the format isn't supported. """ @abstractmethod def todense(self): """ Convert this [`sparse.SparseArray`][] array to a dense [`numpy.ndarray`][]. Note that this may take a large amount of memory and time. Returns ------- numpy.ndarray The converted dense array. See Also -------- - [`sparse.DOK.todense`][] : Equivalent `DOK` array method. - [`sparse.COO.todense`][] : Equivalent `COO` array method. - [`scipy.sparse.coo_array.todense`][] : Equivalent Scipy method. Examples -------- >>> import sparse >>> x = np.random.randint(100, size=(7, 3)) >>> s = sparse.COO.from_numpy(x) >>> x2 = s.todense() >>> np.array_equal(x, x2) True """ def _make_shallow_copy_of(self, other): self.__dict__ = other.__dict__.copy() def __array__(self, *args, **kwargs): from ._settings import AUTO_DENSIFY if not AUTO_DENSIFY: raise RuntimeError( "Cannot convert a sparse array to dense automatically. To manually densify, use the todense method." ) return np.asarray(self.todense(), *args, **kwargs) def __array_function__(self, func, types, args, kwargs): import sparse as module sparse_func = None try: submodules = getattr(func, "__module__", "numpy").split(".")[1:] for submodule in submodules: module = getattr(module, submodule) sparse_func = getattr(module, func.__name__) except AttributeError: pass else: return sparse_func(*args, **kwargs) with contextlib.suppress(AttributeError): sparse_func = getattr(type(self), func.__name__) if not isinstance(sparse_func, Callable) and len(args) == 1 and len(kwargs) == 0: try: return getattr(self, func.__name__) except AttributeError: pass if sparse_func is None: return NotImplemented return sparse_func(*args, **kwargs) @staticmethod def _reduce(method, *args, **kwargs): from ._common import _is_scipy_sparse_obj assert len(args) == 1 self = args[0] if _is_scipy_sparse_obj(self): self = type(self).from_scipy_sparse(self) return self.reduce(method, **kwargs) def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): out = kwargs.pop("out", None) if out is not None and not all(isinstance(x, type(self)) for x in out): return NotImplemented if getattr(ufunc, "signature", None) is not None: return self.__array_function__(ufunc, (np.ndarray, type(self)), inputs, kwargs) if out is not None: test_args = [np.empty((1,), dtype=a.dtype) if hasattr(a, "dtype") else a for a in inputs] test_kwargs = kwargs.copy() if method == "reduce": test_kwargs["axis"] = None test_out = tuple(np.empty((1,), dtype=a.dtype) for a in out) if len(test_out) == 1: test_out = test_out[0] getattr(ufunc, method)(*test_args, out=test_out, **test_kwargs) kwargs["dtype"] = out[0].dtype if method == "outer": method = "__call__" cum_ndim = 0 inputs_transformed = [] for inp in reversed(inputs): inputs_transformed.append(inp[(Ellipsis,) + (None,) * cum_ndim]) cum_ndim += inp.ndim inputs = tuple(reversed(inputs_transformed)) if method == "__call__": result = elemwise(ufunc, *inputs, **kwargs) elif method == "reduce": result = SparseArray._reduce(ufunc, *inputs, **kwargs) else: return NotImplemented if out is not None: (out,) = out if out.shape != result.shape: raise ValueError( f"non-broadcastable output operand with shape {out.shape} " f"doesn't match the broadcast shape {result.shape}" ) out._make_shallow_copy_of(result) return out return result def reduce(self, method, axis=(0,), keepdims=False, **kwargs): """ Performs a reduction operation on this array. Parameters ---------- method : numpy.ufunc The method to use for performing the reduction. axis : Union[int, Iterable[int]], optional The axes along which to perform the reduction. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. **kwargs : dict Any extra arguments to pass to the reduction operation. See Also -------- - [`numpy.ufunc.reduce`][] : A similar Numpy method. - [`sparse.COO.reduce`][] : This method implemented on COO arrays. - [`sparse.GCXS.reduce`][] : This method implemented on GCXS arrays. """ axis = normalize_axis(axis, self.ndim) zero_reduce_result = method.reduce([self.fill_value, self.fill_value], **kwargs) reduce_super_ufunc = _reduce_super_ufunc.get(method) if not equivalent(zero_reduce_result, self.fill_value) and reduce_super_ufunc is None: raise ValueError(f"Performing this reduction operation would produce a dense result: {method!s}") if not isinstance(axis, tuple): axis = (axis,) out = self._reduce_calc(method, axis, keepdims, **kwargs) if len(out) == 1: return out[0] data, counts, axis, n_cols, arr_attrs = out result_fill_value = self.fill_value if reduce_super_ufunc is None: missing_counts = counts != n_cols data[missing_counts] = method(data[missing_counts], self.fill_value, **kwargs) else: data = method( data, reduce_super_ufunc(self.fill_value, n_cols - counts), ).astype(data.dtype) result_fill_value = reduce_super_ufunc(self.fill_value, n_cols) out = self._reduce_return(data, arr_attrs, result_fill_value) if keepdims: shape = list(self.shape) for ax in axis: shape[ax] = 1 out = out.reshape(shape) if out.ndim == 0: return out[()] return out def _reduce_calc(self, method, axis, keepdims, **kwargs): raise NotImplementedError def _reduce_return(self, data, arr_attrs, result_fill_value): raise NotImplementedError def sum(self, axis=None, keepdims=False, dtype=None, out=None): """ Performs a sum operation along the given axes. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to sum. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. dtype : numpy.dtype The data type of the output array. Returns ------- SparseArray The reduced output sparse array. See Also -------- - [`numpy.sum`][] : Equivalent numpy function. - [`scipy.sparse.coo_array.sum`][] : Equivalent Scipy function. """ return np.add.reduce(self, out=out, axis=axis, keepdims=keepdims, dtype=dtype) def max(self, axis=None, keepdims=False, out=None): """ Maximize along the given axes. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to maximize. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. out : numpy.dtype The data type of the output array. Returns ------- SparseArray The reduced output sparse array. See Also -------- - [`numpy.max`][] : Equivalent numpy function. - [`scipy.sparse.coo_array.max`][] : Equivalent Scipy function. """ return np.maximum.reduce(self, out=out, axis=axis, keepdims=keepdims) amax = max def any(self, axis=None, keepdims=False, out=None): """ See if any values along array are ``True``. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to minimize. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. Returns ------- SparseArray The reduced output sparse array. See Also -------- [`numpy.any`][] : Equivalent numpy function. """ return np.logical_or.reduce(self, out=out, axis=axis, keepdims=keepdims) def all(self, axis=None, keepdims=False, out=None): """ See if all values in an array are ``True``. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to minimize. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. Returns ------- SparseArray The reduced output sparse array. See Also -------- [`numpy.all`][] : Equivalent numpy function. """ return np.logical_and.reduce(self, out=out, axis=axis, keepdims=keepdims) def min(self, axis=None, keepdims=False, out=None): """ Minimize along the given axes. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to minimize. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. out : numpy.dtype The data type of the output array. Returns ------- SparseArray The reduced output sparse array. See Also -------- - [`numpy.min`][] : Equivalent numpy function. - [`scipy.sparse.coo_array.min`][] : Equivalent Scipy function. """ return np.minimum.reduce(self, out=out, axis=axis, keepdims=keepdims) amin = min def prod(self, axis=None, keepdims=False, dtype=None, out=None): """ Performs a product operation along the given axes. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to multiply. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. dtype : numpy.dtype The data type of the output array. Returns ------- SparseArray The reduced output sparse array. See Also -------- [`numpy.prod`][] : Equivalent numpy function. """ return np.multiply.reduce(self, out=out, axis=axis, keepdims=keepdims, dtype=dtype) def round(self, decimals=0, out=None): """ Evenly round to the given number of decimals. See Also -------- - [`numpy.round`][] : NumPy equivalent ufunc. - [`sparse.elemwise`][] : Apply an arbitrary element-wise function to one or two arguments. """ if out is not None and not isinstance(out, tuple): out = (out,) return self.__array_ufunc__(np.round, "__call__", self, decimals=decimals, out=out) round_ = round def clip(self, min=None, max=None, out=None): """ Clip (limit) the values in the array. Return an array whose values are limited to ``[min, max]``. One of min or max must be given. See Also -------- - [sparse.clip][] : For full documentation and more details. - [`numpy.clip`][] : Equivalent NumPy function. """ if out is not None and not isinstance(out, tuple): out = (out,) return self.__array_ufunc__(np.clip, "__call__", self, a_min=min, a_max=max, out=out) def astype(self, dtype, casting="unsafe", copy=True): """ Copy of the array, cast to a specified type. See Also -------- - [`scipy.sparse.coo_array.astype`][] : SciPy sparse equivalent function - [`numpy.ndarray.astype`][] : NumPy equivalent ufunc. - [`sparse.elemwise`][] : Apply an arbitrary element-wise function to one or two arguments. """ # this matches numpy's behavior if self.dtype == dtype and not copy: return self return self.__array_ufunc__(np.ndarray.astype, "__call__", self, dtype=dtype, copy=copy, casting=casting) def mean(self, axis=None, keepdims=False, dtype=None, out=None): """ Compute the mean along the given axes. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to compute the mean. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. dtype : numpy.dtype The data type of the output array. Returns ------- SparseArray The reduced output sparse array. See Also -------- - [`numpy.ndarray.mean`][] : Equivalent numpy method. - [`scipy.sparse.coo_array.mean`][] : Equivalent Scipy method. Notes ----- * The `out` parameter is provided just for compatibility with Numpy and isn't actually supported. Examples -------- You can use [`sparse.COO.mean`][] to compute the mean of an array across any dimension. >>> from sparse import COO >>> x = np.array([[1, 2, 0, 0], [0, 1, 0, 0]], dtype="i8") >>> s = COO.from_numpy(x) >>> s2 = s.mean(axis=1) >>> s2.todense() # doctest: +SKIP array([0.5, 1.5, 0., 0.]) You can also use the `keepdims` argument to keep the dimensions after the mean. >>> s3 = s.mean(axis=0, keepdims=True) >>> s3.shape (1, 4) You can pass in an output datatype, if needed. >>> s4 = s.mean(axis=0, dtype=np.float16) >>> s4.dtype dtype('float16') By default, this reduces the array down to one number, computing the mean along all axes. >>> s.mean() np.float64(0.5) """ if axis is None: axis = tuple(range(self.ndim)) elif not isinstance(axis, tuple): axis = (axis,) den = reduce(operator.mul, (self.shape[i] for i in axis), 1) if dtype is None: if issubclass(self.dtype.type, np.integer | np.bool_): dtype = inter_dtype = np.dtype("f8") else: dtype = self.dtype inter_dtype = np.dtype("f4") if issubclass(dtype.type, np.float16) else dtype else: inter_dtype = dtype num = self.sum(axis=axis, keepdims=keepdims, dtype=inter_dtype) if num.ndim: out = np.true_divide(num, den, casting="unsafe") return out.astype(dtype) if out.dtype != dtype else out return np.divide(num, den, dtype=dtype, out=out) def var(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False): """ Compute the variance along the given axes. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to compute the variance. Uses all axes by default. dtype : numpy.dtype, optional The output datatype. out : SparseArray, optional The array to write the output to. ddof : int The degrees of freedom. keepdims : bool, optional Whether or not to keep the dimensions of the original array. Returns ------- SparseArray The reduced output sparse array. See Also -------- [`numpy.ndarray.var`][] : Equivalent numpy method. Examples -------- You can use [`sparse.COO.var`][] to compute the variance of an array across any dimension. >>> from sparse import COO >>> x = np.array([[1, 2, 0, 0], [0, 1, 0, 0]], dtype="i8") >>> s = COO.from_numpy(x) >>> s2 = s.var(axis=1) >>> s2.todense() # doctest: +SKIP array([0.6875, 0.1875]) You can also use the `keepdims` argument to keep the dimensions after the variance. >>> s3 = s.var(axis=0, keepdims=True) >>> s3.shape (1, 4) You can pass in an output datatype, if needed. >>> s4 = s.var(axis=0, dtype=np.float16) >>> s4.dtype dtype('float16') By default, this reduces the array down to one number, computing the variance along all axes. >>> s.var() np.float64(0.5) """ axis = normalize_axis(axis, self.ndim) if axis is None: axis = tuple(range(self.ndim)) if not isinstance(axis, tuple): axis = (axis,) rcount = reduce(operator.mul, (self.shape[a] for a in axis), 1) # Make this warning show up on top. if ddof >= rcount: warnings.warn("Degrees of freedom <= 0 for slice", RuntimeWarning, stacklevel=1) # Cast bool, unsigned int, and int to float64 by default if dtype is None and issubclass(self.dtype.type, np.integer | np.bool_): dtype = np.dtype("f8") arrmean = self.sum(axis, dtype=dtype, keepdims=True)[...] np.divide(arrmean, rcount, out=arrmean) x = self - arrmean if issubclass(self.dtype.type, np.complexfloating): x = x.real * x.real + x.imag * x.imag else: x = np.multiply(x, x, out=x) ret = x.sum(axis=axis, dtype=dtype, out=out, keepdims=keepdims) # Compute degrees of freedom and make sure it is not negative. rcount = max([rcount - ddof, 0]) ret = ret[...] np.divide(ret, rcount, out=ret, casting="unsafe") return ret[()] def std(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False): """ Compute the standard deviation along the given axes. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to compute the standard deviation. Uses all axes by default. dtype : numpy.dtype, optional The output datatype. out : SparseArray, optional The array to write the output to. ddof : int The degrees of freedom. keepdims : bool, optional Whether or not to keep the dimensions of the original array. Returns ------- SparseArray The reduced output sparse array. See Also -------- [`numpy.ndarray.std`][] : Equivalent numpy method. Examples -------- You can use [`sparse.COO.std`][] to compute the standard deviation of an array across any dimension. >>> from sparse import COO >>> x = np.array([[1, 2, 0, 0], [0, 1, 0, 0]], dtype="i8") >>> s = COO.from_numpy(x) >>> s2 = s.std(axis=1) >>> s2.todense() # doctest: +SKIP array([0.8291562, 0.4330127]) You can also use the `keepdims` argument to keep the dimensions after the standard deviation. >>> s3 = s.std(axis=0, keepdims=True) >>> s3.shape (1, 4) You can pass in an output datatype, if needed. >>> s4 = s.std(axis=0, dtype=np.float16) >>> s4.dtype dtype('float16') By default, this reduces the array down to one number, computing the standard deviation along all axes. >>> s.std() # doctest: +SKIP 0.7071067811865476 """ ret = self.var(axis=axis, dtype=dtype, out=out, ddof=ddof, keepdims=keepdims) return np.sqrt(ret) @property def real(self): """The real part of the array. Examples -------- >>> from sparse import COO >>> x = COO.from_numpy([1 + 0j, 0 + 1j]) >>> x.real.todense() # doctest: +SKIP array([1., 0.]) >>> x.real.dtype dtype('float64') Returns ------- out : SparseArray The real component of the array elements. If the array dtype is real, the dtype of the array is used for the output. If the array is complex, the output dtype is float. See Also -------- - [`numpy.ndarray.real`][] : NumPy equivalent attribute. - [`numpy.real`][] : NumPy equivalent function. """ return self.__array_ufunc__(np.real, "__call__", self) @property def imag(self): """The imaginary part of the array. Examples -------- >>> from sparse import COO >>> x = COO.from_numpy([1 + 0j, 0 + 1j]) >>> x.imag.todense() # doctest: +SKIP array([0., 1.]) >>> x.imag.dtype dtype('float64') Returns ------- out : SparseArray The imaginary component of the array elements. If the array dtype is real, the dtype of the array is used for the output. If the array is complex, the output dtype is float. See Also -------- - [`numpy.ndarray.imag`][] : NumPy equivalent attribute. - [`numpy.imag`][] : NumPy equivalent function. """ return self.__array_ufunc__(np.imag, "__call__", self) def conj(self): """Return the complex conjugate, element-wise. The complex conjugate of a complex number is obtained by changing the sign of its imaginary part. Examples -------- >>> from sparse import COO >>> x = COO.from_numpy([1 + 2j, 2 - 1j]) >>> res = x.conj() >>> res.todense() # doctest: +SKIP array([1.-2.j, 2.+1.j]) >>> res.dtype dtype('complex128') Returns ------- out : SparseArray The complex conjugate, with same dtype as the input. See Also -------- - [`numpy.ndarray.conj`][] : NumPy equivalent method. - [`numpy.conj`][] : NumPy equivalent function. """ return np.conj(self) def __array_namespace__(self, *, api_version=None): if api_version is None: api_version = "2024.12" if api_version not in {"2021.12", "2022.12", "2023.12", "2024.12"}: raise ValueError(f'"{api_version}" Array API version not supported.') import sparse return sparse def __bool__(self): """ """ return self._to_scalar(bool) def __float__(self): """ """ return self._to_scalar(float) def __int__(self): """ """ return self._to_scalar(int) def __index__(self): """ """ return self._to_scalar(int) def __complex__(self): """ """ return self._to_scalar(complex) def _to_scalar(self, builtin): if self.size != 1 or self.shape != (): raise ValueError(f"{builtin} can be computed for one-element arrays only.") return builtin(self.todense().flatten()[0]) @abstractmethod def isinf(self): """ """ @abstractmethod def isnan(self): """ """ sparse-0.18.0/sparse/numba_backend/_umath.py000066400000000000000000000570521514474157100210140ustar00rootroot00000000000000import itertools import operator from functools import reduce from itertools import zip_longest import numba import numpy as np from ._utils import _zero_of_dtype, equivalent, isscalar def elemwise(func, *args, **kwargs): """ Apply a function to any number of arguments. Parameters ---------- func : Callable The function to apply. Must support broadcasting. *args : tuple, optional The arguments to the function. Can be [`sparse.SparseArray`][] objects or [`scipy.sparse.spmatrix`][] objects. **kwargs : dict, optional Any additional arguments to pass to the function. Returns ------- SparseArray The result of applying the function. Raises ------ ValueError If the operation would result in a dense matrix, or if the operands don't have broadcastable shapes. See Also -------- [`numpy.ufunc`][] : A similar Numpy construct. Note that any `ufunc` can be used as the `func` input to this function. Notes ----- Previously, operations with Numpy arrays were sometimes supported. Now, it is necessary to convert Numpy arrays to [`sparse.COO`][] objects. """ return _Elemwise(func, *args, **kwargs).get_result() @numba.jit(nopython=True, nogil=True) def _match_arrays(a, b): # pragma: no cover """ Finds all indexes into a and b such that a[i] = b[j]. The outputs are sorted in lexographical order. Parameters ---------- a, b : np.ndarray The input 1-D arrays to match. If matching of multiple fields is needed, use np.recarrays. These two arrays must be sorted. Returns ------- a_idx, b_idx : np.ndarray The output indices of every possible pair of matching elements. """ if len(a) == 0 or len(b) == 0: return np.empty(0, dtype=np.uintp), np.empty(0, dtype=np.uintp) a_ind, b_ind = [], [] nb = len(b) ib = 0 match = 0 for ia, j in enumerate(a): if j == b[match]: ib = match while ib < nb and j >= b[ib]: if j == b[ib]: a_ind.append(ia) b_ind.append(ib) if b[match] < b[ib]: match = ib ib += 1 return np.array(a_ind, dtype=np.uintp), np.array(b_ind, dtype=np.uintp) def _get_nary_broadcast_shape(*shapes): """ Broadcast any number of shapes to a result shape. Parameters ---------- *shapes : tuple[tuple[int]] The shapes to broadcast. Returns ------- tuple[int] The output shape. Raises ------ ValueError If the input shapes cannot be broadcast to a single shape. """ result_shape = () for shape in shapes: try: result_shape = _get_broadcast_shape(shape, result_shape) except ValueError as e: # noqa: PERF203 shapes_str = ", ".join(str(shape) for shape in shapes) raise ValueError(f"operands could not be broadcast together with shapes {shapes_str}") from e return result_shape def _get_broadcast_shape(shape1, shape2, is_result=False): """ Get the overall broadcasted shape. Parameters ---------- shape1, shape2 : tuple[int] The input shapes to broadcast together. is_result : bool Whether or not shape2 is also the result shape. Returns ------- result_shape : tuple[int] The overall shape of the result. Raises ------ ValueError If the two shapes cannot be broadcast together. """ # https://stackoverflow.com/a/47244284/774273 if not all( (l1 == l2) or (l1 == 1) or ((l2 == 1) and not is_result) for l1, l2 in zip(shape1[::-1], shape2[::-1], strict=False) ): raise ValueError(f"operands could not be broadcast together with shapes {shape1}, {shape2}") return tuple(l1 if l1 != 1 else l2 for l1, l2 in zip_longest(shape1[::-1], shape2[::-1], fillvalue=1))[::-1] def _get_broadcast_parameters(shape, broadcast_shape): """ Get the broadcast parameters. Parameters ---------- shape : tuple[int] The input shape. broadcast_shape The shape to broadcast to. Returns ------- params : list A list containing None if the dimension isn't in the original array, False if it needs to be broadcast, and True if it doesn't. """ return [ None if l1 is None else l1 == l2 for l1, l2 in zip_longest(shape[::-1], broadcast_shape[::-1], fillvalue=None) ][::-1] def _get_reduced_coords(coords, params): """ Gets only those dimensions of the coordinates that don't need to be broadcast. Parameters ---------- coords : np.ndarray The coordinates to reduce. params : list The params from which to check which dimensions to get. Returns ------- reduced_coords : np.ndarray The reduced coordinates. """ reduced_params = [bool(param) for param in params] return coords[reduced_params] def _get_reduced_shape(shape, params): """ Gets only those dimensions of the coordinates that don't need to be broadcast. Parameters ---------- shape : np.ndarray The coordinates to reduce. params : list The params from which to check which dimensions to get. Returns ------- reduced_coords : np.ndarray The reduced coordinates. """ return tuple(sh for sh, p in zip(shape, params, strict=True) if p) def _get_expanded_coords_data(coords, data, params, broadcast_shape): """ Expand coordinates/data to broadcast_shape. Does most of the heavy lifting for broadcast_to. Produces sorted output for sorted inputs. Parameters ---------- coords : np.ndarray The coordinates to expand. data : np.ndarray The data corresponding to the coordinates. params : list The broadcast parameters. broadcast_shape : tuple[int] The shape to broadcast to. Returns ------- expanded_coords : np.ndarray List of 1-D arrays. Each item in the list has one dimension of coordinates. expanded_data : np.ndarray The data corresponding to expanded_coords. """ first_dim = -1 expand_shapes = [] for d, p, sh in zip(range(len(broadcast_shape)), params, broadcast_shape, strict=True): if p and first_dim == -1: expand_shapes.append(coords.shape[1]) first_dim = d if not p: expand_shapes.append(sh) all_idx = _cartesian_product(*(np.arange(d, dtype=np.intp) for d in expand_shapes)) false_dim = 0 dim = 0 expanded_coords = np.empty((len(broadcast_shape), all_idx.shape[1]), dtype=np.intp) if first_dim != -1: expanded_data = data[all_idx[first_dim]] else: expanded_coords = all_idx if len(data) else np.empty((0, all_idx.shape[1]), dtype=np.intp) expanded_data = np.repeat(data, reduce(operator.mul, broadcast_shape, 1)) return np.asarray(expanded_coords), np.asarray(expanded_data) for d, p in zip(range(len(broadcast_shape)), params, strict=True): if p: expanded_coords[d] = coords[dim, all_idx[first_dim]] else: expanded_coords[d] = all_idx[false_dim + (d > first_dim)] false_dim += 1 if p is not None: dim += 1 return np.asarray(expanded_coords), np.asarray(expanded_data) # (c) senderle # Taken from https://stackoverflow.com/a/11146645/774273 # License: https://creativecommons.org/licenses/by-sa/3.0/ def _cartesian_product(*arrays): """ Get the cartesian product of a number of arrays. Parameters ---------- *arrays : Tuple[np.ndarray] The arrays to get a cartesian product of. Always sorted with respect to the original array. Returns ------- out : np.ndarray The overall cartesian product of all the input arrays. """ broadcastable = np.ix_(*arrays) broadcasted = np.broadcast_arrays(*broadcastable) rows, cols = np.prod(broadcasted[0].shape), len(broadcasted) dtype = np.result_type(*arrays) out = np.empty(rows * cols, dtype=dtype) start, end = 0, rows for a in broadcasted: out[start:end] = a.reshape(-1) start, end = end, end + rows return out.reshape(cols, rows) def _get_matching_coords(coords, params): """ Get the matching coords across a number of broadcast operands. Parameters ---------- coords : list[`numpy.ndarray`] The input coordinates. params : list[Union[bool, none]] The broadcast parameters. Returns ------- numpy.ndarray The broacasted coordinates """ matching_coords = [] dims = np.zeros(len(coords), dtype=np.uint8) for p_all in zip(*params, strict=True): for i, p in enumerate(p_all): if p: matching_coords.append(coords[i][dims[i]]) break else: matching_coords.append(coords[dims[0]]) for i, p in enumerate(p_all): if p is not None: dims[i] += 1 return np.asarray(matching_coords, dtype=np.intp) def broadcast_to(x, shape): """ Performs the equivalent of `numpy.broadcast_to` for `COO`. Note that this function returns a new array instead of a view. Parameters ---------- shape : tuple[int] The shape to broadcast the data to. Returns ------- COO The broadcasted sparse array. Raises ------ ValueError If the operand cannot be broadcast to the given shape. See Also -------- :obj:`numpy.broadcast_to` : NumPy equivalent function """ from ._coo import COO if shape == x.shape: return x result_shape = _get_broadcast_shape(x.shape, shape, is_result=True) params = _get_broadcast_parameters(x.shape, result_shape) coords, data = _get_expanded_coords_data(x.coords, x.data, params, result_shape) # Check if all the non-broadcast axes are next to each other nonbroadcast_idx = [idx for idx, p in enumerate(params) if p] diff_nonbroadcast_idx = [a - b for a, b in zip(nonbroadcast_idx[1:], nonbroadcast_idx[:-1], strict=True)] sorted = all(d == 1 for d in diff_nonbroadcast_idx) return COO( coords, data, shape=result_shape, has_duplicates=False, sorted=sorted, fill_value=x.fill_value, ) class _Elemwise: def __init__(self, func, *args, **kwargs): """ Initialize the element-wise function calculator. Parameters ---------- func : types.Callable The function to compute *args : tuple[Union[SparseArray, ndarray, scipy.sparse.spmatrix]] The arguments to compute the function on. **kwargs : dict Extra arguments to pass to the function. """ from ._common import _is_scipy_sparse_obj from ._compressed import GCXS from ._coo import COO from ._dok import DOK from ._sparse_array import SparseArray processed_args = [] out_type = GCXS out_kwargs = {} sparse_args = [arg for arg in args if isinstance(arg, SparseArray)] if len(sparse_args) == 0: raise ValueError(f"None of the args is sparse: {args}") if all(isinstance(arg, DOK) for arg in sparse_args): out_type = DOK elif all(isinstance(arg, GCXS) for arg in sparse_args): out_type = GCXS if len({arg.compressed_axes for arg in sparse_args}) == 1: out_kwargs["compressed_axes"] = sparse_args[0].compressed_axes else: out_type = COO for arg in args: if _is_scipy_sparse_obj(arg): processed_args.append(COO.from_scipy_sparse(arg)) elif isscalar(arg) or isinstance(arg, np.ndarray): # Faster and more reliable to pass ()-shaped ndarrays as scalars. processed_args.append(arg) elif isinstance(arg, SparseArray): if not isinstance(arg, COO): arg = arg.asformat(COO) if arg.ndim == 0: arg = arg.todense() processed_args.append(arg) else: self.args = None return self.out_type = out_type self.out_kwargs = out_kwargs self.args = tuple(processed_args) self.func = func self.dtype = kwargs.pop("dtype", None) self.kwargs = kwargs self.cache = {} self._dense_result = False self._check_broadcast() self._get_fill_value() def get_result(self): from ._coo import COO if self.args is None: return NotImplemented if self._dense_result: args = [a.todense() if isinstance(a, COO) else a for a in self.args] return self.func(*args, **self.kwargs) if any(s == 0 for s in self.shape): data = np.empty((0,), dtype=self.fill_value.dtype) coords = np.empty((0, len(self.shape)), dtype=np.intp) return COO( coords, data, shape=self.shape, has_duplicates=False, fill_value=self.fill_value, ) data_list = [] coords_list = [] for mask in itertools.product(*[[True, False] if isinstance(arg, COO) else [None] for arg in self.args]): if not any(mask): continue r = self._get_func_coords_data(mask) if r is not None: coords_list.append(r[0]) data_list.append(r[1]) # Concatenate matches and mismatches data = np.concatenate(data_list) if len(data_list) else np.empty((0,), dtype=self.fill_value.dtype) coords = ( np.concatenate(coords_list, axis=1) if len(coords_list) else np.empty((0, len(self.shape)), dtype=np.intp) ) return COO( coords, data, shape=self.shape, has_duplicates=False, fill_value=self.fill_value, ).asformat(self.out_type, **self.out_kwargs) def _get_fill_value(self): """ A function that finds and returns the fill-value. Raises ------ ValueError If the fill-value is inconsistent. """ from ._coo import COO def get_zero_arg(x): if isinstance(x, COO): return np.atleast_1d(x.fill_value) if isinstance(x, np.generic | np.ndarray): return np.atleast_1d(x) return x zero_args = tuple(get_zero_arg(a) for a in self.args) # Some elemwise functions require a dtype argument, some abhorr it. try: fill_value_array = self.func(*zero_args, dtype=self.dtype, **self.kwargs) except TypeError: fill_value_array = self.func(*zero_args, **self.kwargs) try: fill_value = fill_value_array[(0,) * fill_value_array.ndim] except IndexError: zero_args = tuple( arg.fill_value if isinstance(arg, COO) else _zero_of_dtype(arg.dtype) for arg in self.args ) fill_value = self.func(*zero_args, **self.kwargs)[()] equivalent_fv = equivalent(fill_value, fill_value_array, loose=True).all() if not equivalent_fv and self.shape != self.ndarray_shape: raise ValueError( "Performing a mixed sparse-dense operation that would result in a dense array. " "Please make sure that func(sparse_fill_values, ndarrays) is a constant array." ) if not equivalent_fv: self._dense_result = True # Store dtype separately if needed. if self.dtype is not None: fill_value = fill_value.astype(self.dtype) self.fill_value = fill_value self.dtype = self.fill_value.dtype def _check_broadcast(self): """ Checks if adding the ndarrays changes the broadcast shape. Raises ------ ValueError If the check fails. """ from ._coo import COO full_shape = _get_nary_broadcast_shape(*tuple(np.shape(arg) for arg in self.args)) non_ndarray_shape = _get_nary_broadcast_shape(*tuple(arg.shape for arg in self.args if isinstance(arg, COO))) ndarray_shape = _get_nary_broadcast_shape(*tuple(arg.shape for arg in self.args if isinstance(arg, np.ndarray))) self.shape = full_shape self.ndarray_shape = ndarray_shape self.non_ndarray_shape = non_ndarray_shape def _get_func_coords_data(self, mask): """ Gets the coords/data for a certain mask Parameters ---------- mask : tuple[Union[bool, NoneType]] The mask determining whether to match or unmatch. Returns ------- None or tuple The coords/data tuple for the given mask. """ from ._coo import COO matched_args = [arg for arg, m in zip(self.args, mask, strict=True) if m is not None and m] unmatched_args = [arg for arg, m in zip(self.args, mask, strict=True) if m is not None and not m] ndarray_args = [arg for arg, m in zip(self.args, mask, strict=True) if m is None] matched_broadcast_shape = _get_nary_broadcast_shape( *tuple(np.shape(arg) for arg in itertools.chain(matched_args, ndarray_args)) ) matched_arrays = self._match_coo(*matched_args, cache=self.cache, broadcast_shape=matched_broadcast_shape) func_args = [] m_arg = 0 for arg, m in zip(self.args, mask, strict=True): if m is None: func_args.append(np.broadcast_to(arg, matched_broadcast_shape)[tuple(matched_arrays[0].coords)]) continue if m: func_args.append(matched_arrays[m_arg].data) m_arg += 1 else: func_args.append(arg.fill_value) # Try our best to preserve the output dtype. try: func_data = self.func(*func_args, dtype=self.dtype, **self.kwargs) except TypeError: try: func_args = np.broadcast_arrays(*func_args) out = np.empty(func_args[0].shape, dtype=self.dtype) func_data = self.func(*func_args, out=out, **self.kwargs) except TypeError: func_data = self.func(*func_args, **self.kwargs).astype(self.dtype) unmatched_mask = ~equivalent(func_data, self.fill_value) if not unmatched_mask.any(): return None func_coords = matched_arrays[0].coords[:, unmatched_mask] func_data = func_data[unmatched_mask] if matched_arrays[0].shape != self.shape: params = _get_broadcast_parameters(matched_arrays[0].shape, self.shape) func_coords, func_data = _get_expanded_coords_data(func_coords, func_data, params, self.shape) if all(m is None or m for m in mask): return func_coords, func_data # Not really sorted but we need the sortedness. func_array = COO(func_coords, func_data, self.shape, has_duplicates=False, sorted=True) unmatched_mask = np.ones(func_array.nnz, dtype=np.bool_) for arg in unmatched_args: matched_idx = self._match_coo(func_array, arg, return_midx=True)[0] unmatched_mask[matched_idx] = False coords = np.asarray(func_array.coords[:, unmatched_mask], order="C") data = np.asarray(func_array.data[unmatched_mask], order="C") return coords, data @staticmethod def _match_coo(*args, **kwargs): """ Matches the coordinates for any number of input :obj:`COO` arrays. Equivalent to "sparse" broadcasting for all arrays. Parameters ---------- *args : Tuple[COO] The input :obj:`COO` arrays. return_midx : bool Whether to return matched indices or matched arrays. Matching only supported for two arrays. ``False`` by default. cache : dict Cache of things already matched. No cache by default. Returns ------- matched_idx : List[ndarray] The indices of matched elements in the original arrays. Only returned if ``return_midx`` is ``True``. matched_arrays : List[COO] The expanded, matched :obj:`COO` objects. Only returned if ``return_midx`` is ``False``. """ from ._coo import COO from ._coo.common import linear_loc cache = kwargs.pop("cache", None) return_midx = kwargs.pop("return_midx", False) broadcast_shape = kwargs.pop("broadcast_shape", None) if kwargs: raise ValueError(f"Unknown kwargs: {kwargs.keys()}") if return_midx and (len(args) != 2 or cache is not None): raise NotImplementedError("Matching indices only supported for two args, and no cache.") matched_arrays = [args[0]] cache_key = [id(args[0])] for arg2 in args[1:]: cache_key.append(id(arg2)) key = tuple(cache_key) if cache is not None and key in cache: matched_arrays = cache[key] continue cargs = [matched_arrays[0], arg2] current_shape = _get_broadcast_shape(matched_arrays[0].shape, arg2.shape) params = [_get_broadcast_parameters(arg.shape, current_shape) for arg in cargs] reduced_params = [all(p) for p in zip(*params, strict=True)] reduced_shape = _get_reduced_shape(arg2.shape, _rev_idx(reduced_params, arg2.ndim)) reduced_coords = [_get_reduced_coords(arg.coords, _rev_idx(reduced_params, arg.ndim)) for arg in cargs] linear = [linear_loc(rc, reduced_shape) for rc in reduced_coords] sorted_idx = [np.argsort(idx) for idx in linear] linear = [idx[s] for idx, s in zip(linear, sorted_idx, strict=True)] matched_idx = _match_arrays(*linear) if return_midx: return [sidx[midx] for sidx, midx in zip(sorted_idx, matched_idx, strict=True)] coords = [arg.coords[:, s] for arg, s in zip(cargs, sorted_idx, strict=True)] mcoords = [c[:, idx] for c, idx in zip(coords, matched_idx, strict=True)] mcoords = _get_matching_coords(mcoords, params) mdata = [arg.data[sorted_idx[0]][matched_idx[0]] for arg in matched_arrays] mdata.append(arg2.data[sorted_idx[1]][matched_idx[1]]) # The coords aren't truly sorted, but we don't need them, so it's # best to avoid the extra cost. matched_arrays = [COO(mcoords, md, shape=current_shape, sorted=True, has_duplicates=False) for md in mdata] if cache is not None: cache[key] = matched_arrays if broadcast_shape is not None and matched_arrays[0].shape != broadcast_shape: params = _get_broadcast_parameters(matched_arrays[0].shape, broadcast_shape) coords, idx = _get_expanded_coords_data( matched_arrays[0].coords, np.arange(matched_arrays[0].nnz), params, broadcast_shape, ) matched_arrays = [ COO( coords, arr.data[idx], shape=broadcast_shape, sorted=True, has_duplicates=False, ) for arr in matched_arrays ] return matched_arrays def _rev_idx(arg, idx): if idx == 0: return arg[len(arg) :] return arg[-idx:] sparse-0.18.0/sparse/numba_backend/_utils.py000066400000000000000000000463111514474157100210320ustar00rootroot00000000000000import functools import warnings from collections.abc import Iterable from numbers import Integral import numba import numpy as np def assert_eq(x, y, check_nnz=True, compare_dtype=True, **kwargs): from ._coo import COO assert x.shape == y.shape if compare_dtype: assert x.dtype == y.dtype check_equal = ( np.array_equal if (np.issubdtype(x.dtype, np.integer) and np.issubdtype(y.dtype, np.integer)) or (np.issubdtype(x.dtype, np.flexible) and np.issubdtype(y.dtype, np.flexible)) else functools.partial(np.allclose, equal_nan=True) ) if isinstance(x, COO): assert is_canonical(x) if isinstance(y, COO): assert is_canonical(y) if isinstance(x, COO) and isinstance(y, COO) and check_nnz: assert np.array_equal(x.coords, y.coords) assert check_equal(x.data, y.data, **kwargs) assert x.fill_value == y.fill_value or (np.isnan(x.fill_value) and np.isnan(y.fill_value)) return if hasattr(x, "todense"): xx = x.todense() if check_nnz: assert_nnz(x, xx) else: xx = x if hasattr(y, "todense"): yy = y.todense() if check_nnz: assert_nnz(y, yy) else: yy = y assert check_equal(xx, yy, **kwargs) def assert_gcxs_slicing(s, x): """ Util function to test slicing of GCXS matrices after product multiplication. For simplicity, it tests only tensors with number of dimension = 3. Parameters ---------- s: sparse product matrix x: dense product matrix """ rng = np.random.default_rng() row = rng.integers(s.shape[s.ndim - 2]) assert np.allclose(s[0][row].data, [num for num in x[0][row] if num != 0]) # regression test col = s.shape[s.ndim - 1] for i in range(len(s.indices) // col): j = col * i k = col * (1 + i) s.data[j:k] = s.data[j:k][::-1] s.indices[j:k] = s.indices[j:k][::-1] assert np.array_equal(s[0][row].data, np.array([])) def assert_nnz(s, x): fill_value = s.fill_value if hasattr(s, "fill_value") else _zero_of_dtype(s.dtype) assert np.sum(~equivalent(x, fill_value)) == s.nnz def is_canonical(x): return not x.shape or ((np.diff(x.linear_loc()) > 0).all() and not equivalent(x.data, x.fill_value).any()) def _zero_of_dtype(dtype): """ Creates a ()-shaped 0-dimensional zero array of a given dtype. Parameters ---------- dtype : numpy.dtype The dtype for the array. Returns ------- np.ndarray The zero array. """ return np.zeros((), dtype=dtype)[()] @numba.jit(nopython=True, nogil=True) def algD(n, N, random_state): """ Random Sampling without Replacement Alg D proposed by J.S. Vitter in Faster Methods for Random Sampling Parameters: n = sample size (nnz) N = size of system (elements) random_state = seed for random number generation """ n = np.intp(n + 1) N = np.intp(N) qu1 = N - n + 1 Vprime = np.exp(np.log(random_state.random()) / n) i = 0 arr = np.zeros(n - 1, dtype=np.intp) arr[-1] = -1 while n > 1: nmin1inv = 1 / (n - 1) while True: while True: X = N * (1 - Vprime) S = np.intp(X) if qu1 > S: break Vprime = np.exp(np.log(random_state.random()) / n) y1 = np.exp(np.log(random_state.random() * N / qu1) * nmin1inv) Vprime = y1 * (1 - X / N) * (qu1 / (qu1 - S)) if Vprime <= 1: break y2 = 1 top = N - 1 if n - 1 > S: bottom = N - n limit = N - S else: bottom = N - S - 1 limit = qu1 t = N - 1 while t >= limit: y2 *= top / bottom top -= 1 bottom -= 1 t -= 1 if y1 * np.exp(np.log(y2) / nmin1inv) <= N / (N - X): Vprime = np.exp(np.log(random_state.random()) * nmin1inv) break Vprime = np.exp(np.log(random_state.random()) / n) arr[i] = arr[i - 1] + S + 1 i += 1 N = N - S - 1 n -= 1 qu1 = qu1 - S return arr @numba.jit(nopython=True, nogil=True) def algA(n, N, random_state): """ Random Sampling without Replacement Alg A proposed by J.S. Vitter in Faster Methods for Random Sampling Parameters: n = sample size (nnz) N = size of system (elements) random_state = seed for random number generation """ n = np.intp(n) N = np.intp(N) arr = np.zeros(n, dtype=np.intp) arr[-1] = -1 i = 0 top = N - n while n >= 2: V = random_state.random() S = 0 quot = top / N while quot > V: S += 1 top -= 1 N -= 1 quot *= top / N arr[i] = arr[i - 1] + S + 1 i += 1 N -= 1 n -= 1 S = np.intp(N * random_state.random()) arr[i] = arr[i - 1] + S + 1 i += 1 return arr @numba.jit(nopython=True, nogil=True) def reverse(inv, N): """ If density of random matrix is greater than .5, it is faster to sample states not included Parameters: arr = np.array(np.intp) of indices to be excluded from sample N = size of the system (elements) """ N = np.intp(N) a = np.zeros(np.intp(N - len(inv)), dtype=np.intp) j = 0 k = 0 for i in range(N): if j == len(inv): a[k:] = np.arange(i, N) break if i == inv[j]: j += 1 else: a[k] = i k += 1 return a default_rng = np.random.default_rng() def random( shape, density=None, nnz=None, random_state=None, data_rvs=None, format="coo", fill_value=None, idx_dtype=None, **kwargs, ): """Generate a random sparse multidimensional array Parameters ---------- shape : Tuple[int] Shape of the array density : float, optional Density of the generated array; default is 0.01. Mutually exclusive with `nnz`. nnz : int, optional Number of nonzero elements in the generated array. Mutually exclusive with `density`. random_state : Union[`numpy.random.Generator, int`], optional Random number generator or random seed. If not given, the singleton numpy.random will be used. This random state will be used for sampling the sparsity structure, but not necessarily for sampling the values of the structurally nonzero entries of the matrix. data_rvs : Callable Data generation callback. Must accept one single parameter: number of `nnz` elements, and return one single NumPy array of exactly that length. format : str The format to return the output array in. fill_value : scalar The fill value of the output array. Returns ------- SparseArray The generated random matrix. See Also -------- - [`scipy.sparse.rand`][] : Equivalent Scipy function. - [`numpy.random.rand`][] : Similar Numpy function. Examples -------- >>> from scipy import stats >>> rng = np.random.default_rng(42) >>> rvs = lambda x: stats.poisson(25, loc=10).rvs(x, random_state=rng) >>> s = sparse.random((2, 3, 4), density=0.25, random_state=rng, data_rvs=rvs) >>> s.todense() array([[[39, 0, 0, 0], [28, 33, 0, 37], [ 0, 0, 0, 0]], [[ 0, 0, 0, 0], [ 0, 0, 34, 0], [ 0, 0, 0, 36]]]) """ # Copied, in large part, from scipy.sparse.random # See https://github.com/scipy/scipy/blob/main/LICENSE.txt from ._coo import COO if density is not None and nnz is not None: raise ValueError("'density' and 'nnz' are mutually exclusive") if density is None: density = 0.01 if not (0 <= density <= 1): raise ValueError(f"density {density} is not in the unit interval") elements = np.prod(shape, dtype=np.intp) if nnz is None: nnz = int(elements * density) if not (0 <= nnz <= elements): raise ValueError(f"cannot generate {nnz} nonzero elements for an array with {elements} total elements") if random_state is None: random_state = default_rng elif isinstance(random_state, Integral): random_state = np.random.default_rng(random_state) if data_rvs is None: data_rvs = random_state.random if nnz == elements or density >= 1: ind = np.arange(elements) elif nnz < 2: ind = random_state.choice(elements, nnz) # Faster to find non-sampled indices and remove them for dens > .5 elif elements - nnz < 2: ind = reverse(random_state.choice(elements, elements - nnz), elements) elif nnz > elements / 2: nnztemp = elements - nnz # Using algorithm A for dens > .1 if elements > 10 * nnztemp: ind = reverse( algD(nnztemp, elements, random_state), elements, ) else: ind = reverse( algA(nnztemp, elements, random_state), elements, ) else: ind = algD(nnz, elements, random_state) if elements > 10 * nnz else algA(nnz, elements, random_state) data = data_rvs(nnz) ar = COO( ind[None, :], data, shape=elements, fill_value=fill_value, ).reshape(shape) if idx_dtype: if can_store(idx_dtype, max(shape)): ar.coords = ar.coords.astype(idx_dtype) else: raise ValueError(f"cannot cast array with shape {shape} to dtype {idx_dtype}.") return ar.asformat(format, **kwargs) def isscalar(x): from ._sparse_array import SparseArray return not isinstance(x, SparseArray) and np.isscalar(x) def random_value_array(value, fraction): def replace_values(n): i = int(n * fraction) ar = np.empty((n,), dtype=np.float64) ar[:i] = value ar[i:] = default_rng.random(n - i) return ar return replace_values def normalize_axis(axis, ndim): """ Normalize negative axis indices to their positive counterpart for a given number of dimensions. Parameters ---------- axis : Union[int, Iterable[int], None] The axis indices. ndim : int Number of dimensions to normalize axis indices against. Returns ------- axis The normalized axis indices. """ if axis is None: return None if isinstance(axis, Integral): axis = int(axis) if axis < 0: axis += ndim if axis >= ndim or axis < 0: raise ValueError(f"Invalid axis index {axis} for ndim={ndim}") return axis if isinstance(axis, Iterable): if not all(isinstance(a, Integral) for a in axis): raise ValueError(f"axis {axis} not understood") return tuple(normalize_axis(a, ndim) for a in axis) raise ValueError(f"axis {axis} not understood") def equivalent(x, y, /, loose=False): """ Checks the equivalence of two scalars or arrays with broadcasting. Assumes a consistent dtype. Parameters ---------- x : scalar or numpy.ndarray y : scalar or numpy.ndarray Returns ------- equivalent : scalar or numpy.ndarray The element-wise comparison of where two arrays are equivalent. Examples -------- >>> equivalent(1, 1) np.True_ >>> equivalent(np.nan, np.nan + 1) np.True_ >>> equivalent(1, 2) np.False_ >>> equivalent(np.inf, np.inf) np.True_ >>> equivalent(np.float64(0.0), np.float64(-0.0)) np.False_ """ x = np.asarray(x) y = np.asarray(y) # Can't contain NaNs dt = np.result_type(x.dtype, y.dtype) if not any(np.issubdtype(dt, t) for t in [np.floating, np.complexfloating]): return x == y if loose: if np.issubdtype(dt, np.complexfloating): return equivalent(x.real, y.real, loose=True) & equivalent(x.imag, y.imag, loose=True) # TODO: Rec array handling return (x == y) | ((x != x) & (y != y)) if x.size == 0 or y.size == 0: shape = np.broadcast_shapes(x.shape, y.shape) return np.empty(shape, dtype=np.bool_) x, y = np.broadcast_arrays(x[..., None], y[..., None]) return (x.astype(dt).view(np.uint8) == y.astype(dt).view(np.uint8)).all(axis=-1) # copied from zarr # See https://github.com/zarr-developers/zarr-python/blob/main/zarr/util.py def human_readable_size(size): if size < 2**10: return str(size) if size < 2**20: return f"{size / 2**10:.1f}K" if size < 2**30: return f"{size / 2**20:.1f}M" if size < 2**40: return f"{size / 2**30:.1f}G" if size < 2**50: return f"{size / 2**40:.1f}T" return f"{size / 2**50:.1f}P" def html_table(arr): table = [""] headings = ["Format", "Data Type", "Shape", "nnz", "Density", "Read-only"] info = [ type(arr).__name__.lower(), str(arr.dtype), str(arr.shape), str(arr.nnz), str(arr.density), ] # read-only info.append(str(not hasattr(arr, "__setitem__"))) if hasattr(arr, "nbytes"): headings.append("Size") info.append(human_readable_size(arr.nbytes)) headings.append("Storage ratio") with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RuntimeWarning) ratio = float(np.float64(arr.nbytes) / np.float64(arr.size * arr.dtype.itemsize)) info.append(f"{ratio:.2f}") # compressed_axes if type(arr).__name__ == "GCXS": headings.append("Compressed Axes") info.append(str(arr.compressed_axes)) for h, i in zip(headings, info, strict=True): table.append(f'') table.append("
{h}{i}
") return "".join(table) def check_compressed_axes(ndim, compressed_axes): """ Checks if the given compressed_axes are compatible with the shape of the array. Parameters ---------- ndim : int compressed_axes : Iterable Raises ------ ValueError If the compressed_axes are incompatible with the number of dimensions """ if compressed_axes is None: return if isinstance(ndim, Iterable): ndim = len(ndim) if not isinstance(compressed_axes, Iterable): raise ValueError("compressed_axes must be an iterable") if len(compressed_axes) == ndim: raise ValueError("cannot compress all axes") if not np.array_equal(list(set(compressed_axes)), compressed_axes): raise ValueError("axes must be sorted without repeats") if not all(isinstance(a, Integral) for a in compressed_axes): raise ValueError("axes must be represented with integers") if min(compressed_axes) < 0 or max(compressed_axes) >= ndim: raise ValueError("axis out of range") def check_fill_value(x, /, *, accept_fv=None) -> None: """Raises on incorrect fill-values. Parameters ---------- x : SparseArray The array to check accept_fv : scalar or list of scalar, optional The list of accepted fill-values. The default accepts only zero. Raises ------ ValueError If the fill-value doesn't match. """ if accept_fv is None: accept_fv = [0] if not isinstance(accept_fv, Iterable): accept_fv = [accept_fv] if not any(equivalent(fv, x.fill_value, loose=True) for fv in accept_fv): raise ValueError(f"{x.fill_value=} but should be in {accept_fv}.") def check_zero_fill_value(*args, loose=True): """ Checks if all the arguments have zero fill-values. Parameters ---------- *args : Iterable[SparseArray] Raises ------ ValueError If all arguments don't have zero fill-values. Examples -------- >>> import sparse >>> s1 = sparse.random((10,), density=0.5) >>> s2 = sparse.random((10,), density=0.5, fill_value=0.5) >>> check_zero_fill_value(s1) >>> check_zero_fill_value(s2) Traceback (most recent call last): ... ValueError: This operation requires zero fill values, but argument 0 had a fill value of 0.5. >>> check_zero_fill_value(s1, s2) Traceback (most recent call last): ... ValueError: This operation requires zero fill values, but argument 1 had a fill value of 0.5. """ for i, arg in enumerate(args): if arg.size == 0: continue if hasattr(arg, "fill_value") and not equivalent(arg.fill_value, _zero_of_dtype(arg.dtype), loose=loose): raise ValueError( f"This operation requires zero fill values, but argument {i:d} had a fill value of {arg.fill_value!s}." ) def check_consistent_fill_value(arrays): """ Checks if all the arguments have consistent fill-values. Parameters ---------- args : Iterable[SparseArray] Raises ------ ValueError If all elements of :code:`arrays` don't have the same fill-value. Examples -------- >>> import sparse >>> s1 = sparse.random((10,), density=0.5, fill_value=0.1) >>> s2 = sparse.random((10,), density=0.5, fill_value=0.5) >>> check_consistent_fill_value([s1, s1]) >>> check_consistent_fill_value([s1, s2]) # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): ... ValueError: This operation requires consistent fill-values, but argument 1 had a fill value of 0.5,\ which is different from a fill_value of 0.1 in the first argument. """ arrays = list(arrays) from ._sparse_array import SparseArray if not all(isinstance(s, SparseArray) for s in arrays): raise ValueError("All arrays must be instances of SparseArray.") if len(arrays) == 0: raise ValueError("At least one array required.") fv = arrays[0].fill_value for i, arg in enumerate(arrays): if not equivalent(fv, arg.fill_value): raise ValueError( "This operation requires consistent fill-values, " f"but argument {i:d} had a fill value of {arg.fill_value!s}, which " f"is different from a fill_value of {fv!s} in the first " "argument." ) def get_out_dtype(arr, scalar): out_type = arr.dtype if not can_store(out_type, scalar): out_type = np.min_scalar_type(scalar) return out_type def can_store(dtype, scalar): try: with warnings.catch_warnings(): warnings.simplefilter("ignore") warnings.filterwarnings("error", "out-of-bound", DeprecationWarning) return np.array(scalar, dtype=dtype) == np.array(scalar) except (ValueError, OverflowError): return False def is_unsigned_dtype(dtype): return np.issubdtype(dtype, np.integer) and np.iinfo(dtype).min == 0 def convert_format(format): from ._sparse_array import SparseArray if isinstance(format, type): if not issubclass(format, SparseArray): raise ValueError(f"Invalid format: {format}") return format.__name__.lower() if isinstance(format, str): return format raise ValueError(f"Invalid format: {format}") sparse-0.18.0/sparse/numba_backend/tests/000077500000000000000000000000001514474157100203165ustar00rootroot00000000000000sparse-0.18.0/sparse/numba_backend/tests/__init__.py000066400000000000000000000000001514474157100224150ustar00rootroot00000000000000sparse-0.18.0/sparse/numba_backend/tests/conftest.py000066400000000000000000000002141514474157100225120ustar00rootroot00000000000000import pytest @pytest.fixture(scope="session") def rng(): from sparse.numba_backend._utils import default_rng return default_rng sparse-0.18.0/sparse/numba_backend/tests/test_array_function.py000066400000000000000000000074021514474157100247550ustar00rootroot00000000000000import sparse from sparse.numba_backend import SparseArray from sparse.numba_backend._settings import NEP18_ENABLED from sparse.numba_backend._utils import assert_eq import pytest import numpy as np import scipy if not NEP18_ENABLED: pytest.skip("NEP18 is not enabled", allow_module_level=True) @pytest.mark.parametrize( "func", [ np.mean, np.std, np.var, np.sum, lambda x: np.sum(x, axis=0), lambda x: np.transpose(x), ], ) def test_unary(func): y = sparse.random((50, 50), density=0.25) x = y.todense() xx = func(x) yy = func(y) assert_eq(xx, yy) @pytest.mark.parametrize("arg_order", [(0, 1), (1, 0), (1, 1)]) @pytest.mark.parametrize("func", [np.dot, np.result_type, np.tensordot, np.matmul]) def test_binary(func, arg_order): y = sparse.random((50, 50), density=0.25) x = y.todense() xx = func(x, x) args = [(x, y)[i] for i in arg_order] yy = func(*args) if isinstance(xx, np.ndarray): assert_eq(xx, yy) else: # result_type returns a dtype assert xx == yy def test_stack(): """stack(), by design, does not allow for mixed type inputs""" y = sparse.random((50, 50), density=0.25) x = y.todense() xx = np.stack([x, x]) yy = np.stack([y, y]) assert_eq(xx, yy) @pytest.mark.parametrize( "arg_order", [(0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)], ) @pytest.mark.parametrize("func", [lambda a, b, c: np.where(a.astype(bool), b, c)]) def test_ternary(func, arg_order): y = sparse.random((50, 50), density=0.25) x = y.todense() xx = func(x, x, x) args = [(x, y)[i] for i in arg_order] yy = func(*args) assert_eq(xx, yy) @pytest.mark.parametrize("func", [np.shape, np.size, np.ndim]) def test_property(func): y = sparse.random((50, 50), density=0.25) x = y.todense() xx = func(x) yy = func(y) assert xx == yy def test_broadcast_to_scalar(): s = sparse.COO.from_numpy([0, 0, 1, 2]) actual = np.broadcast_to(np.zeros_like(s, shape=()), (3,)) expected = np.broadcast_to(np.zeros_like(s.todense(), shape=()), (3,)) assert isinstance(actual, sparse.COO) assert_eq(actual, expected) def test_zeros_like_order(): s = sparse.COO.from_numpy([0, 0, 1, 2]) actual = np.zeros_like(s, order="C") expected = np.zeros_like(s.todense(), order="C") assert isinstance(actual, sparse.COO) assert_eq(actual, expected) @pytest.mark.parametrize("format", ["dok", "gcxs", "coo"]) def test_format(format): s = sparse.random((5, 5), density=0.2, format=format) assert s.format == format class TestAsarray: np_eye = np.eye(5) @pytest.mark.parametrize( "input", [ np_eye, scipy.sparse.csr_array(np_eye), scipy.sparse.csc_array(np_eye), 4, np.array(5), np.arange(12).reshape((2, 3, 2)), sparse.COO.from_numpy(np_eye), sparse.GCXS.from_numpy(np_eye), sparse.DOK.from_numpy(np_eye), ], ) @pytest.mark.parametrize("dtype", [np.int64, np.float64, np.complex128]) @pytest.mark.parametrize("format", ["dok", "gcxs", "coo"]) def test_asarray(self, input, dtype, format): if format == "dok" and (np.isscalar(input) or input.ndim == 0): # scalars and 0-D arrays aren't supported in DOK format return s = sparse.asarray(input, dtype=dtype, format=format) actual = s.todense() if hasattr(s, "todense") else s expected = input.todense() if hasattr(input, "todense") else np.asarray(input) np.testing.assert_equal(actual, expected) if isinstance(input, SparseArray): assert sparse.asarray(input).__class__ is input.__class__ sparse-0.18.0/sparse/numba_backend/tests/test_compressed.py000066400000000000000000000324661514474157100241060ustar00rootroot00000000000000import sparse from sparse.numba_backend._compressed import GCXS from sparse.numba_backend._utils import assert_eq, equivalent import pytest import numpy as np @pytest.fixture(scope="module", params=["f8", "f4", "i8", "i4"]) def random_sparse(request, rng): dtype = request.param if np.issubdtype(dtype, np.integer): def data_rvs(n): return rng.integers(-1000, 1000, n) else: data_rvs = None return sparse.random((20, 30, 40), density=0.25, format="gcxs", data_rvs=data_rvs, random_state=rng).astype(dtype) @pytest.fixture(scope="module", params=["f8", "f4", "i8", "i4"]) def random_sparse_small(request, rng): dtype = request.param if np.issubdtype(dtype, np.integer): def data_rvs(n): return rng.integers(-10, 10, n) else: data_rvs = None return sparse.random((20, 30, 40), density=0.25, format="gcxs", data_rvs=data_rvs, random_state=rng).astype(dtype) @pytest.mark.parametrize( "reduction, kwargs", [ ("sum", {}), ("sum", {"dtype": np.float32}), ("mean", {}), ("mean", {"dtype": np.float32}), ("prod", {}), ("max", {}), ("min", {}), ("std", {}), ("var", {}), ], ) @pytest.mark.parametrize("axis", [None, 0, 1, 2, (0, 2), -3, (1, -1)]) @pytest.mark.parametrize("keepdims", [True, False]) def test_reductions(reduction, random_sparse, axis, keepdims, kwargs): x = random_sparse y = x.todense() xx = getattr(x, reduction)(axis=axis, keepdims=keepdims, **kwargs) yy = getattr(y, reduction)(axis=axis, keepdims=keepdims, **kwargs) assert_eq(xx, yy) @pytest.mark.xfail(reason=("Setting output dtype=float16 produces results inconsistent with numpy")) @pytest.mark.filterwarnings("ignore:overflow") @pytest.mark.parametrize( "reduction, kwargs", [("sum", {"dtype": np.float16}), ("mean", {"dtype": np.float16})], ) @pytest.mark.parametrize("axis", [None, 0, 1, 2, (0, 2)]) def test_reductions_float16(random_sparse, reduction, kwargs, axis): x = random_sparse y = x.todense() xx = getattr(x, reduction)(axis=axis, **kwargs) yy = getattr(y, reduction)(axis=axis, **kwargs) assert_eq(xx, yy, atol=1e-2) @pytest.mark.parametrize("reduction,kwargs", [("any", {}), ("all", {})]) @pytest.mark.parametrize("axis", [None, 0, 1, 2, (0, 2), -3, (1, -1)]) @pytest.mark.parametrize("keepdims", [True, False]) def test_reductions_bool(random_sparse, reduction, kwargs, axis, keepdims): y = np.zeros((2, 3, 4), dtype=bool) y[0] = True y[1, 1, 1] = True x = sparse.COO.from_numpy(y) xx = getattr(x, reduction)(axis=axis, keepdims=keepdims, **kwargs) yy = getattr(y, reduction)(axis=axis, keepdims=keepdims, **kwargs) assert_eq(xx, yy) @pytest.mark.parametrize( "reduction,kwargs", [ (np.max, {}), (np.sum, {}), (np.sum, {"dtype": np.float32}), (np.mean, {}), (np.mean, {"dtype": np.float32}), (np.prod, {}), (np.min, {}), ], ) @pytest.mark.parametrize("axis", [None, 0, 1, 2, (0, 2), -1, (0, -1)]) @pytest.mark.parametrize("keepdims", [True, False]) def test_ufunc_reductions(random_sparse, reduction, kwargs, axis, keepdims): x = random_sparse y = x.todense() xx = reduction(x, axis=axis, keepdims=keepdims, **kwargs) yy = reduction(y, axis=axis, keepdims=keepdims, **kwargs) assert_eq(xx, yy) # If not a scalar/1 element array, must be a sparse array if xx.size > 1: assert isinstance(xx, GCXS) @pytest.mark.parametrize( "reduction,kwargs", [ (np.max, {}), (np.sum, {"axis": 0}), (np.prod, {"keepdims": True}), (np.minimum.reduce, {"axis": 0}), ], ) @pytest.mark.parametrize("fill_value", [0, 1.0, -1, -2.2, 5.0]) def test_ufunc_reductions_kwargs(reduction, kwargs, fill_value): x = sparse.random((2, 3, 4), density=0.5, format="gcxs", fill_value=fill_value) y = x.todense() xx = reduction(x, **kwargs) yy = reduction(y, **kwargs) assert_eq(xx, yy) # If not a scalar/1 element array, must be a sparse array if xx.size > 1: assert isinstance(xx, GCXS) @pytest.mark.parametrize( "a,b", [ [(3, 4), (3, 4)], [(12,), (3, 4)], [(12,), (3, -1)], [(3, 4), (12,)], [(3, 4), (-1, 4)], [(3, 4), (3, -1)], [(2, 3, 4, 5), (8, 15)], [(2, 3, 4, 5), (24, 5)], [(2, 3, 4, 5), (20, 6)], [(), ()], ], ) def test_reshape(a, b): s = sparse.random(a, density=0.5, format="gcxs") x = s.todense() assert_eq(x.reshape(b), s.reshape(b)) def test_reshape_same(): s = sparse.random((3, 5), density=0.5, format="gcxs") assert s.reshape(s.shape) is s @pytest.mark.parametrize( "a,b", [ [(3, 4, 5), (2, 1, 0)], [(12,), None], [(9, 10), (1, 0)], [(4, 3, 5), (1, 0, 2)], [(5, 4, 3), (0, 2, 1)], [(3, 4, 5, 6), (0, 2, 1, 3)], ], ) def test_tranpose(a, b): s = sparse.random(a, density=0.5, format="gcxs") x = s.todense() assert_eq(x.transpose(b), s.transpose(b)) @pytest.mark.parametrize("fill_value_in", [0, np.inf, np.nan, 5, None]) @pytest.mark.parametrize("fill_value_out", [0, np.inf, np.nan, 5, None]) @pytest.mark.parametrize("format", [sparse.COO, sparse._compressed.CSR]) def test_to_scipy_sparse(fill_value_in, fill_value_out, format): s = sparse.random((3, 5), density=0.5, format=format, fill_value=fill_value_in) if not ((fill_value_in in {0, None} and fill_value_out in {0, None}) or equivalent(fill_value_in, fill_value_out)): with pytest.raises(ValueError, match=r"fill_value=.* but should be in .*\."): s.to_scipy_sparse(accept_fv=fill_value_out) return sps_matrix = s.to_scipy_sparse(accept_fv=fill_value_in) s2 = format.from_scipy_sparse(sps_matrix, fill_value=fill_value_out) assert_eq(s, s2) def test_tocoo(): coo = sparse.random((5, 6), density=0.5) b = GCXS.from_coo(coo) assert_eq(b.tocoo(), coo) @pytest.mark.parametrize("complex", [True, False]) def test_complex_methods(complex): x = np.array([1 + 2j, 2 - 1j, 0, 1, 0]) if complex else np.array([1, 2, 0, 0, 0]) s = GCXS.from_numpy(x) assert_eq(s.imag, x.imag) assert_eq(s.real, x.real) assert_eq(s.conj(), x.conj()) @pytest.mark.parametrize( "index", [ # Integer 0, 1, -1, (1, 1, 1), # Pure slices (slice(0, 2),), (slice(None, 2), slice(None, 2)), (slice(1, None), slice(1, None)), (slice(None, None),), (slice(None, None, -1),), (slice(None, 2, -1), slice(None, 2, -1)), (slice(1, None, 2), slice(1, None, 2)), (slice(None, None, 2),), (slice(None, 2, -1), slice(None, 2, -2)), (slice(1, None, 2), slice(1, None, 1)), (slice(None, None, -2),), # Combinations (0, slice(0, 2)), (slice(0, 1), 0), (None, slice(1, 3), 0), (slice(0, 3), None, 0), (slice(1, 2), slice(2, 4)), (slice(1, 2), slice(None, None)), (slice(1, 2), slice(None, None), 2), (slice(1, 2, 2), slice(None, None), 2), (slice(1, 2, None), slice(None, None, 2), 2), (slice(1, 2, -2), slice(None, None), -2), (slice(1, 2, None), slice(None, None, -2), 2), (slice(1, 2, -1), slice(None, None), -1), (slice(1, 2, None), slice(None, None, -1), 2), (slice(2, 0, -1), slice(None, None), -1), (slice(-2, None, None),), (slice(-1, None, None), slice(-2, None, None)), # With ellipsis (Ellipsis, slice(1, 3)), (1, Ellipsis, slice(1, 3)), (slice(0, 1), Ellipsis), (Ellipsis, None), (None, Ellipsis), (1, Ellipsis), (1, Ellipsis, None), (1, 1, 1, Ellipsis), (Ellipsis, 1, None), # Pathological - Slices larger than array (slice(None, 1000)), (slice(None), slice(None, 1000)), (slice(None), slice(1000, -1000, -1)), (slice(None), slice(1000, -1000, -50)), # Pathological - Wrong ordering of start/stop (slice(5, 0),), (slice(0, 5, -1),), ], ) @pytest.mark.parametrize("compressed_axes", [(0,), (1,), (2,), (0, 1), (0, 2), (1, 2)]) def test_slicing(index, compressed_axes): s = sparse.random((2, 3, 4), density=0.5, format="gcxs", compressed_axes=compressed_axes) x = s.todense() assert_eq(x[index], s[index]) @pytest.mark.parametrize( "index", [ ([1, 0], 0), (1, [0, 2]), (0, [1, 0], 0), (1, [2, 0], 0), ([True, False], slice(1, None), slice(-2, None)), (slice(1, None), slice(-2, None), [True, False, True, False]), ([1, 0],), (Ellipsis, [2, 1, 3]), (slice(None), [2, 1, 2]), (1, [2, 0, 1]), ], ) @pytest.mark.parametrize("compressed_axes", [(0,), (1,), (2,), (0, 1), (0, 2), (1, 2)]) def test_advanced_indexing(index, compressed_axes): s = sparse.random((2, 3, 4), density=0.5, format="gcxs", compressed_axes=compressed_axes) x = s.todense() assert_eq(x[index], s[index]) @pytest.mark.parametrize( "index", [ (Ellipsis, Ellipsis), (1, 1, 1, 1), (slice(None),) * 4, 5, -5, "foo", [True, False, False], 0.5, [0.5], {"potato": "kartoffel"}, ([[0, 1]],), ], ) def test_slicing_errors(index): s = sparse.random((2, 3, 4), density=0.5, format="gcxs") with pytest.raises(IndexError): s[index] def test_change_compressed_axes(): coo = sparse.random((3, 4, 5), density=0.5) s = GCXS.from_coo(coo, compressed_axes=(0, 1)) b = GCXS.from_coo(coo, compressed_axes=(1, 2)) assert_eq(s, b) s.change_compressed_axes((1, 2)) assert_eq(s, b) def test_concatenate(): xx = sparse.random((2, 3, 4), density=0.5, format="gcxs") x = xx.todense() yy = sparse.random((5, 3, 4), density=0.5, format="gcxs") y = yy.todense() zz = sparse.random((4, 3, 4), density=0.5, format="gcxs") z = zz.todense() assert_eq(np.concatenate([x, y, z], axis=0), sparse.concatenate([xx, yy, zz], axis=0)) xx = sparse.random((5, 3, 1), density=0.5, format="gcxs") x = xx.todense() yy = sparse.random((5, 3, 3), density=0.5, format="gcxs") y = yy.todense() zz = sparse.random((5, 3, 2), density=0.5, format="gcxs") z = zz.todense() assert_eq(np.concatenate([x, y, z], axis=2), sparse.concatenate([xx, yy, zz], axis=2)) assert_eq(np.concatenate([x, y, z], axis=-1), sparse.concatenate([xx, yy, zz], axis=-1)) @pytest.mark.parametrize("axis", [0, 1]) @pytest.mark.parametrize("func", [sparse.stack, sparse.concatenate]) def test_concatenate_mixed(func, axis): s = sparse.random((10, 10), density=0.5, format="gcxs") d = s.todense() with pytest.raises(ValueError): func([d, s, s], axis=axis) def test_concatenate_noarrays(): with pytest.raises(ValueError): sparse.concatenate([]) @pytest.mark.parametrize("shape", [(5,), (2, 3, 4), (5, 2)]) @pytest.mark.parametrize("axis", [0, 1, -1]) def test_stack(shape, axis): xx = sparse.random(shape, density=0.5, format="gcxs") x = xx.todense() yy = sparse.random(shape, density=0.5, format="gcxs") y = yy.todense() zz = sparse.random(shape, density=0.5, format="gcxs") z = zz.todense() assert_eq(np.stack([x, y, z], axis=axis), sparse.stack([xx, yy, zz], axis=axis)) @pytest.mark.parametrize("in_shape", [(5, 5), 62, (3, 3, 3)]) def test_flatten(in_shape): s = sparse.random(in_shape, format="gcxs", density=0.5) x = s.todense() a = s.flatten() e = x.flatten() assert_eq(e, a) def test_gcxs_valerr(): a = np.arange(300) with pytest.raises(ValueError): GCXS.from_numpy(a, idx_dtype=np.int8) def test_upcast(): a = sparse.random((50, 50, 50), density=0.1, format="coo", idx_dtype=np.uint8) b = a.asformat("gcxs") assert b.indices.dtype == np.uint16 a = sparse.random((8, 7, 6), density=0.5, format="gcxs", idx_dtype=np.uint8) b = sparse.random((6, 6, 6), density=0.8, format="gcxs", idx_dtype=np.uint8) assert sparse.concatenate((a, a)).indptr.dtype == np.uint16 assert sparse.stack((b, b)).indptr.dtype == np.uint16 def test_from_coo(): a = sparse.random((5, 5, 5), density=0.1, format="coo") b = GCXS(a) assert_eq(a, b) def test_from_coo_valerr(): a = sparse.random((25, 25, 25), density=0.01, format="coo") with pytest.raises(ValueError): GCXS.from_coo(a, idx_dtype=np.int8) @pytest.mark.parametrize( "pad_width", [ 2, (2, 1), ((2), (1)), ((1, 2), (4, 5), (7, 8)), ], ) @pytest.mark.parametrize("constant_values", [0, 1, 150, np.nan]) def test_pad_valid(pad_width, constant_values): y = sparse.random((50, 50, 3), density=0.15, fill_value=constant_values, format="gcxs") x = y.todense() xx = np.pad(x, pad_width=pad_width, constant_values=constant_values) yy = np.pad(y, pad_width=pad_width, constant_values=constant_values) assert_eq(xx, yy) @pytest.mark.parametrize( "pad_width", [ ((2, 1), (5, 7)), ], ) @pytest.mark.parametrize("constant_values", [150, 2, (1, 2)]) def test_pad_invalid(pad_width, constant_values, fill_value=0): y = sparse.random((50, 50, 3), density=0.15, format="gcxs") with pytest.raises(ValueError): np.pad(y, pad_width, constant_values=constant_values) sparse-0.18.0/sparse/numba_backend/tests/test_compressed_2d.py000066400000000000000000000071401514474157100244620ustar00rootroot00000000000000import sparse from sparse import COO from sparse.numba_backend._compressed.compressed import CSC, CSR, GCXS from sparse.numba_backend._utils import assert_eq import pytest import numpy as np import scipy.sparse import scipy.stats @pytest.fixture(scope="module", params=[CSR, CSC]) def cls(request): return request.param @pytest.fixture(scope="module", params=["f8", "f4", "i8", "i4"]) def dtype(request): return request.param @pytest.fixture(scope="module") def random_sparse(cls, dtype, rng): if np.issubdtype(dtype, np.integer): def data_rvs(n): return rng.integers(-1000, 1000, n) else: data_rvs = None return cls(sparse.random((20, 30), density=0.25, data_rvs=data_rvs).astype(dtype)) @pytest.fixture(scope="module") def random_sparse_small(cls, dtype, rng): if np.issubdtype(dtype, np.integer): def data_rvs(n): return rng.integers(-10, 10, n) else: data_rvs = None return cls(sparse.random((20, 20), density=0.25, data_rvs=data_rvs).astype(dtype)) def test_repr(random_sparse): cls = type(random_sparse).__name__ str_repr = repr(random_sparse) assert cls in str_repr def test_bad_constructor_input(cls): with pytest.raises(ValueError, match=r".*shape.*"): cls(arg="hello world") @pytest.mark.parametrize("n", [0, 1, 3]) def test_bad_nd_input(cls, n): a = np.ones(shape=tuple(5 for _ in range(n))) with pytest.raises(ValueError, match=f"{n}-d"): cls(a) @pytest.mark.parametrize("source_type", ["gcxs", "coo"]) def test_from_sparse(cls, source_type): gcxs = sparse.random((20, 30), density=0.25, format=source_type) result = cls(gcxs) assert_eq(result, gcxs) @pytest.mark.parametrize("scipy_type", ["coo", "csr", "csc", "lil"]) @pytest.mark.parametrize("CLS", [CSR, CSC, GCXS]) def test_from_scipy_sparse(scipy_type, CLS, dtype): orig = scipy.sparse.random_array((20, 30), density=0.2, format=scipy_type, dtype=dtype) ref = COO.from_scipy_sparse(orig) result = CLS.from_scipy_sparse(orig) assert_eq(ref, result) result_via_init = CLS(orig) assert_eq(ref, result_via_init) @pytest.mark.parametrize("cls_str", ["coo", "dok", "csr", "csc", "gcxs"]) def test_to_sparse(cls_str, random_sparse): result = random_sparse.asformat(cls_str) assert_eq(random_sparse, result) @pytest.mark.parametrize("copy", [True, False]) def test_transpose(random_sparse, copy): from operator import is_, is_not t = random_sparse.transpose(copy=copy) tt = t.transpose(copy=copy) # Check if a copy was made check = is_not if copy else is_ assert check(random_sparse.data, t.data) assert check(random_sparse.indices, t.indices) assert check(random_sparse.indptr, t.indptr) assert random_sparse.shape == t.shape[::-1] assert_eq(random_sparse, tt) assert type(random_sparse) is type(tt) assert_eq(random_sparse.transpose(axes=(0, 1)), random_sparse) assert_eq(random_sparse.transpose(axes=(1, 0)), t) with pytest.raises(ValueError, match="Invalid transpose axes"): random_sparse.transpose(axes=0) @pytest.mark.parametrize("format", ["csr", "csc"]) def test_mT_fill_value(format): fv = 1.0 arr = sparse.full((10, 20), fill_value=fv, format=format) assert_eq(arr.mT, sparse.full((20, 10), fill_value=fv)) def test_transpose_error(random_sparse): with pytest.raises(ValueError): random_sparse.transpose(axes=1) def test_matmul(random_sparse_small): arr = random_sparse_small.todense() actual = random_sparse_small @ random_sparse_small expected = arr @ arr assert_eq(actual, expected) sparse-0.18.0/sparse/numba_backend/tests/test_compressed_convert.py000066400000000000000000000051671514474157100256440ustar00rootroot00000000000000from sparse.numba_backend._compressed import convert from sparse.numba_backend._utils import assert_eq import pytest from numba.typed import List import numpy as np def make_inds(shape): return [np.arange(1, a - 1) for a in shape] def make_increments(shape): inds = make_inds(shape) shape_bins = convert.transform_shape(np.asarray(shape)) return List([inds[i] * shape_bins[i] for i in range(len(shape))]) @pytest.mark.parametrize( "shape, expected_subsample, subsample", [ [(5, 6, 7, 8, 9), np.array([3610, 6892, 10338]), 1000], [(13, 12, 12, 9, 7), np.array([9899, 34441, 60635, 86703]), 10000], [ (12, 15, 7, 14, 9), np.array([14248, 36806, 61382, 85956, 110532, 135106]), 10000, ], [(9, 9, 12, 7, 12), np.array([10177, 34369, 60577]), 10000], ], ) def test_convert_to_flat(shape, expected_subsample, subsample): inds = make_inds(shape) dtype = inds[0].dtype assert_eq( convert.convert_to_flat(inds, shape, dtype)[::subsample], expected_subsample.astype(dtype), ) @pytest.mark.parametrize( "shape, expected_subsample, subsample", [ [(5, 6, 7, 8, 9), np.array([3610, 6892, 10338]), 1000], [(13, 12, 12, 9, 7), np.array([9899, 34441, 60635, 86703]), 10000], [ (12, 15, 7, 14, 9), np.array([14248, 36806, 61382, 85956, 110532, 135106]), 10000, ], [(9, 9, 12, 7, 12), np.array([10177, 34369, 60577]), 10000], ], ) def test_compute_flat(shape, expected_subsample, subsample): increments = make_increments(shape) dtype = increments[0].dtype operations = np.prod([inc.shape[0] for inc in increments[:-1]], dtype=dtype) cols = np.tile(increments[-1], operations) assert_eq( convert.compute_flat(increments, cols, operations)[::subsample], expected_subsample.astype(dtype), ) @pytest.mark.parametrize( "shape, expected_shape", [ [(5, 6, 7, 8, 9), np.array([3024, 504, 72, 9, 1])], [(13, 12, 12, 9, 7), np.array([9072, 756, 63, 7, 1])], [(12, 15, 7, 14, 9), np.array([13230, 882, 126, 9, 1])], [ (18, 5, 12, 14, 9, 11, 8, 14), np.array([9313920, 1862784, 155232, 11088, 1232, 112, 14, 1]), ], [ (11, 6, 13, 11, 17, 7, 15), np.array([1531530, 255255, 19635, 1785, 105, 15, 1]), ], [(9, 9, 12, 7, 12), np.array([9072, 1008, 84, 12, 1])], ], ) def test_transform_shape(shape, expected_shape): assert_eq(convert.transform_shape(np.asarray(shape)), expected_shape, compare_dtype=False) sparse-0.18.0/sparse/numba_backend/tests/test_conversion.py000066400000000000000000000031041514474157100241120ustar00rootroot00000000000000import sparse from sparse.numba_backend._utils import assert_eq import pytest import numpy as np import scipy.sparse as sps FORMATS_ND = [ sparse.COO, sparse.DOK, sparse.GCXS, ] FORMATS_2D = [ sparse.numba_backend._compressed.CSC, sparse.numba_backend._compressed.CSR, ] FORMATS = FORMATS_2D + FORMATS_ND @pytest.mark.parametrize("format1", FORMATS) @pytest.mark.parametrize("format2", FORMATS) def test_conversion(format1, format2): x = sparse.random((10, 10), density=0.5, format=format1, fill_value=0.5) y = x.asformat(format2) assert_eq(x, y) def test_extra_kwargs(): x = sparse.full((2, 2), 1, format="gcxs", compressed_axes=[1]) y = sparse.full_like(x, 1) assert_eq(x, y) @pytest.mark.parametrize("format1", FORMATS_ND) @pytest.mark.parametrize("format2", FORMATS_ND) def test_conversion_scalar(format1, format2): x = sparse.random((), format=format1, fill_value=0.5) y = x.asformat(format2) assert_eq(x, y) def test_non_canonical_conversion(): """ Regression test for gh-602. Adapted from https://github.com/LiberTEM/sparseconverter/blob/4cfc0ee2ad4c37b07742db8f3643bcbd858a4e85/src/sparseconverter/__init__.py#L154-L183 """ data = np.array((2.0, 1.0, 3.0, 3.0, 1.0)) indices = np.array((1, 0, 0, 1, 1), dtype=int) indptr = np.array((0, 2, 5), dtype=int) x = sps.csr_array((data, indices, indptr), shape=(2, 2)) ref = np.array(((1.0, 2.0), (3.0, 4.0))) gcxs_check = sparse.GCXS(x) assert np.all(gcxs_check[:1].todense() == ref[:1]) and np.all(gcxs_check[1:].todense() == ref[1:]) sparse-0.18.0/sparse/numba_backend/tests/test_coo.py000066400000000000000000001730311514474157100225140ustar00rootroot00000000000000import contextlib import operator import pickle import sys import sparse from sparse import COO, DOK from sparse.numba_backend._settings import NEP18_ENABLED from sparse.numba_backend._utils import assert_eq, check_zero_fill_value, html_table, random_value_array import pytest import numpy as np import scipy.sparse import scipy.stats @pytest.fixture(scope="module", params=["f8", "f4", "i8", "i4"]) def random_sparse(request, rng): dtype = request.param if np.issubdtype(dtype, np.integer): def data_rvs(n): return rng.integers(-1000, 1000, n) else: data_rvs = None return sparse.random((20, 30, 40), density=0.25, data_rvs=data_rvs).astype(dtype) @pytest.fixture(scope="module", params=["f8", "f4", "i8", "i4"]) def random_sparse_small(request, rng): dtype = request.param if np.issubdtype(dtype, np.integer): def data_rvs(n): return rng.integers(-10, 10, n) else: data_rvs = None return sparse.random((20, 30, 40), density=0.25, data_rvs=data_rvs).astype(dtype) @pytest.mark.parametrize("reduction, kwargs", [("sum", {}), ("sum", {"dtype": np.float32}), ("prod", {})]) @pytest.mark.parametrize("axis", [None, 0, 1, 2, (0, 2), -3, (1, -1)]) @pytest.mark.parametrize("keepdims", [True, False]) def test_reductions_fv(reduction, random_sparse_small, axis, keepdims, kwargs, rng): x = random_sparse_small + rng.integers(-1, 1, dtype="i4") y = x.todense() xx = getattr(x, reduction)(axis=axis, keepdims=keepdims, **kwargs) yy = getattr(y, reduction)(axis=axis, keepdims=keepdims, **kwargs) assert_eq(xx, yy) @pytest.mark.parametrize( "reduction, kwargs", [ ("sum", {}), ("sum", {"dtype": np.float32}), ("mean", {}), ("mean", {"dtype": np.float32}), ("prod", {}), ("max", {}), ("min", {}), ("std", {}), ("var", {}), ], ) @pytest.mark.parametrize("axis", [None, 0, 1, 2, (0, 2), -3, (1, -1)]) @pytest.mark.parametrize("keepdims", [True, False]) def test_reductions(reduction, random_sparse, axis, keepdims, kwargs): x = random_sparse y = x.todense() xx = getattr(x, reduction)(axis=axis, keepdims=keepdims, **kwargs) yy = getattr(y, reduction)(axis=axis, keepdims=keepdims, **kwargs) assert_eq(xx, yy) @pytest.mark.xfail(reason=("Setting output dtype=float16 produces results inconsistent with numpy")) @pytest.mark.filterwarnings("ignore:overflow") @pytest.mark.parametrize( "reduction, kwargs", [("sum", {"dtype": np.float16}), ("mean", {"dtype": np.float16})], ) @pytest.mark.parametrize("axis", [None, 0, 1, 2, (0, 2)]) def test_reductions_float16(random_sparse, reduction, kwargs, axis): x = random_sparse y = x.todense() xx = getattr(x, reduction)(axis=axis, **kwargs) yy = getattr(y, reduction)(axis=axis, **kwargs) assert_eq(xx, yy, atol=1e-2) @pytest.mark.parametrize("reduction,kwargs", [("any", {}), ("all", {})]) @pytest.mark.parametrize("axis", [None, 0, 1, 2, (0, 2), -3, (1, -1)]) @pytest.mark.parametrize("keepdims", [True, False]) def test_reductions_bool(random_sparse, reduction, kwargs, axis, keepdims): y = np.zeros((2, 3, 4), dtype=bool) y[0] = True y[1, 1, 1] = True x = sparse.COO.from_numpy(y) xx = getattr(x, reduction)(axis=axis, keepdims=keepdims, **kwargs) yy = getattr(y, reduction)(axis=axis, keepdims=keepdims, **kwargs) assert_eq(xx, yy) @pytest.mark.parametrize( "reduction,kwargs", [ (np.max, {}), (np.sum, {}), (np.sum, {"dtype": np.float32}), (np.mean, {}), (np.mean, {"dtype": np.float32}), (np.prod, {}), (np.min, {}), ], ) @pytest.mark.parametrize("axis", [None, 0, 1, 2, (0, 2), -1, (0, -1)]) @pytest.mark.parametrize("keepdims", [True, False]) def test_ufunc_reductions(random_sparse, reduction, kwargs, axis, keepdims): x = random_sparse y = x.todense() xx = reduction(x, axis=axis, keepdims=keepdims, **kwargs) yy = reduction(y, axis=axis, keepdims=keepdims, **kwargs) assert_eq(xx, yy) # If not a scalar/1 element array, must be a sparse array if xx.size > 1: assert isinstance(xx, COO) @pytest.mark.parametrize( "reduction,kwargs", [ (np.max, {}), (np.sum, {"axis": 0}), (np.prod, {"keepdims": True}), (np.add.reduce, {}), (np.add.reduce, {"keepdims": True}), (np.minimum.reduce, {"axis": 0}), ], ) def test_ufunc_reductions_kwargs(reduction, kwargs): x = sparse.random((2, 3, 4), density=0.5) y = x.todense() xx = reduction(x, **kwargs) yy = reduction(y, **kwargs) assert_eq(xx, yy) # If not a scalar/1 element array, must be a sparse array if xx.size > 1: assert isinstance(xx, COO) @pytest.mark.parametrize("reduction", ["nansum", "nanmean", "nanprod", "nanmax", "nanmin"]) @pytest.mark.parametrize("axis", [None, 0, 1]) @pytest.mark.parametrize("keepdims", [False]) @pytest.mark.parametrize("fraction", [0.25, 0.5, 0.75, 1.0]) @pytest.mark.filterwarnings("ignore:All-NaN") @pytest.mark.filterwarnings("ignore:Mean of empty slice") def test_nan_reductions(reduction, axis, keepdims, fraction): s = sparse.random((2, 3, 4), data_rvs=random_value_array(np.nan, fraction), density=0.25) x = s.todense() expected = getattr(np, reduction)(x, axis=axis, keepdims=keepdims) actual = getattr(sparse, reduction)(s, axis=axis, keepdims=keepdims) assert_eq(expected, actual) @pytest.mark.parametrize("reduction", ["nanmax", "nanmin", "nanmean"]) @pytest.mark.parametrize("axis", [None, 0, 1]) def test_all_nan_reduction_warning(reduction, axis): x = random_value_array(np.nan, 1.0)(2 * 3 * 4).reshape(2, 3, 4) s = COO.from_numpy(x) with pytest.warns(RuntimeWarning): getattr(sparse, reduction)(s, axis=axis) @pytest.mark.parametrize( "axis", [None, (1, 2, 0), (2, 1, 0), (0, 1, 2), (0, 1, -1), (0, -2, -1), (-3, -2, -1)], ) def test_transpose(axis): x = sparse.random((2, 3, 4), density=0.25) y = x.todense() xx = x.transpose(axis) yy = y.transpose(axis) assert_eq(xx, yy) @pytest.mark.parametrize( "axis", [ (0, 1), # too few (0, 1, 2, 3), # too many (3, 1, 0), # axis 3 illegal (0, -1, -4), # axis -4 illegal (0, 0, 1), # duplicate axis 0 (0, -1, 2), # duplicate axis -1 == 2 0.3, # Invalid type in axis ((0, 1, 2),), # Iterable inside iterable ], ) def test_transpose_error(axis): x = sparse.random((2, 3, 4), density=0.25) with pytest.raises(ValueError): x.transpose(axis) @pytest.mark.parametrize("axis1", [-3, -2, -1, 0, 1, 2]) @pytest.mark.parametrize("axis2", [-3, -2, -1, 0, 1, 2]) def test_swapaxes(axis1, axis2): x = sparse.random((2, 3, 4), density=0.25) y = x.todense() xx = x.swapaxes(axis1, axis2) yy = y.swapaxes(axis1, axis2) assert_eq(xx, yy) @pytest.mark.parametrize("axis1", [-4, 3]) @pytest.mark.parametrize("axis2", [-4, 3, 0]) def test_swapaxes_error(axis1, axis2): x = sparse.random((2, 3, 4), density=0.25) with pytest.raises(ValueError): x.swapaxes(axis1, axis2) @pytest.mark.parametrize( "source, destination", [ [0, 1], [2, 1], [-2, 1], [-2, -3], [(0, 1), (2, 3)], [(-1, 0), (0, 1)], [(0, 1, 2), (2, 1, 0)], [(0, 1, 2), (-2, -3, -1)], ], ) def test_moveaxis(source, destination): x = sparse.random((2, 3, 4, 5), density=0.25) y = x.todense() xx = sparse.moveaxis(x, source, destination) yy = np.moveaxis(y, source, destination) assert_eq(xx, yy) @pytest.mark.parametrize("source, destination", [[0, -4], [(0, 5), (1, 2)], [(0, 1, 2), (2, 1)]]) def test_moveaxis_error(source, destination): x = sparse.random((2, 3, 4), density=0.25) with pytest.raises(ValueError): sparse.moveaxis(x, source, destination) @pytest.mark.parametrize( "a,b", [ [(3, 4), (3, 4)], [(12,), (3, 4)], [(12,), (3, -1)], [(3, 4), (12,)], [(3, 4), (-1, 4)], [(3, 4), (3, -1)], [(2, 3, 4, 5), (8, 15)], [(2, 3, 4, 5), (24, 5)], [(2, 3, 4, 5), (20, 6)], [(), ()], ], ) @pytest.mark.parametrize("format", ["coo", "dok"]) def test_reshape(a, b, format): s = sparse.random(a, density=0.5, format=format) x = s.todense() assert_eq(x.reshape(b), s.reshape(b)) def test_large_reshape(): n = 100 m = 10 row = np.arange(n, dtype=np.uint16) col = row % m data = np.ones(n, dtype=np.uint8) x = COO((data, (row, col)), shape=(100, 10), sorted=True, has_duplicates=False) assert_eq(x, x.reshape(x.shape)) def test_reshape_same(): s = sparse.random((3, 5), density=0.5) assert s.reshape(s.shape) is s @pytest.mark.parametrize("format", [COO, DOK]) def test_reshape_function(format): s = sparse.random((5, 3), density=0.5, format=format) x = s.todense() shape = (3, 5) s2 = np.reshape(s, shape) assert isinstance(s2, format) assert_eq(s2, x.reshape(shape)) def test_reshape_upcast(): a = sparse.random((10, 10, 10), density=0.5, format="coo", idx_dtype=np.uint8) assert a.reshape(1000).coords.dtype == np.uint16 @pytest.mark.parametrize("format", [COO, DOK]) def test_reshape_errors(format): s = sparse.random((5, 3), density=0.5, format=format) with pytest.raises(NotImplementedError): s.reshape((3, 5, 1), order="F") @pytest.mark.parametrize("a_ndim", [1, 2, 3]) @pytest.mark.parametrize("b_ndim", [1, 2, 3]) def test_kron(a_ndim, b_ndim): a_shape = (2, 3, 4)[:a_ndim] b_shape = (5, 6, 7)[:b_ndim] sa = sparse.random(a_shape, density=0.5) a = sa.todense() sb = sparse.random(b_shape, density=0.5) b = sb.todense() sol = np.kron(a, b) assert_eq(sparse.kron(sa, sb), sol) assert_eq(sparse.kron(sa, b), sol) assert_eq(sparse.kron(a, sb), sol) with pytest.raises(ValueError): assert_eq(sparse.kron(a, b), sol) @pytest.mark.parametrize("a_spmatrix, b_spmatrix", [(True, True), (True, False), (False, True)]) def test_kron_spmatrix(a_spmatrix, b_spmatrix): sa = sparse.random((3, 4), density=0.5) a = sa.todense() sb = sparse.random((5, 6), density=0.5) b = sb.todense() if a_spmatrix: sa = sa.tocsr() if b_spmatrix: sb = sb.tocsr() sol = np.kron(a, b) assert_eq(sparse.kron(sa, sb), sol) assert_eq(sparse.kron(sa, b), sol) assert_eq(sparse.kron(a, sb), sol) with pytest.raises(ValueError): assert_eq(sparse.kron(a, b), sol) @pytest.mark.parametrize("ndim", [1, 2, 3]) def test_kron_scalar(ndim): if ndim: a_shape = (3, 4, 5)[:ndim] sa = sparse.random(a_shape, density=0.5) a = sa.todense() else: sa = a = np.array(6) scalar = np.array(5) sol = np.kron(a, scalar) assert_eq(sparse.kron(sa, scalar), sol) assert_eq(sparse.kron(scalar, sa), sol) def test_gt(): s = sparse.random((2, 3, 4), density=0.5) x = s.todense() m = x.mean() assert_eq(x > m, s > m) m = s.data[2] assert_eq(x > m, s > m) assert_eq(x >= m, s >= m) @pytest.mark.parametrize( "index", [ # Integer 0, 1, -1, (1, 1, 1), # Pure slices (slice(0, 2),), (slice(None, 2), slice(None, 2)), (slice(1, None), slice(1, None)), (slice(None, None),), (slice(None, None, -1),), (slice(None, 2, -1), slice(None, 2, -1)), (slice(1, None, 2), slice(1, None, 2)), (slice(None, None, 2),), (slice(None, 2, -1), slice(None, 2, -2)), (slice(1, None, 2), slice(1, None, 1)), (slice(None, None, -2),), # Combinations (0, slice(0, 2)), (slice(0, 1), 0), (None, slice(1, 3), 0), (slice(0, 3), None, 0), (slice(1, 2), slice(2, 4)), (slice(1, 2), slice(None, None)), (slice(1, 2), slice(None, None), 2), (slice(1, 2, 2), slice(None, None), 2), (slice(1, 2, None), slice(None, None, 2), 2), (slice(1, 2, -2), slice(None, None), -2), (slice(1, 2, None), slice(None, None, -2), 2), (slice(1, 2, -1), slice(None, None), -1), (slice(1, 2, None), slice(None, None, -1), 2), (slice(2, 0, -1), slice(None, None), -1), (slice(-2, None, None),), (slice(-1, None, None), slice(-2, None, None)), # With ellipsis (Ellipsis, slice(1, 3)), (1, Ellipsis, slice(1, 3)), (slice(0, 1), Ellipsis), (Ellipsis, None), (None, Ellipsis), (1, Ellipsis), (1, Ellipsis, None), (1, 1, 1, Ellipsis), (Ellipsis, 1, None), # With multi-axis advanced indexing ([0, 1],) * 2, ([0, 1], [0, 2]), ([0, 0, 0], [0, 1, 2], [1, 2, 1]), # Pathological - Slices larger than array (slice(None, 1000)), (slice(None), slice(None, 1000)), (slice(None), slice(1000, -1000, -1)), (slice(None), slice(1000, -1000, -50)), # Pathological - Wrong ordering of start/stop (slice(5, 0),), (slice(0, 5, -1),), (slice(0, 0, None),), ], ) def test_slicing(index): s = sparse.random((2, 3, 4), density=0.5) x = s.todense() assert_eq(x[index], s[index]) @pytest.mark.parametrize( "index", [ ([1, 0], 0), (1, [0, 2]), (0, [1, 0], 0), (1, [2, 0], 0), (1, [], 0), ([True, False], slice(1, None), slice(-2, None)), (slice(1, None), slice(-2, None), [True, False, True, False]), ([1, 0],), (Ellipsis, [2, 1, 3]), (slice(None), [2, 1, 2]), (1, [2, 0, 1]), ], ) def test_advanced_indexing(index): s = sparse.random((2, 3, 4), density=0.5) x = s.todense() assert_eq(x[index], s[index]) def test_custom_dtype_slicing(): dt = np.dtype([("part1", np.float64), ("part2", np.int64, (2,)), ("part3", np.int64, (2, 2))]) x = np.zeros((2, 3, 4), dtype=dt) x[1, 1, 1] = (0.64, [4, 2], [[1, 2], [3, 0]]) s = COO.from_numpy(x) assert x[1, 1, 1] == s[1, 1, 1] assert x[0, 1, 2] == s[0, 1, 2] assert_eq(x["part1"], s["part1"]) assert_eq(x["part2"], s["part2"]) assert_eq(x["part3"], s["part3"]) @pytest.mark.parametrize( "index", [ (Ellipsis, Ellipsis), (1, 1, 1, 1), (slice(None),) * 4, 5, -5, "foo", [True, False, False], 0.5, [0.5], {"potato": "kartoffel"}, ([[0, 1]],), ], ) def test_slicing_errors(index): s = sparse.random((2, 3, 4), density=0.5) with pytest.raises(IndexError): s[index] def test_concatenate(): xx = sparse.random((2, 3, 4), density=0.5) x = xx.todense() yy = sparse.random((5, 3, 4), density=0.5) y = yy.todense() zz = sparse.random((4, 3, 4), density=0.5) z = zz.todense() assert_eq(np.concatenate([x, y, z], axis=0), sparse.concatenate([xx, yy, zz], axis=0)) xx = sparse.random((5, 3, 1), density=0.5) x = xx.todense() yy = sparse.random((5, 3, 3), density=0.5) y = yy.todense() zz = sparse.random((5, 3, 2), density=0.5) z = zz.todense() assert_eq(np.concatenate([x, y, z], axis=2), sparse.concatenate([xx, yy, zz], axis=2)) assert_eq(np.concatenate([x, y, z], axis=-1), sparse.concatenate([xx, yy, zz], axis=-1)) @pytest.mark.parametrize("axis", [0, 1]) @pytest.mark.parametrize("func", [sparse.stack, sparse.concatenate]) def test_concatenate_mixed(func, axis): s = sparse.random((10, 10), density=0.5) d = s.todense() with pytest.raises(ValueError): func([d, s, s], axis=axis) def test_concatenate_noarrays(): with pytest.raises(ValueError): sparse.concatenate([]) @pytest.mark.parametrize("shape", [(5,), (2, 3, 4), (5, 2)]) @pytest.mark.parametrize("axis", [0, 1, -1]) def test_stack(shape, axis): xx = sparse.random(shape, density=0.5) x = xx.todense() yy = sparse.random(shape, density=0.5) y = yy.todense() zz = sparse.random(shape, density=0.5) z = zz.todense() assert_eq(np.stack([x, y, z], axis=axis), sparse.stack([xx, yy, zz], axis=axis)) def test_large_concat_stack(): data = np.array([1], dtype=np.uint8) coords = np.array([[255]], dtype=np.uint8) xs = COO(coords, data, shape=(256,), has_duplicates=False, sorted=True) x = xs.todense() assert_eq(np.stack([x, x]), sparse.stack([xs, xs])) assert_eq(np.concatenate((x, x)), sparse.concatenate((xs, xs))) def test_addition(): a = sparse.random((2, 3, 4), density=0.5) x = a.todense() b = sparse.random((2, 3, 4), density=0.5) y = b.todense() assert_eq(x + y, a + b) assert_eq(x - y, a - b) @pytest.mark.parametrize("scalar", [2, 2.5, np.float32(2.0), np.int8(3)]) def test_scalar_multiplication(scalar): a = sparse.random((2, 3, 4), density=0.5) x = a.todense() assert_eq(x * scalar, a * scalar) assert (a * scalar).nnz == a.nnz assert_eq(scalar * x, scalar * a) assert (scalar * a).nnz == a.nnz assert_eq(x / scalar, a / scalar) assert (a / scalar).nnz == a.nnz assert_eq(x // scalar, a // scalar) # division may reduce nnz. @pytest.mark.filterwarnings("ignore:divide by zero") def test_scalar_exponentiation(): a = sparse.random((2, 3, 4), density=0.5) x = a.todense() assert_eq(x**2, a**2) assert_eq(x**0.5, a**0.5) assert_eq(x**-1, a**-1) def test_create_with_lists_of_tuples(): L = [((0, 0, 0), 1), ((1, 2, 1), 1), ((1, 1, 1), 2), ((1, 3, 2), 3)] s = COO(L, shape=(2, 4, 3)) x = np.zeros((2, 4, 3), dtype=np.asarray([1, 2, 3]).dtype) for ind, value in L: x[ind] = value assert_eq(s, x) def test_sizeof(): x = np.eye(100) y = COO.from_numpy(x) nb = sys.getsizeof(y) assert 400 < nb < x.nbytes / 10 @pytest.mark.parametrize("sps_class", [scipy.sparse.coo_array, scipy.sparse.coo_matrix]) def test_scipy_sparse_interface(rng, sps_class): n = 100 m = 10 row = rng.integers(0, n, size=n, dtype=np.uint16) col = rng.integers(0, m, size=n, dtype=np.uint16) data = np.ones(n, dtype=np.uint8) if sps_class is scipy.sparse.coo_array: stack = np.zeros(n, dtype=np.uint8) inp = (data, (stack, row, col)) shape = (1, n, m) else: inp = (data, (row, col)) shape = (n, m) x = sps_class(inp, shape=shape) xx = sparse.COO(inp, shape=shape) def mT(x): match x.ndim: case 0 | 1: return x case 2: return x.T case _: return np.moveaxis(x, -1, -2) assert_eq(x, xx, check_nnz=False) assert_eq(mT(x), xx.mT, check_nnz=False) assert_eq(xx.to_scipy_sparse(), x, check_nnz=False) assert_eq(COO.from_scipy_sparse(xx.to_scipy_sparse()), xx, check_nnz=False) assert_eq(x, xx, check_nnz=False) assert_eq(mT(x).dot(x), xx.mT.dot(xx), check_nnz=False) assert isinstance(x + xx, COO) assert isinstance(xx + x, COO) @pytest.mark.parametrize("scipy_format", ["coo", "csr", "dok", "csc"]) def test_scipy_sparse_interaction(scipy_format): x = sparse.random((10, 20), density=0.2).todense() sp = getattr(scipy.sparse, scipy_format + "_array")(x) coo = COO(x) assert isinstance(sp + coo, COO) assert isinstance(coo + sp, COO) assert_eq(sp, coo) @pytest.mark.parametrize( "func", [operator.mul, operator.add, operator.sub, operator.gt, operator.lt, operator.ne], ) def test_op_scipy_sparse(func): xs = sparse.random((3, 4), density=0.5) y = sparse.random((3, 4), density=0.5).todense() ys = scipy.sparse.csr_array(y) x = xs.todense() assert_eq(func(x, y), func(xs, ys)) @pytest.mark.parametrize( "func", [ operator.add, operator.sub, pytest.param( operator.mul, marks=pytest.mark.xfail(reason="Scipy sparse auto-densifies in this case."), ), pytest.param( operator.gt, marks=pytest.mark.xfail(reason="Scipy sparse doesn't support this yet."), ), pytest.param( operator.lt, marks=pytest.mark.xfail(reason="Scipy sparse doesn't support this yet."), ), pytest.param( operator.ne, marks=pytest.mark.xfail(reason="Scipy sparse doesn't support this yet."), ), ], ) def test_op_scipy_sparse_left(func): ys = sparse.random((3, 4), density=0.5) x = sparse.random((3, 4), density=0.5).todense() xs = scipy.sparse.csr_array(x) y = ys.todense() assert_eq(func(x, y), func(xs, ys)) def test_cache_csr(): x = sparse.random((10, 5), density=0.5).todense() s = COO(x, cache=True) assert isinstance(s.tocsr(), scipy.sparse.csr_array) assert isinstance(s.tocsc(), scipy.sparse.csc_array) assert s.tocsr() is s.tocsr() assert s.tocsc() is s.tocsc() def test_single_dimension(): x = COO([1, 3], [1.0, 3.0], shape=(4,)) assert_eq(x, np.array([0, 1.0, 0, 3.0])) def test_large_sum(rng): n = 500000 x = rng.integers(0, 10000, size=(n,)) y = rng.integers(0, 1000, size=(n,)) z = rng.integers(0, 3, size=(n,)) data = rng.random(n) a = COO((x, y, z), data, shape=(10000, 1000, 3)) b = a.sum(axis=2) assert b.nnz > 100000 def test_add_many_sparse_arrays(): x = COO({(1, 1): 1}, shape=(2, 2)) y = sum([x] * 100) assert y.nnz < np.prod(y.shape) def test_caching(): x = COO({(9, 9, 9): 1}, shape=(10, 10, 10)) assert x[:].reshape((100, 10)).transpose().tocsr() is not x[:].reshape((100, 10)).transpose().tocsr() x = COO({(9, 9, 9): 1}, shape=(10, 10, 10), cache=True) assert x[:].reshape((100, 10)).transpose().tocsr() is x[:].reshape((100, 10)).transpose().tocsr() x = COO({(1, 1, 1, 1, 1, 1, 1, 2): 1}, shape=(2, 2, 2, 2, 2, 2, 2, 3), cache=True) for _ in range(x.ndim): x.reshape(x.size) assert len(x._cache["reshape"]) < 5 def test_scalar_slicing(): x = np.array([0, 1]) s = COO(x) assert np.isscalar(s[0]) assert_eq(x[0], s[0]) assert isinstance(s[0, ...], COO) assert s[0, ...].shape == () assert_eq(x[0, ...], s[0, ...]) assert np.isscalar(s[1]) assert_eq(x[1], s[1]) assert isinstance(s[1, ...], COO) assert s[1, ...].shape == () assert_eq(x[1, ...], s[1, ...]) @pytest.mark.parametrize( "shape, k", [((3, 4), 0), ((3, 4, 5), 1), ((4, 2), -1), ((2, 4), -2), ((4, 4), 1000)], ) def test_triul(shape, k): s = sparse.random(shape, density=0.5) x = s.todense() assert_eq(np.triu(x, k), sparse.triu(s, k)) assert_eq(np.tril(x, k), sparse.tril(s, k)) def test_empty_reduction(): x = np.zeros((2, 3, 4), dtype=np.float64) xs = COO.from_numpy(x) assert_eq(x.sum(axis=(0, 2)), xs.sum(axis=(0, 2))) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4)]) @pytest.mark.parametrize("density", [0.1, 0.3, 0.5, 0.7]) def test_random_shape(shape, density): s = sparse.random(shape, density) assert isinstance(s, COO) assert s.shape == shape expected_nnz = density * np.prod(shape) assert np.floor(expected_nnz) <= s.nnz <= np.ceil(expected_nnz) @pytest.mark.parametrize("shape, nnz", [((1,), 1), ((2,), 0), ((3, 4), 5)]) def test_random_nnz(shape, nnz): s = sparse.random(shape, nnz=nnz) assert isinstance(s, COO) assert s.nnz == nnz @pytest.mark.parametrize("density, nnz", [(1, 1), (1.01, None), (-0.01, None), (None, 2)]) def test_random_invalid_density_and_nnz(density, nnz): with pytest.raises(ValueError): sparse.random((1,), density, nnz=nnz) def test_two_random_unequal(): s1 = sparse.random((2, 3, 4), 0.3) s2 = sparse.random((2, 3, 4), 0.3) assert not np.allclose(s1.todense(), s2.todense()) def test_two_random_same_seed(rng): state = rng.integers(100) s1 = sparse.random((2, 3, 4), 0.3, random_state=state) s2 = sparse.random((2, 3, 4), 0.3, random_state=state) assert_eq(s1, s2) @pytest.mark.parametrize( "rvs, dtype", [ (None, np.float64), (scipy.stats.poisson(25, loc=10).rvs, np.int64), (lambda x: np.random.default_rng().choice([True, False], size=x), np.bool_), ], ) @pytest.mark.parametrize("shape", [(2, 4, 5), (20, 40, 50)]) @pytest.mark.parametrize("density", [0.0, 0.01, 0.1, 0.2]) def test_random_rvs(rvs, dtype, shape, density): x = sparse.random(shape, density, data_rvs=rvs) assert x.shape == shape assert x.dtype == dtype @pytest.mark.parametrize("format", ["coo", "dok"]) def test_random_fv(format, rng): fv = rng.random() s = sparse.random((2, 3, 4), density=0.5, format=format, fill_value=fv) assert s.fill_value == fv def test_scalar_shape_construction(rng): x = rng.random(5) coords = np.arange(5)[None] s = COO(coords, x, shape=5) assert_eq(x, s) def test_len(): s = sparse.random((20, 30, 40)) assert len(s) == 20 def test_density(): s = sparse.random((20, 30, 40), density=0.1) assert np.isclose(s.density, 0.1) def test_size(): s = sparse.random((20, 30, 40)) assert s.size == 20 * 30 * 40 def test_np_array(): s = sparse.random((20, 30, 40)) with pytest.raises(RuntimeError): np.array(s) @pytest.mark.parametrize( "shapes", [ [(2,), (3, 2), (4, 3, 2)], [(3,), (2, 3), (2, 2, 3)], [(2,), (2, 2), (2, 2, 2)], [(4,), (4, 4), (4, 4, 4)], [(4,), (4, 4), (4, 4, 4)], [(4,), (4, 4), (4, 4, 4)], [(1, 1, 2), (1, 3, 1), (4, 1, 1)], [(2,), (2, 1), (2, 1, 1)], [(3,), (), (2, 3)], [(4, 4), (), ()], ], ) def test_three_arg_where(shapes): cs = sparse.random(shapes[0], density=0.5).astype(np.bool_) xs = sparse.random(shapes[1], density=0.5) ys = sparse.random(shapes[2], density=0.5) c = cs.todense() x = xs.todense() y = ys.todense() expected = np.where(c, x, y) actual = sparse.where(cs, xs, ys) assert isinstance(actual, COO) assert_eq(expected, actual) def test_one_arg_where(): s = sparse.random((2, 3, 4), density=0.5) x = s.todense() expected = np.where(x) actual = sparse.where(s) assert len(expected) == len(actual) for e, a in zip(expected, actual, strict=True): assert_eq(e, a, compare_dtype=False) def test_one_arg_where_dense(rng): x = rng.random((2, 3, 4)) with pytest.raises(ValueError): sparse.where(x) def test_two_arg_where(): cs = sparse.random((2, 3, 4), density=0.5).astype(np.bool_) xs = sparse.random((2, 3, 4), density=0.5) with pytest.raises(ValueError): sparse.where(cs, xs) @pytest.mark.parametrize("func", [operator.imul, operator.iadd, operator.isub]) def test_inplace_invalid_shape(func): xs = sparse.random((3, 4), density=0.5) ys = sparse.random((2, 3, 4), density=0.5) with pytest.raises(ValueError): func(xs, ys) def test_nonzero(): s = sparse.random((2, 3, 4), density=0.5) x = s.todense() expected = x.nonzero() actual = s.nonzero() assert isinstance(actual, tuple) assert len(expected) == len(actual) for e, a in zip(expected, actual, strict=True): assert_eq(e, a, compare_dtype=False) def test_argwhere(): s = sparse.random((2, 3, 4), density=0.5) x = s.todense() assert_eq(np.argwhere(s), np.argwhere(x), compare_dtype=False) @pytest.mark.parametrize("format", ["coo", "dok"]) def test_asformat(format): s = sparse.random((2, 3, 4), density=0.5, format="coo") s2 = s.asformat(format) assert_eq(s, s2) @pytest.mark.parametrize("format", [sparse.COO, sparse.DOK, scipy.sparse.csr_array, np.asarray]) def test_as_coo(format): x = format(sparse.random((3, 4), density=0.5, format="coo").todense()) s1 = sparse.as_coo(x) s2 = COO(x) assert_eq(x, s1) assert_eq(x, s2) def test_invalid_attrs_error(): s = sparse.random((3, 4), density=0.5, format="coo") with pytest.raises(ValueError): sparse.as_coo(s, shape=(2, 3)) with pytest.raises(ValueError): COO(s, shape=(2, 3)) with pytest.raises(ValueError): sparse.as_coo(s, fill_value=0.0) def test_invalid_iterable_error(): with pytest.raises(ValueError): x = [(3, 4, 5)] COO.from_iter(x, shape=(6,)) with pytest.raises(ValueError): x = [((2.3, 4.5), 3.2)] COO.from_iter(x, shape=(5,)) with pytest.raises(TypeError): COO.from_iter({(1, 1): 1}) def test_prod_along_axis(): s1 = sparse.random((10, 10), density=0.1) s2 = 1 - s1 x1 = s1.todense() x2 = s2.todense() assert_eq(s1.prod(axis=0), x1.prod(axis=0)) assert_eq(s2.prod(axis=0), x2.prod(axis=0)) class TestRoll: # test on 1d array # @pytest.mark.parametrize("shift", [0, 2, -2, 20, -20]) def test_1d(self, shift): xs = sparse.random((100,), density=0.5) x = xs.todense() assert_eq(np.roll(x, shift), sparse.roll(xs, shift)) assert_eq(np.roll(x, shift), sparse.roll(x, shift)) # test on 2d array # @pytest.mark.parametrize("shift", [0, 2, -2, 20, -20]) @pytest.mark.parametrize("ax", [None, 0, 1, (0, 1)]) def test_2d(self, shift, ax): xs = sparse.random((10, 10), density=0.5) x = xs.todense() assert_eq(np.roll(x, shift, axis=ax), sparse.roll(xs, shift, axis=ax)) assert_eq(np.roll(x, shift, axis=ax), sparse.roll(x, shift, axis=ax)) # test on rolling multiple axes at once # @pytest.mark.parametrize("shift", [(0, 0), (1, -1), (-1, 1), (10, -10)]) @pytest.mark.parametrize("ax", [(0, 1), (0, 2), (1, 2), (-1, 1)]) def test_multiaxis(self, shift, ax): xs = sparse.random((9, 9, 9), density=0.5) x = xs.todense() assert_eq(np.roll(x, shift, axis=ax), sparse.roll(xs, shift, axis=ax)) assert_eq(np.roll(x, shift, axis=ax), sparse.roll(x, shift, axis=ax)) # test original is unchanged # @pytest.mark.parametrize("shift", [0, 2, -2, 20, -20]) @pytest.mark.parametrize("ax", [None, 0, 1, (0, 1)]) def test_original_is_copied(self, shift, ax): xs = sparse.random((10, 10), density=0.5) xc = COO(np.copy(xs.coords), np.copy(xs.data), shape=xs.shape) sparse.roll(xs, shift, axis=ax) assert_eq(xs, xc) # test on empty array # def test_empty(self): x = np.array([]) assert_eq(np.roll(x, 1), sparse.roll(sparse.as_coo(x), 1)) # test error handling # @pytest.mark.parametrize( "args", [ # iterable shift, but axis not iterable ((1, 1), 0), # ndim(axis) != 1 (1, [[0, 1]]), # ndim(shift) != 1 ([[0, 1]], [0, 1]), ([[0, 1], [0, 1]], [0, 1]), ], ) def test_valerr(self, args): x = sparse.random((2, 2, 2), density=1) with pytest.raises(ValueError): sparse.roll(x, *args) @pytest.mark.parametrize("dtype", [np.uint8, np.int8]) @pytest.mark.parametrize("shift", [300, -300]) def test_dtype_errors(self, dtype, shift): x = sparse.random((5, 5, 5), density=0.2, idx_dtype=dtype) with pytest.raises(ValueError): sparse.roll(x, shift) def test_unsigned_type_error(self): x = sparse.random((5, 5, 5), density=0.3, idx_dtype=np.uint8) with pytest.raises(ValueError): sparse.roll(x, -1) def test_clip(): x = np.array([[0, 0, 1, 0, 2], [5, 0, 0, 3, 0]]) s = sparse.COO.from_numpy(x) assert_eq(s.clip(min=1), x.clip(min=1)) assert_eq(s.clip(max=3), x.clip(max=3)) assert_eq(s.clip(min=1, max=3), x.clip(min=1, max=3)) assert_eq(s.clip(min=1, max=3.0), x.clip(min=1, max=3.0)) assert_eq(np.clip(s, 1, 3), np.clip(x, 1, 3)) out = sparse.COO.from_numpy(np.zeros_like(x)) out2 = s.clip(min=1, max=3, out=out) assert out is out2 assert_eq(out, x.clip(min=1, max=3)) class TestFailFillValue: # Check failed fill_value op def test_nonzero_fv(self): xs = sparse.random((2, 3), density=0.5, fill_value=1) ys = sparse.random((3, 4), density=0.5) with pytest.raises(ValueError): sparse.dot(xs, ys) def test_inconsistent_fv(self): xs = sparse.random((3, 4), density=0.5, fill_value=1) ys = sparse.random((3, 4), density=0.5, fill_value=2) with pytest.raises(ValueError): sparse.concatenate([xs, ys]) def test_pickle(): x = sparse.COO.from_numpy([1, 0, 0, 0, 0]).reshape((5, 1)) # Enable caching and add some data to it x.enable_caching() x.T # noqa: B018 assert x._cache is not None # Pickle sends data but not cache x2 = pickle.loads(pickle.dumps(x)) assert_eq(x, x2) assert x2._cache is None @pytest.mark.parametrize("deep", [True, False]) def test_copy(deep): x = sparse.COO.from_numpy([1, 0, 0, 0, 0]).reshape((5, 1)) # Enable caching and add some data to it x.enable_caching() x.T # noqa: B018 assert x._cache is not None x2 = x.copy(deep) assert_eq(x, x2) assert (x2.data is x.data) is not deep assert (x2.coords is x.coords) is not deep assert x2._cache is None @pytest.mark.parametrize("ndim", [2, 3, 4, 5]) def test_initialization(ndim, rng): shape = [10] * ndim shape[1] *= 2 shape = tuple(shape) coords = rng.integers(10, size=(ndim, 20)) data = rng.random(20) COO(coords, data=data, shape=shape) with pytest.raises(ValueError, match="data length"): COO(coords, data=data[:5], shape=shape) with pytest.raises(ValueError, match="shape of `coords`"): coords = rng.integers(10, size=(1, 20)) COO(coords, data=data, shape=shape) @pytest.mark.parametrize("N, M", [(4, None), (4, 10), (10, 4), (0, 10)]) def test_eye(N, M): m = M or N for k in [0, N - 2, N + 2, m - 2, m + 2, np.iinfo(np.intp).min]: assert_eq(sparse.eye(N, M=M, k=k), np.eye(N, M=M, k=k)) assert_eq(sparse.eye(N, M=M, k=k, dtype="i4"), np.eye(N, M=M, k=k, dtype="i4")) @pytest.mark.parametrize("from_", [np.int8, np.int64, np.float32, np.float64, np.complex64, np.complex128]) @pytest.mark.parametrize("to", [np.int8, np.int64, np.float32, np.float64, np.complex64, np.complex128]) @pytest.mark.parametrize("casting", ["no", "safe", "same_kind"]) def test_can_cast(from_, to, casting): assert sparse.can_cast(sparse.zeros((2, 2), dtype=from_), to, casting=casting) == np.can_cast( np.zeros((2, 2), dtype=from_), to, casting=casting ) assert sparse.can_cast(from_, to, casting=casting) == np.can_cast(from_, to, casting=casting) @pytest.mark.parametrize("funcname", ["ones", "zeros"]) def test_ones_zeros(funcname): sp_func = getattr(sparse, funcname) np_func = getattr(np, funcname) assert_eq(sp_func(5), np_func(5)) assert_eq(sp_func((5, 4)), np_func((5, 4))) assert_eq(sp_func((5, 4), dtype="i4"), np_func((5, 4), dtype="i4")) assert_eq(sp_func((5, 4), dtype=None), np_func((5, 4), dtype=None)) @pytest.mark.parametrize("funcname", ["ones_like", "zeros_like"]) def test_ones_zeros_like(funcname): sp_func = getattr(sparse, funcname) np_func = getattr(np, funcname) x = np.ones((5, 5), dtype="i8") assert_eq(sp_func(x), np_func(x)) assert_eq(sp_func(x, dtype="f8"), np_func(x, dtype="f8")) assert_eq(sp_func(x, dtype=None), np_func(x, dtype=None)) assert_eq(sp_func(x, shape=(2, 2)), np_func(x, shape=(2, 2))) def test_full(): assert_eq(sparse.full(5, 9), np.full(5, 9)) assert_eq(sparse.full(5, 9, dtype="f8"), np.full(5, 9, dtype="f8")) assert_eq(sparse.full((5, 4), 9.5), np.full((5, 4), 9.5)) assert_eq(sparse.full((5, 4), 9.5, dtype="i4"), np.full((5, 4), 9.5, dtype="i4")) def test_full_like(): x = np.zeros((5, 5), dtype="i8") assert_eq(sparse.full_like(x, 9.5), np.full_like(x, 9.5)) assert_eq(sparse.full_like(x, 9.5, dtype="f8"), np.full_like(x, 9.5, dtype="f8")) assert_eq(sparse.full_like(x, 9.5, shape=(2, 2)), np.full_like(x, 9.5, shape=(2, 2))) @pytest.mark.parametrize( "x", [ np.array([1, 2, 0, 0, 0]), np.array([1 + 2j, 2 - 1j, 0, 1, 0]), np.array(["a", "b", "c"]), ], ) def test_complex_methods(x): s = sparse.COO.from_numpy(x) assert_eq(s.imag, x.imag) assert_eq(s.real, x.real) if np.issubdtype(s.dtype, np.number): assert_eq(s.conj(), x.conj()) def test_np_matrix(rng): x = rng.random((10, 1)).view(type=np.matrix) s = sparse.COO.from_numpy(x) assert_eq(x, s) def test_out_dtype(): a = sparse.eye(5, dtype="float32") b = sparse.eye(5, dtype="float64") assert np.positive(a, out=b).dtype == np.positive(a.todense(), out=b.todense()).dtype assert ( np.positive(a, out=b, dtype="float64").dtype == np.positive(a.todense(), out=b.todense(), dtype="float64").dtype ) @contextlib.contextmanager def auto_densify(): "For use in tests only! Not threadsafe." import os from importlib import reload os.environ["SPARSE_AUTO_DENSIFY"] = "1" reload(sparse.numba_backend._settings) yield del os.environ["SPARSE_AUTO_DENSIFY"] reload(sparse.numba_backend._settings) def test_setting_into_numpy_slice(): actual = np.zeros((5, 5)) s = sparse.COO(data=[1, 1], coords=(2, 4), shape=(5,)) # This calls s.__array__(dtype('float64')) which means that __array__ # must accept a positional argument. If not this will raise, of course, # TypeError: __array__() takes 1 positional argument but 2 were given with auto_densify(): actual[:, 0] = s # Might as well check the content of the result as well. expected = np.zeros((5, 5)) expected[:, 0] = s.todense() assert_eq(actual, expected) # Without densification, setting is unsupported. with pytest.raises(RuntimeError): actual[:, 0] = s def test_successful_densification(): s = sparse.random((3, 4, 5), density=0.5) with auto_densify(): x = np.array(s) assert isinstance(x, np.ndarray) assert_eq(s, x) def test_failed_densification(): s = sparse.random((3, 4, 5), density=0.5) with pytest.raises(RuntimeError): np.array(s) def test_warn_on_too_dense(): import os from importlib import reload os.environ["SPARSE_WARN_ON_TOO_DENSE"] = "1" reload(sparse.numba_backend._settings) with pytest.warns(RuntimeWarning): sparse.random((3, 4, 5), density=1.0) del os.environ["SPARSE_WARN_ON_TOO_DENSE"] reload(sparse.numba_backend._settings) def test_prune_coo(): coords = np.array([[0, 1, 2, 3]]) data = np.array([1, 0, 1, 2]) s1 = COO(coords, data, shape=(4,)) s2 = COO(coords, data, shape=(4,), prune=True) assert s2.nnz == 3 # Densify s1 because it isn't canonical assert_eq(s1.todense(), s2, check_nnz=False) def test_diagonal(): a = sparse.random((4, 4), density=0.5) assert_eq(sparse.diagonal(a, offset=0), np.diagonal(a.todense(), offset=0)) assert_eq(sparse.diagonal(a, offset=1), np.diagonal(a.todense(), offset=1)) assert_eq(sparse.diagonal(a, offset=2), np.diagonal(a.todense(), offset=2)) a = sparse.random((4, 5, 4, 6), density=0.5) assert_eq( sparse.diagonal(a, offset=0, axis1=0, axis2=2), np.diagonal(a.todense(), offset=0, axis1=0, axis2=2), ) assert_eq( sparse.diagonal(a, offset=1, axis1=0, axis2=2), np.diagonal(a.todense(), offset=1, axis1=0, axis2=2), ) assert_eq( sparse.diagonal(a, offset=2, axis1=0, axis2=2), np.diagonal(a.todense(), offset=2, axis1=0, axis2=2), ) def test_diagonalize(): assert_eq(sparse.diagonalize(np.ones(3)), sparse.eye(3)) assert_eq( sparse.diagonalize(scipy.sparse.coo_array(np.eye(3))), sparse.diagonalize(sparse.eye(3)), ) # inverse of diagonal b = sparse.random((4, 3, 2), density=0.5) b_diag = sparse.diagonalize(b, axis=1) assert_eq(b, sparse.diagonal(b_diag, axis1=1, axis2=3).transpose([0, 2, 1])) RESULT_TYPE_DTYPES = [ "i1", "i2", "i4", "i8", "u1", "u2", "u4", "u8", "f4", "f8", "c8", "c16", object, ] @pytest.mark.parametrize("t1", RESULT_TYPE_DTYPES) @pytest.mark.parametrize("t2", RESULT_TYPE_DTYPES) @pytest.mark.parametrize( "func", [ sparse.result_type, pytest.param( np.result_type, marks=pytest.mark.skipif(not NEP18_ENABLED, reason="NEP18 is not enabled"), ), ], ) @pytest.mark.parametrize("data", [1, [1]]) # Not the same outputs! def test_result_type(t1, t2, func, data): a = np.array(data, dtype=t1) b = np.array(data, dtype=t2) expect = np.result_type(a, b) assert func(a, sparse.COO(b)) == expect assert func(sparse.COO(a), b) == expect assert func(sparse.COO(a), sparse.COO(b)) == expect assert func(a.dtype, sparse.COO(b)) == np.result_type(a.dtype, b) assert func(sparse.COO(a), b.dtype) == np.result_type(a, b.dtype) @pytest.mark.parametrize("in_shape", [(5, 5), 62, (3, 3, 3)]) def test_flatten(in_shape): s = sparse.random(in_shape, density=0.5) x = s.todense() a = s.flatten() e = x.flatten() assert_eq(e, a) def test_asnumpy(): s = sparse.COO(data=[1], coords=[2], shape=(5,)) assert_eq(sparse.asnumpy(s), s.todense()) assert_eq(sparse.asnumpy(s, dtype=np.float64), np.asarray(s.todense(), dtype=np.float64)) a = np.array([1, 2, 3]) # Array passes through with no copying. assert sparse.asnumpy(a) is a @pytest.mark.parametrize("shape1", [(2,), (2, 3), (2, 3, 4)]) @pytest.mark.parametrize("shape2", [(2,), (2, 3), (2, 3, 4)]) def test_outer(shape1, shape2): s1 = sparse.random(shape1, density=0.5) s2 = sparse.random(shape2, density=0.5) x1 = s1.todense() x2 = s2.todense() assert_eq(sparse.outer(s1, s2), np.outer(x1, x2)) assert_eq(np.multiply.outer(s1, s2), np.multiply.outer(x1, x2)) def test_scalar_list_init(): a = sparse.COO([], [], ()) b = sparse.COO([], [1], ()) assert a.todense() == 0 assert b.todense() == 1 def test_raise_on_nd_data(): s1 = sparse.random((2, 3, 4), density=0.5) with pytest.raises(ValueError): sparse.COO(s1.coords, s1.data[:, None], shape=(2, 3, 4)) def test_astype_casting(): s1 = sparse.random((2, 3, 4), density=0.5) with pytest.raises(TypeError): s1.astype(dtype=np.int64, casting="safe") def test_astype_no_copy(): s1 = sparse.random((2, 3, 4), density=0.5) s2 = s1.astype(s1.dtype, copy=False) assert s1 is s2 def test_coo_valerr(): a = np.arange(300) with pytest.raises(ValueError): COO.from_numpy(a, idx_dtype=np.int8) def test_random_idx_dtype(): with pytest.raises(ValueError): sparse.random((300,), density=0.1, format="coo", idx_dtype=np.int8) def test_html_for_size_zero(): arr = sparse.COO.from_numpy(np.array(())) ground_truth = "" ground_truth += '' ground_truth += '' ground_truth += '' ground_truth += '' ground_truth += '' ground_truth += '' ground_truth += '' ground_truth += '' ground_truth += "
Formatcoo
Data Typefloat64
Shape(0,)
nnz0
Densitynan
Read-onlyTrue
Size0
Storage rationan
" table = html_table(arr) assert table == ground_truth @pytest.mark.parametrize( "pad_width", [ 2, (2, 1), ((2), (1)), ((1, 2), (4, 5), (7, 8)), ], ) @pytest.mark.parametrize("constant_values", [0, 1, 150, np.nan]) def test_pad_valid(pad_width, constant_values): y = sparse.random((50, 50, 3), density=0.15, fill_value=constant_values) x = y.todense() xx = np.pad(x, pad_width=pad_width, constant_values=constant_values) yy = np.pad(y, pad_width=pad_width, constant_values=constant_values) assert_eq(xx, yy) @pytest.mark.parametrize( "pad_width", [ ((2, 1), (5, 7)), ], ) @pytest.mark.parametrize("constant_values", [150, 2, (1, 2)]) def test_pad_invalid(pad_width, constant_values, fill_value=0): y = sparse.random((50, 50, 3), density=0.15) with pytest.raises(ValueError): np.pad(y, pad_width, constant_values=constant_values) @pytest.mark.parametrize("val", [0, 5]) def test_scalar_from_numpy(val): x = np.int64(val) s = sparse.COO.from_numpy(x) assert s.nnz == 0 assert_eq(x, s) def test_scalar_elemwise(rng): s1 = sparse.random((), density=0.5) x2 = rng.random(2) x1 = s1.todense() assert_eq(s1 * x2, x1 * x2) def test_array_as_shape(): coords = [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]] data = [10, 20, 30, 40, 50] sparse.COO(coords, data, shape=np.array((5, 5))) @pytest.mark.parametrize( "arr", [np.array([[0, 3, 0], [1, 2, 0]]), np.array([[[0, 0], [1, 0]], [[5, 0], [0, -3]]])], ) @pytest.mark.parametrize("axis", [None, 0, 1]) @pytest.mark.parametrize("keepdims", [True, False]) @pytest.mark.parametrize("mode", [(sparse.argmax, np.argmax), (sparse.argmin, np.argmin)]) def test_argmax_argmin(arr, axis, keepdims, mode): sparse_func, np_func = mode s_arr = sparse.COO.from_numpy(arr) result = sparse_func(s_arr, axis=axis, keepdims=keepdims).todense() expected = np_func(arr, axis=axis, keepdims=keepdims) np.testing.assert_equal(result, expected) @pytest.mark.parametrize("axis", [None, 0, 1, 2]) @pytest.mark.parametrize("mode", [(sparse.argmax, np.argmax), (sparse.argmin, np.argmin)]) def test_argmax_argmin_3D(axis, mode): sparse_func, np_func = mode s_arr = sparse.zeros(shape=(1000, 550, 3), format="dok") s_arr[100, 100, 0] = 3 s_arr[100, 100, 1] = 3 s_arr[100, 99, 0] = -2 s_arr = s_arr.to_coo() result = sparse_func(s_arr, axis=axis).todense() expected = np_func(s_arr.todense(), axis=axis) np.testing.assert_equal(result, expected) @pytest.mark.parametrize("func", [sparse.argmax, sparse.argmin]) def test_argmax_argmin_constraint(func): s = sparse.COO.from_numpy(np.full((2, 2), 2), fill_value=2) with pytest.raises(ValueError, match="`axis=2` is out of bounds for array of dimension 2."): func(s, axis=2) @pytest.mark.parametrize("config", [(np.inf, "isinf"), (np.nan, "isnan")]) def test_isinf_isnan(config): obj, func_name = config arr = np.array([[1, 1, obj], [-obj, 1, 1]]) s = sparse.COO.from_numpy(arr) result = getattr(s, func_name)().todense() expected = getattr(np, func_name)(arr) np.testing.assert_equal(result, expected) class TestSqueeze: eye_arr = np.eye(2).reshape(1, 2, 1, 2) @pytest.mark.parametrize( "arr_and_axis", [ (eye_arr, None), (eye_arr, 0), (eye_arr, 2), (eye_arr, (0, 2)), (np.zeros((5,)), None), ], ) def test_squeeze(self, arr_and_axis): arr, axis = arr_and_axis s_arr = sparse.COO.from_numpy(arr) result_1 = sparse.squeeze(s_arr, axis=axis).todense() result_2 = s_arr.squeeze(axis=axis).todense() expected = np.squeeze(arr, axis=axis) np.testing.assert_equal(result_1, result_2) np.testing.assert_equal(result_1, expected) def test_squeeze_validation(self): s_arr = sparse.COO.from_numpy(np.eye(3)) with pytest.raises(IndexError, match="tuple index out of range"): s_arr.squeeze(3) with pytest.raises(ValueError, match="Invalid axis parameter: `1.1`."): s_arr.squeeze(1.1) with pytest.raises(ValueError, match="Specified axis `0` has a size greater than one: 3"): s_arr.squeeze(0) class TestUnique: arr = np.array([[0, 0, 1, 5, 3, 0], [1, 0, 4, 0, 3, 0], [0, 1, 0, 1, 1, 0]], dtype=np.int64) arr_empty = np.zeros((5, 5)) arr_full = np.arange(1, 10) @pytest.mark.parametrize("arr", [arr, arr_empty, arr_full]) @pytest.mark.parametrize("fill_value", [-1, 0, 1]) def test_unique_counts(self, arr, fill_value): s_arr = sparse.COO.from_numpy(arr, fill_value) result_values, result_counts = sparse.unique_counts(s_arr) expected_values, expected_counts = np.unique(arr, return_counts=True) np.testing.assert_equal(result_values, expected_values) np.testing.assert_equal(result_counts, expected_counts) @pytest.mark.parametrize("arr", [arr, arr_empty, arr_full]) @pytest.mark.parametrize("fill_value", [-1, 0, 1]) def test_unique_values(self, arr, fill_value): s_arr = sparse.COO.from_numpy(arr, fill_value) result = sparse.unique_values(s_arr) expected = np.unique(arr) np.testing.assert_equal(result, expected) @pytest.mark.parametrize("func", [sparse.unique_counts, sparse.unique_values]) def test_input_validation(self, func): with pytest.raises(ValueError, match="Input must be an instance of SparseArray"): func(self.arr) @pytest.mark.parametrize("axis", [-1, 0, 1, 2, 3]) def test_expand_dims(axis): arr = np.arange(24).reshape((2, 3, 4)) s_arr = sparse.COO.from_numpy(arr) result = sparse.expand_dims(s_arr, axis=axis) expected = np.expand_dims(arr, axis=axis) np.testing.assert_equal(result.todense(), expected) @pytest.mark.parametrize( "arr", [ np.array([[0, 0, 1, 5, 3, 0], [1, 0, 4, 0, 3, 0], [0, 1, 0, 1, 1, 0]], dtype=np.int64), np.array([[[2, 0], [0, 5]], [[1, 0], [4, 0]], [[0, 1], [0, -1]]], dtype=np.float64), np.arange(3, 10), ], ) @pytest.mark.parametrize("fill_value", [-1, 0, 1, 3]) @pytest.mark.parametrize("axis", [0, 1, -1]) @pytest.mark.parametrize("descending", [False, True]) @pytest.mark.parametrize( "stable", [False, pytest.param(True, marks=pytest.mark.xfail(reason="Numba doesn't support `stable=True`."))] ) def test_sort(arr, fill_value, axis, descending, stable): if axis >= arr.ndim: return s_arr = sparse.COO.from_numpy(arr, fill_value) kind = "mergesort" if stable else "quicksort" result = sparse.sort(s_arr, axis=axis, descending=descending, stable=stable) expected = -np.sort(-arr, axis=axis, kind=kind) if descending else np.sort(arr, axis=axis, kind=kind) np.testing.assert_equal(result.todense(), expected) # make sure no inplace changes happened np.testing.assert_equal(s_arr.todense(), arr) @pytest.mark.parametrize("fill_value", [-1, 0, 1]) @pytest.mark.parametrize("descending", [False, True]) def test_sort_only_fill_value(fill_value, descending): arr = np.full((3, 3), fill_value=fill_value) s_arr = sparse.COO.from_numpy(arr, fill_value) result = sparse.sort(s_arr, axis=0, descending=descending) expected = np.sort(arr, axis=0) np.testing.assert_equal(result.todense(), expected) @pytest.mark.parametrize("axis", [None, -1, 0, 1, 2, (0, 1), (2, 0)]) def test_flip(axis): arr = np.arange(24).reshape((2, 3, 4)) s_arr = sparse.COO.from_numpy(arr) result = sparse.flip(s_arr, axis=axis) expected = np.flip(arr, axis=axis) np.testing.assert_equal(result.todense(), expected) @pytest.mark.parametrize("fill_value", [-1, 0, 1, 3]) @pytest.mark.parametrize( "indices,axis", [ ( [1], 0, ), ([2, 1], 1), ([1, 2, 3], 2), ([2, 3], -1), ([5, 3, 7, 8], None), ], ) def test_take(fill_value, indices, axis): arr = np.arange(24).reshape((2, 3, 4)) s_arr = sparse.COO.from_numpy(arr, fill_value) result = sparse.take(s_arr, np.array(indices), axis=axis) expected = np.take(arr, indices, axis) np.testing.assert_equal(result.todense(), expected) @pytest.mark.parametrize("ndim", [2, 3, 4, 5]) @pytest.mark.parametrize("density", [0.0, 0.1, 0.25, 1.0]) def test_matrix_transpose(ndim, density): shape = tuple(range(2, 34)[:ndim]) xs = sparse.random(shape, density=density) xd = xs.todense() transpose_axes = list(range(ndim)) transpose_axes[-2:] = transpose_axes[-2:][::-1] expected = np.transpose(xd, axes=transpose_axes) actual = sparse.matrix_transpose(xs) assert_eq(actual, expected) assert_eq(xs.mT, expected) @pytest.mark.parametrize( ("shape1", "shape2", "axis"), [ ((2, 3, 4), (3, 4), -2), ((3, 4), (2, 3, 4), -1), ((3, 1, 4), (3, 2, 4), 2), ((1, 3, 4), (3, 4), -2), ((3, 4, 1), (3, 4, 2), 0), ((3, 1), (3, 4), -2), ((1, 4), (3, 4), 1), ], ) @pytest.mark.parametrize("density", [0.0, 0.1, 0.25, 1.0]) @pytest.mark.parametrize("is_complex", [False, True]) def test_vecdot(shape1, shape2, axis, density, rng, is_complex): def data_rvs(size): data = rng.random(size) if is_complex: data = data + rng.random(size) * 1j return data s1 = sparse.random(shape1, density=density, data_rvs=data_rvs) s2 = sparse.random(shape2, density=density, data_rvs=data_rvs) x1 = s1.todense() x2 = s2.todense() def np_vecdot(x1, x2, /, *, axis=-1): if np.issubdtype(x1.dtype, np.complexfloating): x1 = np.conjugate(x1) return np.sum(x1 * x2, axis=axis) actual = sparse.vecdot(s1, s2, axis=axis) assert s1.dtype == s2.dtype == actual.dtype expected = np_vecdot(x1, x2, axis=axis) np.testing.assert_allclose(actual.todense(), expected) @pytest.mark.parametrize( ("shape1", "shape2", "axis"), [ ((2, 3, 4), (3, 4), 0), ((3, 4), (2, 3, 4), 0), ((3, 1, 4), (3, 2, 4), -2), ((1, 3, 4), (3, 4), -3), ((3, 4, 1), (3, 4, 2), -1), ((3, 1), (3, 4), 1), ((1, 4), (3, 4), -2), ], ) def test_vecdot_invalid_axis(shape1, shape2, axis): s1 = sparse.random(shape1, density=0.5) s2 = sparse.random(shape2, density=0.5) with pytest.raises(ValueError, match=r"Shapes must match along"): sparse.vecdot(s1, s2, axis=axis) @pytest.mark.parametrize( ("func", "args", "kwargs"), [ (sparse.eye, (5,), {}), (sparse.zeros, ((5,)), {}), (sparse.ones, ((5,)), {}), (sparse.full, ((5,), 5), {}), (sparse.empty, ((5,)), {}), (sparse.full_like, (5,), {}), (sparse.ones_like, (), {}), (sparse.zeros_like, (), {}), (sparse.empty_like, (), {}), (sparse.asarray, (), {}), ], ) def test_invalid_device(func, args, kwargs): if func.__name__.endswith("_like") or func is sparse.asarray: like = sparse.random((5, 5), density=0.5) args = (like,) + args with pytest.raises(ValueError, match="Device must be"): func(*args, device="invalid_device", **kwargs) def test_device(): s = sparse.random((5, 5), density=0.5) data = getattr(s, "data", None) device = getattr(data, "device", "cpu") assert s.device == device def test_to_device(): s = sparse.random((5, 5), density=0.5) s2 = s.to_device(s.device) assert s is s2 def test_to_invalid_device(): s = sparse.random((5, 5), density=0.5) with pytest.raises(ValueError, match=r"Only .* is supported."): s.to_device("invalid_device") # regression test for gh-877 def test_check_zero_fill_value(): a = sparse.zeros((1, 0)) b = a - sparse.mean(a, axis=1) b @ b.T # should not raise an error with pytest.raises(ValueError, match="This operation requires zero fill values"): s1 = sparse.random((10,), density=0.5, fill_value=1.0) check_zero_fill_value(s1) # regression test for gh-869 def test_xH_x(): Y = np.array([[0, -1j], [+1j, 0]]) Ysp = COO.from_numpy(Y) assert_eq(Ysp.conj().T @ Y, Y.conj().T @ Y) assert_eq(Ysp.conj().T @ Ysp, Y.conj().T @ Y) assert_eq(Y.conj().T @ Ysp.conj().T, Y.conj().T @ Y.conj().T) def test_repeat_invalid_input(): a = np.eye(3) with pytest.raises(TypeError, match="`a` must be a SparseArray"): sparse.repeat(a, repeats=2) with pytest.raises(ValueError, match="`repeats` must be an integer"): sparse.repeat(COO.from_numpy(a), repeats=[2, 2, 2]) @pytest.mark.parametrize("ndim", range(1, 5)) @pytest.mark.parametrize("repeats", [1, 2, 3]) def test_repeat(ndim, repeats): rng = np.random.default_rng() shape = tuple(rng.integers(1, 4) for _ in range(ndim)) a = rng.integers(1, 10, size=shape) sparse_a = COO.from_numpy(a) for axis in [*range(-ndim, ndim), None]: expected = np.repeat(a, repeats=repeats, axis=axis) result_sparse = sparse.repeat(sparse_a, repeats=repeats, axis=axis) actual = result_sparse.todense() assert actual.shape == expected.shape, f"Shape mismatch on axis {axis}: {actual.shape} vs {expected.shape}" np.testing.assert_array_equal(actual, expected) expected = np.repeat(a, repeats=repeats, axis=None) result_sparse = sparse.repeat(sparse_a, repeats=repeats, axis=None) actual = result_sparse.todense() print(f"Expected: {expected}, Actual: {actual}") assert actual.shape == expected.shape np.testing.assert_array_equal(actual, expected) def test_tile_invalid_input(): a = np.eye(3) assert isinstance(sparse.tile(a, 2), sparse.COO) @pytest.mark.parametrize( "arr,reps", [ (np.array([1, 2, 3]), (3,)), (np.array([4, 5, 6, 7]), 3), (np.array(1), 3), (np.array([[1, 2], [3, 4]]), (2, 2)), (np.array([[[1], [2]], [[3], [4]]]), (2, 1, 2)), (np.random.default_rng(0).integers(0, 10, (2, 1, 3)), (2, 2, 2)), (np.random.default_rng(1).integers(0, 5, (1, 3, 1, 2)), (2, 1, 3, 1)), ], ) def test_tile(arr, reps): sparse_arr = sparse.COO.from_numpy(arr) expected = np.tile(arr, reps) result = sparse.tile(sparse_arr, reps).todense() np.testing.assert_array_equal(result, expected, err_msg=f"Mismatch for shape={arr.shape}, reps={reps}") @pytest.mark.parametrize("ndim", range(1, 5)) @pytest.mark.parametrize("shape_range", [3]) def test_unstack_matches_numpy(ndim, shape_range): rng = np.random.default_rng(42) shape = tuple(rng.integers(2, shape_range + 2) for _ in range(ndim)) a = rng.integers(0, 10, size=shape) sparse_a = COO.from_numpy(a) for axis in range(-ndim, ndim): sparse_parts = sparse.unstack(sparse_a, axis=axis) np_parts = np.moveaxis(a, axis, 0) assert len(sparse_parts) == np_parts.shape[0], f"Wrong number of slices on axis {axis}" for i, part in enumerate(sparse_parts): expected = np_parts[i] if isinstance(part, COO): actual = part.todense() elif np.isscalar(part): actual = np.array(part) else: raise TypeError(f"Unexpected type returned from unstack: {type(part)}") np.testing.assert_array_equal(actual, expected, err_msg=f"Mismatch at slice {i} on axis {axis}") @pytest.mark.parametrize("axis", [-10, 10, 100, -100]) def test_unstack_invalid_axis(axis): a = COO.from_numpy(np.arange(6).reshape(2, 3)) with pytest.raises(ValueError, match="axis must be in range"): sparse.unstack(a, axis) def test_unstack_invalid_type(): a = np.arange(6).reshape(2, 3) # not a sparse array with pytest.raises(TypeError, match="must be a SparseArray"): sparse.unstack(a, axis=0) @pytest.mark.parametrize("ndim", range(1, 4)) @pytest.mark.parametrize("shape_range", [3]) @pytest.mark.parametrize("n", [1, 2]) @pytest.mark.parametrize("use_prepend, use_append", [(False, False), (True, False), (False, True), (True, True)]) def test_diff_matches_numpy(ndim, shape_range, n, use_prepend, use_append): rng = np.random.default_rng(42) shape = tuple(rng.integers(2, shape_range + 2) for _ in range(ndim)) x = rng.integers(0, 10, size=shape) sparse_x = COO.from_numpy(x) for axis in range(-ndim, ndim): prepend = rng.integers(0, 10, size=x.shape).astype(x.dtype) if use_prepend else None append = rng.integers(0, 10, size=x.shape).astype(x.dtype) if use_append else None sparse_prepend = COO.from_numpy(prepend) if prepend is not None else None sparse_append = COO.from_numpy(append) if append is not None else None sparse_result = sparse.diff(sparse_x, axis=axis, n=n, prepend=sparse_prepend, append=sparse_append) kwargs = {} if prepend is not None: kwargs["prepend"] = prepend if append is not None: kwargs["append"] = append dense_result = np.diff(x, axis=axis, n=n, **kwargs) np.testing.assert_array_equal( sparse_result.todense(), dense_result, err_msg=f"Mismatch at axis={axis}, n={n}, prepend={use_prepend}, append={use_append}", ) def test_diff_invalid_type(): a = np.arange(6).reshape(2, 3) with pytest.raises(TypeError, match="must be a SparseArray"): sparse.diff(a) class TestInterp: xp = [-1, 0, 1] fp = [3, 2, 0] @pytest.fixture(params=["coo", "dok", "gcxs", "dense"]) def x(self, request): arr = sparse.random((10, 10, 10), fill_value=0) if request.param == "dense": return arr.todense() return arr.asformat(request.param) @pytest.mark.parametrize( "xp", [ xp, sparse.COO.from_numpy(np.array(xp)), ], ) @pytest.mark.parametrize( "fp", [ fp, sparse.COO.from_numpy(np.array(fp)), sparse.COO.from_numpy(np.array(fp) + 1j), ], ) def test_interp(self, x, xp, fp): def to_dense(arr): if isinstance(x, sparse.SparseArray): return arr.todense() return arr actual = sparse.interp(x, xp, fp) expected = np.interp(to_dense(x), xp, fp) assert isinstance(actual, type(x)) if isinstance(x, sparse.SparseArray): assert actual.fill_value == fp[1] np.testing.assert_array_equal(to_dense(actual), expected) sparse-0.18.0/sparse/numba_backend/tests/test_coo_numba.py000066400000000000000000000033301514474157100236700ustar00rootroot00000000000000import sparse import numba import numpy as np @numba.njit def identity(x): """Pass an object through numba and back""" return x def identity_constant(x): @numba.njit def get_it(): """Pass an object through numba and back as a constant""" return x return get_it() def assert_coo_equal(c1, c2): assert c1.shape == c2.shape assert sparse.all(c1 == c2) assert c1.data.dtype == c2.data.dtype assert c1.fill_value == c2.fill_value def assert_coo_same_memory(c1, c2): assert_coo_equal(c1, c2) assert c1.coords.data == c2.coords.data assert c1.data.data == c2.data.data class TestBasic: """Test very simple construction and field access""" def test_roundtrip(self): c1 = sparse.COO(np.eye(3), fill_value=1) c2 = identity(c1) assert type(c1) is type(c2) assert_coo_same_memory(c1, c2) def test_roundtrip_constant(self): c1 = sparse.COO(np.eye(3), fill_value=1) c2 = identity_constant(c1) # constants are always copies assert_coo_equal(c1, c2) def test_unpack_attrs(self): @numba.njit def unpack(c): return c.coords, c.data, c.shape, c.fill_value c1 = sparse.COO(np.eye(3), fill_value=1) coords, data, shape, fill_value = unpack(c1) c2 = sparse.COO(coords, data, shape, fill_value=fill_value) assert_coo_same_memory(c1, c2) def test_repack_attrs(self): @numba.njit def pack(coords, data, shape): return sparse.COO(coords, data, shape) # repacking fill_value isn't possible yet c1 = sparse.COO(np.eye(3)) c2 = pack(c1.coords, c1.data, c1.shape) assert_coo_same_memory(c1, c2) sparse-0.18.0/sparse/numba_backend/tests/test_dask_interop.py000066400000000000000000000006371514474157100244170ustar00rootroot00000000000000import sparse from dask.base import tokenize def test_deterministic_token(): a = sparse.COO(data=[1, 2, 3], coords=[10, 20, 30], shape=(40,)) b = sparse.COO(data=[1, 2, 3], coords=[10, 20, 30], shape=(40,)) assert tokenize(a) == tokenize(b) # One of these things is not like the other.... c = sparse.COO(data=[1, 2, 4], coords=[10, 20, 30], shape=(40,)) assert tokenize(a) != tokenize(c) sparse-0.18.0/sparse/numba_backend/tests/test_dok.py000066400000000000000000000176031514474157100225130ustar00rootroot00000000000000import sparse from sparse import DOK from sparse.numba_backend._utils import assert_eq import pytest import numpy as np @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4)]) @pytest.mark.parametrize("density", [0.1, 0.3, 0.5, 0.7]) def test_random_shape_nnz(shape, density): s = sparse.random(shape, density, format="dok") assert isinstance(s, DOK) assert s.shape == shape expected_nnz = density * np.prod(shape) assert np.floor(expected_nnz) <= s.nnz <= np.ceil(expected_nnz) def test_convert_to_coo(): s1 = sparse.random((2, 3, 4), 0.5, format="dok") s2 = sparse.COO(s1) assert_eq(s1, s2) def test_convert_from_coo(): s1 = sparse.random((2, 3, 4), 0.5, format="coo") s2 = DOK(s1) assert_eq(s1, s2) def test_convert_from_numpy(rng): x = rng.random((2, 3, 4)) s = DOK(x) assert_eq(x, s) def test_convert_to_numpy(): s = sparse.random((2, 3, 4), 0.5, format="dok") x = s.todense() assert_eq(x, s) def test_convert_from_scipy_sparse(): import scipy.sparse x = scipy.sparse.rand(6, 3, density=0.2) s = DOK(x) assert_eq(x, s) @pytest.mark.parametrize( "shape, data", [ (2, {0: 1}), ((2, 3), {(0, 1): 3, (1, 2): 4}), ((2, 3, 4), {(0, 1): 3, (1, 2, 3): 4, (1, 1): [6, 5, 4, 1]}), ], ) def test_construct(shape, data): s = DOK(shape, data) x = np.zeros(shape, dtype=s.dtype) for c, d in data.items(): x[c] = d assert_eq(x, s) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4)]) @pytest.mark.parametrize("density", [0.1, 0.3, 0.5, 0.7]) def test_getitem_single(shape, density, rng): s = sparse.random(shape, density, format="dok") x = s.todense() for _ in range(s.nnz): idx = rng.integers(np.prod(shape)) idx = np.unravel_index(idx, shape) assert np.isclose(s[idx], x[idx]) @pytest.mark.parametrize( "shape, density, indices", [ ((2, 3), 0.5, (slice(1),)), ((5, 5), 0.2, (slice(0, 4, 2),)), ((10, 10), 0.2, (slice(5), slice(0, 10, 3))), ((5, 5), 0.5, (slice(0, 4, 4), slice(0, 4, 4))), ((5, 5), 0.4, (1, slice(0, 4, 1))), ((10, 10), 0.8, ([0, 4, 5], [3, 2, 4])), ((10, 10), 0, (slice(10), slice(10))), ], ) def test_getitem(shape, density, indices): s = sparse.random(shape, density, format="dok") x = s.todense() sparse_sliced = s[indices] dense_sliced = x[indices] assert_eq(sparse_sliced.todense(), dense_sliced) @pytest.mark.parametrize( "shape, density, indices", [ ((10, 10), 0.8, ([0, 4, 5],)), ((5, 5, 5), 0.5, ([1, 2, 3], [0, 2, 2])), ], ) def test_getitem_notimplemented_error(shape, density, indices): s = sparse.random(shape, density, format="dok") with pytest.raises(NotImplementedError): s[indices] @pytest.mark.parametrize( "shape, density, indices", [ ((10, 10), 0.8, ([0, 4, 5], [0, 2])), ((5, 5, 5), 0.5, ([1, 2, 3], [0], [2, 3, 4])), ((10,), 0.5, (5, 6)), ], ) def test_getitem_index_error(shape, density, indices): s = sparse.random(shape, density, format="dok") with pytest.raises(IndexError): s[indices] @pytest.mark.parametrize( "shape, index, value_shape", [ ((2,), slice(None), ()), ((2,), slice(1, 2), ()), ((2,), slice(0, 2), (2,)), ((2,), 1, ()), ((2, 3), (0, slice(None)), ()), ((2, 3), (0, slice(1, 3)), ()), ((2, 3), (1, slice(None)), (3,)), ((2, 3), (0, slice(1, 3)), (2,)), ((2, 3), (0, slice(2, 0, -1)), (2,)), ((2, 3), (slice(None), 1), ()), ((2, 3), (slice(None), 1), (2,)), ((2, 3), (slice(1, 2), 1), ()), ((2, 3), (slice(1, 2), 1), (1,)), ((2, 3), (0, 2), ()), ((2, 3), ([0, 1], [1, 2]), (2,)), ((2, 3), ([0, 1], [1, 2]), ()), ((4,), ([1, 3]), ()), ], ) def test_setitem(shape, index, value_shape, rng): s = sparse.random(shape, 0.5, format="dok") x = s.todense() value = rng.random(value_shape) s[index] = value x[index] = value assert_eq(x, s) def test_setitem_delete(): shape = (2, 3) index = [0, 1], [1, 2] value = 0 s = sparse.random(shape, 1.0, format="dok") x = s.todense() s[index] = value x[index] = value assert_eq(x, s) assert s.nnz < s.size @pytest.mark.parametrize( "shape, index, value_shape", [ ((2, 3), ([0, 1.5], [1, 2]), ()), ((2, 3), ([0, 1], [1]), ()), ((2, 3), ([[0], [1]], [1, 2]), ()), ], ) def test_setitem_index_error(shape, index, value_shape, rng): s = sparse.random(shape, 0.5, format="dok") value = rng.random(value_shape) with pytest.raises(IndexError): s[index] = value @pytest.mark.parametrize( "shape, index, value_shape", [ ((2, 3), ([0, 1],), ()), ], ) def test_setitem_notimplemented_error(shape, index, value_shape, rng): s = sparse.random(shape, 0.5, format="dok") value = rng.random(value_shape) with pytest.raises(NotImplementedError): s[index] = value @pytest.mark.parametrize( "shape, index, value_shape", [ ((2, 3), ([0, 1], [1, 2]), (1, 2)), ((2, 3), ([0, 1], [1, 2]), (3,)), ((2,), 1, (2,)), ], ) def test_setitem_value_error(shape, index, value_shape, rng): s = sparse.random(shape, 0.5, format="dok") value = rng.random(value_shape) with pytest.raises(ValueError): s[index] = value def test_default_dtype(): s = DOK((5,)) assert s.dtype == np.float64 def test_int_dtype(): data = {1: np.uint8(1), 2: np.uint16(2)} s = DOK((5,), data) assert s.dtype == np.uint16 def test_float_dtype(): data = {1: np.uint8(1), 2: np.float32(2)} s = DOK((5,), data) assert s.dtype == np.float32 def test_set_zero(): s = DOK((1,), dtype=np.uint8) s[0] = 1 s[0] = 0 assert s[0] == 0 assert s.nnz == 0 @pytest.mark.parametrize("format", ["coo", "dok"]) def test_asformat(format): s = sparse.random((2, 3, 4), density=0.5, format="dok") s2 = s.asformat(format) assert_eq(s, s2) def test_coo_fv_interface(rng): s1 = sparse.full((5, 5), fill_value=1 + rng.random()) s2 = sparse.DOK(s1) assert_eq(s1, s2) s3 = sparse.COO(s2) assert_eq(s1, s3) def test_empty_dok_dtype(): d = sparse.DOK(5, dtype=np.uint8) s = sparse.COO(d) assert s.dtype == d.dtype def test_zeros_like(): s = sparse.random((2, 3, 4), density=0.5) s2 = sparse.zeros_like(s, format="dok") assert s.shape == s2.shape assert s.dtype == s2.dtype assert isinstance(s2, sparse.DOK) @pytest.mark.parametrize( "pad_width", [ 2, (2, 1), ((2), (1)), ((1, 2), (4, 5), (7, 8)), ], ) @pytest.mark.parametrize("constant_values", [0, 1, 150, np.nan]) def test_pad_valid(pad_width, constant_values): y = sparse.random((50, 50, 3), density=0.15, fill_value=constant_values, format="dok") x = y.todense() xx = np.pad(x, pad_width=pad_width, constant_values=constant_values) yy = np.pad(y, pad_width=pad_width, constant_values=constant_values) assert_eq(xx, yy) @pytest.mark.parametrize( "pad_width", [ ((2, 1), (5, 7)), ], ) @pytest.mark.parametrize("constant_values", [150, 2, (1, 2)]) def test_pad_invalid(pad_width, constant_values, fill_value=0): y = sparse.random((50, 50, 3), density=0.15, format="dok") with pytest.raises(ValueError): np.pad(y, pad_width, constant_values=constant_values) @pytest.mark.parametrize("func", [np.concatenate, np.stack]) def test_dok_concat_stack(func): s1 = sparse.random((4, 4), density=0.25, format="dok") s2 = sparse.random((4, 4), density=0.25, format="dok") x1 = s1.todense() x2 = s2.todense() assert_eq(func([s1, s2]), func([x1, x2])) def test_dok_indexing(): s = sparse.DOK((3, 3)) s[1, 2] = 0.5 x = s.todense() assert_eq(x[1::-1], s[1::-1]) sparse-0.18.0/sparse/numba_backend/tests/test_dot.py000066400000000000000000000253641514474157100225270ustar00rootroot00000000000000import operator import sparse from sparse import COO from sparse.numba_backend._compressed import GCXS from sparse.numba_backend._utils import assert_eq, assert_gcxs_slicing, default_rng import pytest import numpy as np import scipy.sparse import scipy.stats @pytest.mark.parametrize( "a_shape,b_shape,axes", [ [(3, 4), (4, 3), (1, 0)], [(3, 4), (4, 3), (0, 1)], [(3, 4, 5), (4, 3), (1, 0)], [(3, 4), (5, 4, 3), (1, 1)], [(3, 4), (5, 4, 3), ((0, 1), (2, 1))], [(3, 4), (5, 4, 3), ((1, 0), (1, 2))], [(3, 4, 5), (4,), (1, 0)], [(4,), (3, 4, 5), (0, 1)], [(4,), (4,), (0, 0)], [(4,), (4,), 0], ], ) @pytest.mark.parametrize( "a_format, b_format", [("coo", "coo"), ("coo", "gcxs"), ("gcxs", "coo"), ("gcxs", "gcxs")], ) def test_tensordot(a_shape, b_shape, axes, a_format, b_format): sa = sparse.random(a_shape, density=0.5, format=a_format) sb = sparse.random(b_shape, density=0.5, format=b_format) a = sa.todense() b = sb.todense() a_b = np.tensordot(a, b, axes) # tests for return_type=None sa_sb = sparse.tensordot(sa, sb, axes) sa_b = sparse.tensordot(sa, b, axes) a_sb = sparse.tensordot(a, sb, axes) assert_eq(a_b, sa_sb) assert_eq(a_b, sa_b) assert_eq(a_b, a_sb) if all(isinstance(arr, COO) for arr in [sa, sb]): assert isinstance(sa_sb, COO) else: assert isinstance(sa_sb, GCXS) assert isinstance(sa_b, np.ndarray) assert isinstance(a_sb, np.ndarray) # tests for return_type=COO sa_b = sparse.tensordot(sa, b, axes, return_type=COO) a_sb = sparse.tensordot(a, sb, axes, return_type=COO) assert_eq(a_b, sa_b) assert_eq(a_b, a_sb) assert isinstance(sa_b, COO) assert isinstance(a_sb, COO) # tests form return_type=GCXS sa_b = sparse.tensordot(sa, b, axes, return_type=GCXS) a_sb = sparse.tensordot(a, sb, axes, return_type=GCXS) assert_eq(a_b, sa_b) assert_eq(a_b, a_sb) assert isinstance(sa_b, GCXS) assert isinstance(a_sb, GCXS) # tests for return_type=np.ndarray sa_sb = sparse.tensordot(sa, sb, axes, return_type=np.ndarray) assert_eq(a_b, sa_sb) assert isinstance(sa_sb, np.ndarray) def test_tensordot_empty(): x1 = np.empty((0, 0, 0)) x2 = np.empty((0, 0, 0)) s1 = sparse.COO.from_numpy(x1) s2 = sparse.COO.from_numpy(x2) assert_eq(np.tensordot(x1, x2), sparse.tensordot(s1, s2)) def test_tensordot_valueerror(): x1 = sparse.COO(np.array(1)) x2 = sparse.COO(np.array(1)) with pytest.raises(ValueError): x1 @ x2 def gen_kwargs(format): from sparse.numba_backend._utils import convert_format format = convert_format(format) if format == "gcxs": return [{"compressed_axes": c} for c in [(0,), (1,)]] return [{}] def gen_for_format(format): return [(format, g) for g in gen_kwargs(format)] @pytest.mark.parametrize( "a_shape, b_shape", [ ((3, 1, 6, 5), (2, 1, 4, 5, 6)), ((2, 1, 4, 5, 6), (3, 1, 6, 5)), ((1, 1, 5), (3, 5, 6)), ((3, 4, 5), (1, 5, 6)), ((3, 4, 5), (3, 5, 6)), ((3, 4, 5), (5, 6)), ((4, 5), (5, 6)), ((5,), (5, 6)), ((4, 5), (5,)), ((5,), (5,)), ((3, 4), (1, 2, 4, 3)), ], ) @pytest.mark.parametrize( "a_format, a_kwargs", [*gen_for_format("coo"), *gen_for_format("gcxs")], ) @pytest.mark.parametrize( "b_format, b_kwargs", [*gen_for_format("coo"), *gen_for_format("gcxs")], ) def test_matmul(a_shape, b_shape, a_format, b_format, a_kwargs, b_kwargs): if len(a_shape) == 1: a_kwargs = {} if len(b_shape) == 1: b_kwargs = {} sa = sparse.random(a_shape, density=0.5, format=a_format, **a_kwargs) sb = sparse.random(b_shape, density=0.5, format=b_format, **b_kwargs) a = sa.todense() b = sb.todense() assert_eq(np.matmul(a, b), sparse.matmul(sa, sb)) assert_eq(sparse.matmul(sa, b), sparse.matmul(a, sb)) assert_eq(np.matmul(a, b), sparse.matmul(sa, sb)) if a.ndim == 2 or b.ndim == 2: assert_eq( np.matmul(a, b), sparse.matmul( scipy.sparse.coo_array(a) if a.ndim == 2 else sa, scipy.sparse.coo_array(b) if b.ndim == 2 else sb, ), ) if hasattr(operator, "matmul"): assert_eq(operator.matmul(a, b), operator.matmul(sa, sb)) def test_matmul_errors(): with pytest.raises(ValueError): sa = sparse.random((3, 4, 5, 6), 0.5) sb = sparse.random((3, 6, 5, 6), 0.5) sparse.matmul(sa, sb) @pytest.mark.parametrize( "a, b", [ ( sparse.GCXS.from_numpy(default_rng.choice([0, np.nan, 2], size=[100, 100], p=[0.99, 0.001, 0.009])), sparse.random((100, 100), density=0.01), ), ( sparse.COO.from_numpy(default_rng.choice([0, np.nan, 2], size=[100, 100], p=[0.99, 0.001, 0.009])), sparse.random((100, 100), density=0.01), ), ( sparse.GCXS.from_numpy(default_rng.choice([0, np.nan, 2], size=[100, 100], p=[0.99, 0.001, 0.009])), scipy.sparse.random(100, 100), ), ( default_rng.choice([0, np.nan, 2], size=[100, 100], p=[0.99, 0.001, 0.009]), sparse.random((100, 100), density=0.01), ), ], ) def test_matmul_nan_warnings(a, b): with pytest.warns(RuntimeWarning): a @ b @pytest.mark.parametrize( "a_shape, b_shape", [ ((1, 4, 5), (3, 5, 6)), ((3, 4, 5), (1, 5, 6)), ((3, 4, 5), (3, 5, 6)), ((3, 4, 5), (5, 6)), ((4, 5), (5, 6)), ((5,), (5, 6)), ((4, 5), (5,)), ((5,), (5,)), ], ) @pytest.mark.parametrize( "a_format, a_kwargs", [*gen_for_format("coo"), *gen_for_format("gcxs")], ) @pytest.mark.parametrize( "b_format, b_kwargs", [*gen_for_format("coo"), *gen_for_format("gcxs")], ) def test_dot(a_shape, b_shape, a_format, b_format, a_kwargs, b_kwargs): if len(a_shape) == 1: a_kwargs = {} if len(b_shape) == 1: b_kwargs = {} sa = sparse.random(a_shape, density=0.5, format=a_format, **a_kwargs) sb = sparse.random(b_shape, density=0.5, format=b_format, **b_kwargs) a = sa.todense() b = sb.todense() e = np.dot(a, b) assert_eq(e, sa.dot(sb)) assert_eq(e, sparse.dot(sa, sb)) assert_eq(e, sparse.dot(a, sb)) assert_eq(e, sparse.dot(a, sb)) # Basic equivalences e = operator.matmul(a, b) assert_eq(e, operator.matmul(sa, sb)) assert_eq(e, operator.matmul(a, sb)) assert_eq(e, operator.matmul(sa, b)) @pytest.mark.parametrize( "a_dense, b_dense, o_type", [ (False, False, sparse.SparseArray), (False, True, np.ndarray), (True, False, np.ndarray), ], ) def test_dot_type(a_dense, b_dense, o_type): a = sparse.random((3, 4), density=0.8) b = sparse.random((4, 5), density=0.8) if a_dense: a = a.todense() if b_dense: b = b.todense() assert isinstance(sparse.dot(a, b), o_type) @pytest.mark.xfail def test_dot_nocoercion(): sa = sparse.random((3, 4, 5), density=0.5) sb = sparse.random((5, 6), density=0.5) a = sa.todense() b = sb.todense() la = a.tolist() lb = b.tolist() if hasattr(operator, "matmul"): # Operations with naive collection (list) assert_eq(operator.matmul(la, b), operator.matmul(la, sb)) assert_eq(operator.matmul(a, lb), operator.matmul(sa, lb)) dot_formats = [ lambda x: x.asformat("coo"), lambda x: x.asformat("gcxs"), lambda x: x.todense(), ] @pytest.mark.parametrize("format1", dot_formats) @pytest.mark.parametrize("format2", dot_formats) def test_small_values(format1, format2): s1 = format1(sparse.COO(coords=[[0, 10]], data=[3.6e-100, 7.2e-009], shape=(20,))) s2 = format2(sparse.COO(coords=[[0, 0], [4, 28]], data=[3.8e-25, 4.5e-225], shape=(20, 50))) def dense_convertor(x): return x.todense() if isinstance(x, sparse.SparseArray) else x x1, x2 = dense_convertor(s1), dense_convertor(s2) assert_eq(x1 @ x2, s1 @ s2) dot_dtypes = [np.complex64, np.complex128] @pytest.mark.parametrize("dtype1", dot_dtypes) @pytest.mark.parametrize("dtype2", dot_dtypes) @pytest.mark.parametrize("format1", dot_formats) @pytest.mark.parametrize("format2", dot_formats) @pytest.mark.parametrize("ndim1", (1, 2)) @pytest.mark.parametrize("ndim2", (1, 2)) def test_complex(dtype1, dtype2, format1, format2, ndim1, ndim2): s1 = format1(sparse.random((20,) * ndim1, density=0.5).astype(dtype1)) s2 = format2(sparse.random((20,) * ndim2, density=0.5).astype(dtype2)) def dense_convertor(x): return x.todense() if isinstance(x, sparse.SparseArray) else x x1, x2 = dense_convertor(s1), dense_convertor(s2) assert_eq(x1 @ x2, s1 @ s2) @pytest.mark.parametrize("dtype1", dot_dtypes) @pytest.mark.parametrize("dtype2", dot_dtypes) @pytest.mark.parametrize("ndim1", (1, 2)) @pytest.mark.parametrize("ndim2", (1, 2)) def test_dot_dense(dtype1, dtype2, ndim1, ndim2): a = sparse.random((20,) * ndim1, density=0.5).astype(dtype1).todense() b = sparse.random((20,) * ndim2, density=0.5).astype(dtype2).todense() assert_eq(sparse.dot(a, b), np.dot(a, b)) assert_eq(sparse.matmul(a, b), np.matmul(a, b)) if ndim1 == 2 and ndim2 == 2: assert_eq(sparse.tensordot(a, b), np.tensordot(a, b)) @pytest.mark.parametrize( "a_shape, b_shape", [((3, 4, 5), (5, 6)), ((2, 8, 6), (6, 3))], ) def test_dot_GCXS_slicing(a_shape, b_shape): sa = sparse.random(shape=a_shape, density=1, format="gcxs") sb = sparse.random(shape=b_shape, density=1, format="gcxs") a = sa.todense() b = sb.todense() # tests dot sa_sb = sparse.dot(sa, sb) a_b = np.dot(a, b) assert_gcxs_slicing(sa_sb, a_b) @pytest.mark.parametrize( "a_shape,b_shape,axes", [ [(3, 4, 5), (4, 3), (1, 0)], [(3, 4), (5, 4, 3), (1, 1)], [(5, 9), (9, 5, 6), (0, 1)], ], ) def test_tensordot_GCXS_slicing(a_shape, b_shape, axes): sa = sparse.random(shape=a_shape, density=1, format="gcxs") sb = sparse.random(shape=b_shape, density=1, format="gcxs") a = sa.todense() b = sb.todense() sa_sb = sparse.tensordot(sa, sb, axes) a_b = np.tensordot(a, b, axes) assert_gcxs_slicing(sa_sb, a_b) @pytest.mark.parametrize( "a_shape, b_shape", [ [(1, 1, 5), (3, 5, 6)], [(3, 4, 5), (1, 5, 6)], [(3, 4, 5), (3, 5, 6)], [(3, 4, 5), (5, 6)], ], ) def test_matmul_GCXS_slicing(a_shape, b_shape): sa = sparse.random(shape=a_shape, density=1, format="gcxs") sb = sparse.random(shape=b_shape, density=1, format="gcxs") a = sa.todense() b = sb.todense() sa_sb = sparse.matmul(sa, sb) a_b = np.matmul(a, b) assert_gcxs_slicing(sa_sb, a_b) sparse-0.18.0/sparse/numba_backend/tests/test_einsum.py000066400000000000000000000126021514474157100232300ustar00rootroot00000000000000import sparse import pytest import numpy as np einsum_cases = [ "a,->a", "ab,->ab", ",ab,->ab", ",,->", "a,ab,abc->abc", "a,b,ab->ab", "ea,fb,gc,hd,abcd->efgh", "ea,fb,abcd,gc,hd->efgh", "abcd,ea,fb,gc,hd->efgh", "acdf,jbje,gihb,hfac,gfac,gifabc,hfac", "cd,bdhe,aidb,hgca,gc,hgibcd,hgac", "abhe,hidj,jgba,hiab,gab", "bde,cdh,agdb,hica,ibd,hgicd,hiac", "chd,bde,agbc,hiad,hgc,hgi,hiad", "chd,bde,agbc,hiad,bdi,cgh,agdb", "bdhe,acad,hiab,agac,hibd", "ab,ab,c->", "ab,ab,c->c", "ab,ab,cd,cd->", "ab,ab,cd,cd->ac", "ab,ab,cd,cd->cd", "ab,ab,cd,cd,ef,ef->", "ab,cd,ef->abcdef", "ab,cd,ef->acdf", "ab,cd,de->abcde", "ab,cd,de->be", "ab,bcd,cd->abcd", "ab,bcd,cd->abd", "eb,cb,fb->cef", "dd,fb,be,cdb->cef", "bca,cdb,dbf,afc->", "dcc,fce,ea,dbf->ab", "fdf,cdd,ccd,afe->ae", "abcd,ad", "ed,fcd,ff,bcf->be", "baa,dcf,af,cde->be", "bd,db,eac->ace", "fff,fae,bef,def->abd", "efc,dbc,acf,fd->abe", "ab,ab", "ab,ba", "abc,abc", "abc,bac", "abc,cba", "ab,bc", "ab,cb", "ba,bc", "ba,cb", "abcd,cd", "abcd,ab", "abcd,cdef", "abcd,cdef->feba", "abcd,efdc", "aab,bc->ac", "ab,bcc->ac", "aab,bcc->ac", "baa,bcc->ac", "aab,ccb->ac", "aab,fa,df,ecc->bde", "ecb,fef,bad,ed->ac", "bcf,bbb,fbf,fc->", "bb,ff,be->e", "bcb,bb,fc,fff->", "fbb,dfd,fc,fc->", "afd,ba,cc,dc->bf", "adb,bc,fa,cfc->d", "bbd,bda,fc,db->acf", "dba,ead,cad->bce", "aef,fbc,dca->bde", "abab->ba", "...ab,...ab", "...ab,...b->...a", "a...,a...", "a...,a...", ] @pytest.mark.parametrize("subscripts", einsum_cases) @pytest.mark.parametrize("density", [0.1, 1.0]) def test_einsum(subscripts, density): d = 4 terms = subscripts.split("->")[0].split(",") arrays = [sparse.random((d,) * len(term), density=density) for term in terms] sparse_out = sparse.einsum(subscripts, *arrays) numpy_out = np.einsum(subscripts, *(s.todense() for s in arrays)) if not numpy_out.shape: # scalar output assert np.allclose(numpy_out, sparse_out) else: # array output assert np.allclose(numpy_out, sparse_out.todense()) @pytest.mark.parametrize("input", [[[0, 0]], [[0, Ellipsis]], [[Ellipsis, 1], [Ellipsis]], [[0, 1], [0]]]) @pytest.mark.parametrize("density", [0.1, 1.0]) def test_einsum_nosubscript(input, density): d = 4 arrays = [sparse.random((d, d), density=density)] sparse_out = sparse.einsum(*arrays, *input) numpy_out = np.einsum(*(s.todense() for s in arrays), *input) if not numpy_out.shape: # scalar output assert np.allclose(numpy_out, sparse_out) else: # array output assert np.allclose(numpy_out, sparse_out.todense()) def test_einsum_input_fill_value(): x = sparse.random(shape=(2,), density=0.5, format="coo", fill_value=2) with pytest.raises(ValueError): sparse.einsum("cba", x) def test_einsum_no_input(): with pytest.raises(ValueError): sparse.einsum() @pytest.mark.parametrize("subscript", ["a+b->c", "i->&", "i->ij", "ij->jij", "a..,a...", ".i...", "a,a->->"]) def test_einsum_invalid_input(subscript): x = sparse.random(shape=(2,), density=0.5, format="coo") y = sparse.random(shape=(2,), density=0.5, format="coo") with pytest.raises(ValueError): sparse.einsum(subscript, x, y) @pytest.mark.parametrize("subscript", [0, [0, 0]]) def test_einsum_type_error(subscript): x = sparse.random(shape=(2,), density=0.5, format="coo") y = sparse.random(shape=(2,), density=0.5, format="coo") with pytest.raises(TypeError): sparse.einsum(subscript, x, y) format_test_cases = [ (("coo",), "coo"), (("dok",), "dok"), (("gcxs",), "gcxs"), (("dense",), "dense"), (("coo", "coo"), "coo"), (("dok", "coo"), "coo"), (("coo", "dok"), "coo"), (("coo", "dense"), "coo"), (("dense", "coo"), "coo"), (("dok", "dense"), "dok"), (("dense", "dok"), "dok"), (("gcxs", "dense"), "gcxs"), (("dense", "gcxs"), "gcxs"), (("dense", "dense"), "dense"), (("dense", "dok", "gcxs"), "coo"), ] @pytest.mark.parametrize("formats,expected", format_test_cases) def test_einsum_format(formats, expected, rng): inputs = [ rng.standard_normal((2, 2, 2)) if format == "dense" else sparse.random((2, 2, 2), density=0.5, format=format) for format in formats ] if len(inputs) == 1: eq = "abc->bc" elif len(inputs) == 2: eq = "abc,cda->abd" elif len(inputs) == 3: eq = "abc,cad,dea->abe" out = sparse.einsum(eq, *inputs) assert { sparse.COO: "coo", sparse.DOK: "dok", sparse.GCXS: "gcxs", np.ndarray: "dense", }[out.__class__] == expected def test_einsum_shape_check(): x = sparse.random((2, 3, 4), density=0.5) with pytest.raises(ValueError): sparse.einsum("aab", x) y = sparse.random((2, 3, 4), density=0.5) with pytest.raises(ValueError): sparse.einsum("abc,acb", x, y) @pytest.mark.parametrize("dtype", [np.int64, np.complex128]) def test_einsum_dtype(dtype): x = sparse.random((3, 3), density=0.5) * 10.0 x = x.astype(np.float64) y = sparse.COO.from_numpy(np.ones((3, 1), dtype=np.float64)) result = sparse.einsum("ij,i->j", x, y, dtype=dtype) assert result.dtype == dtype sparse-0.18.0/sparse/numba_backend/tests/test_elemwise.py000066400000000000000000000471371514474157100235550ustar00rootroot00000000000000import operator import sparse from sparse import COO, DOK from sparse.numba_backend._compressed import GCXS from sparse.numba_backend._utils import assert_eq, random_value_array import pytest import numpy as np @pytest.mark.parametrize( "func", [ np.expm1, np.log1p, np.sin, np.tan, np.sinh, np.tanh, np.floor, np.ceil, np.sqrt, np.conj, np.round, np.rint, lambda x: x.astype("int32"), np.conjugate, np.conj, lambda x: x.round(decimals=2), abs, ], ) @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_elemwise(func, format): s = sparse.random((2, 3, 4), density=0.5, format=format) x = s.todense() fs = func(s) assert isinstance(fs, format) assert fs.nnz <= s.nnz assert_eq(func(x), fs) @pytest.mark.parametrize( "func", [ np.expm1, np.log1p, np.sin, np.tan, np.sinh, np.tanh, np.floor, np.ceil, np.sqrt, np.conj, np.round, np.rint, np.conjugate, np.conj, lambda x, out: x.round(decimals=2, out=out), ], ) @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_elemwise_inplace(func, format): s = sparse.random((2, 3, 4), density=0.5, format=format) x = s.todense() func(s, out=s) func(x, out=x) assert isinstance(s, format) assert_eq(x, s) @pytest.mark.parametrize( "shape1, shape2", [ ((2, 3, 4), (3, 4)), ((3, 4), (2, 3, 4)), ((3, 1, 4), (3, 2, 4)), ((1, 3, 4), (3, 4)), ((3, 4, 1), (3, 4, 2)), ((1, 5), (5, 1)), ((3, 1), (3, 4)), ((3, 1), (1, 4)), ((1, 4), (3, 4)), ((2, 2, 2), (1, 1, 1)), ], ) @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_elemwise_mixed(shape1, shape2, format, rng): s1 = sparse.random(shape1, density=0.5, format=format) x2 = rng.random(shape2) x1 = s1.todense() assert_eq(s1 * x2, x1 * x2) @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_elemwise_mixed_empty(format, rng): s1 = sparse.random((2, 0, 4), density=0.5, format=format) x2 = rng.random((2, 0, 4)) x1 = s1.todense() assert_eq(s1 * x2, x1 * x2) @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_elemwise_unsupported(format): class A: pass s1 = sparse.random((2, 3, 4), density=0.5, format=format) x2 = A() with pytest.raises(TypeError): s1 + x2 assert sparse.elemwise(operator.add, s1, x2) is NotImplemented @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_elemwise_mixed_broadcast(format, rng): s1 = sparse.random((2, 3, 4), density=0.5, format=format) s2 = sparse.random(4, density=0.5) x3 = rng.random((3, 4)) x1 = s1.todense() x2 = s2.todense() def func(x1, x2, x3): return x1 * x2 * x3 assert_eq(sparse.elemwise(func, s1, s2, x3), func(x1, x2, x3)) @pytest.mark.parametrize( "func", [operator.mul, operator.add, operator.sub, operator.gt, operator.lt, operator.ne], ) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_elemwise_binary(func, shape, format): xs = sparse.random(shape, density=0.5, format=format) ys = sparse.random(shape, density=0.5, format=format) x = xs.todense() y = ys.todense() assert_eq(func(xs, ys), func(x, y)) @pytest.mark.parametrize("func", [operator.imul, operator.iadd, operator.isub]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_elemwise_binary_inplace(func, shape, format): xs = sparse.random(shape, density=0.5, format=format) ys = sparse.random(shape, density=0.5, format=format) x = xs.todense() y = ys.todense() xs = func(xs, ys) x = func(x, y) assert_eq(xs, x) @pytest.mark.parametrize( "func", [ lambda x, y, z: x + y + z, lambda x, y, z: x * y * z, lambda x, y, z: x + y * z, lambda x, y, z: (x + y) * z, ], ) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) @pytest.mark.parametrize( "formats", [ [COO, COO, COO], [GCXS, GCXS, GCXS], [COO, GCXS, GCXS], ], ) def test_elemwise_trinary(func, shape, formats): xs = sparse.random(shape, density=0.5, format=formats[0]) ys = sparse.random(shape, density=0.5, format=formats[1]) zs = sparse.random(shape, density=0.5, format=formats[2]) x = xs.todense() y = ys.todense() z = zs.todense() fs = sparse.elemwise(func, xs, ys, zs) assert_eq(fs, func(x, y, z)) @pytest.mark.parametrize("func", [operator.add, operator.mul]) @pytest.mark.parametrize( "shape1,shape2", [ ((2, 3, 4), (3, 4)), ((3, 4), (2, 3, 4)), ((3, 1, 4), (3, 2, 4)), ((1, 3, 4), (3, 4)), ((3, 4, 1), (3, 4, 2)), ((1, 5), (5, 1)), ((3, 1), (3, 4)), ((3, 1), (1, 4)), ((1, 4), (3, 4)), ((2, 2, 2), (1, 1, 1)), ], ) def test_binary_broadcasting(func, shape1, shape2): density1 = 1 if np.prod(shape1) == 1 else 0.5 density2 = 1 if np.prod(shape2) == 1 else 0.5 xs = sparse.random(shape1, density=density1) x = xs.todense() ys = sparse.random(shape2, density=density2) y = ys.todense() expected = func(x, y) actual = func(xs, ys) assert isinstance(actual, COO) assert_eq(expected, actual) assert np.count_nonzero(expected) == actual.nnz @pytest.mark.parametrize( "shape1,shape2", [((3, 4), (2, 3, 4)), ((3, 1, 4), (3, 2, 4)), ((3, 4, 1), (3, 4, 2))], ) def test_broadcast_to(shape1, shape2): a = sparse.random(shape1, density=0.5) x = a.todense() assert_eq(np.broadcast_to(x, shape2), a.broadcast_to(shape2)) @pytest.mark.parametrize( "shapes", [ [(2,), (3, 2), (4, 3, 2)], [(3,), (2, 3), (2, 2, 3)], [(2,), (2, 2), (2, 2, 2)], [(4,), (4, 4), (4, 4, 4)], [(4,), (4, 4), (4, 4, 4)], [(4,), (4, 4), (4, 4, 4)], [(1, 1, 2), (1, 3, 1), (4, 1, 1)], [(2,), (2, 1), (2, 1, 1)], ], ) @pytest.mark.parametrize( "func", [ lambda x, y, z: (x + y) * z, lambda x, y, z: x * (y + z), lambda x, y, z: x * y * z, lambda x, y, z: x + y + z, lambda x, y, z: x + y - z, lambda x, y, z: x - y + z, ], ) def test_trinary_broadcasting(shapes, func): args = [sparse.random(s, density=0.5) for s in shapes] dense_args = [arg.todense() for arg in args] fs = sparse.elemwise(func, *args) assert isinstance(fs, COO) assert_eq(fs, func(*dense_args)) @pytest.mark.parametrize( "shapes, func", [ ([(2,), (3, 2), (4, 3, 2)], lambda x, y, z: (x + y) * z), ([(3,), (2, 3), (2, 2, 3)], lambda x, y, z: x * (y + z)), ([(2,), (2, 2), (2, 2, 2)], lambda x, y, z: x * y * z), ([(4,), (4, 4), (4, 4, 4)], lambda x, y, z: x + y + z), ], ) @pytest.mark.parametrize("value", [np.nan, np.inf, -np.inf]) @pytest.mark.parametrize("fraction", [0.25, 0.5, 0.75, 1.0]) @pytest.mark.filterwarnings("ignore:invalid value") def test_trinary_broadcasting_pathological(shapes, func, value, fraction): args = [sparse.random(s, density=0.5, data_rvs=random_value_array(value, fraction)) for s in shapes] dense_args = [arg.todense() for arg in args] fs = sparse.elemwise(func, *args) assert isinstance(fs, COO) assert_eq(fs, func(*dense_args)) def test_sparse_broadcasting(monkeypatch): orig_unmatch_coo = sparse.numba_backend._umath._Elemwise._get_func_coords_data state = {"num_matches": 0} xs = sparse.random((3, 4), density=0.5) ys = sparse.random((3, 4), density=0.5) def mock_unmatch_coo(*args, **kwargs): result = orig_unmatch_coo(*args, **kwargs) if result is not None: state["num_matches"] += 1 return result monkeypatch.setattr(sparse.numba_backend._umath._Elemwise, "_get_func_coords_data", mock_unmatch_coo) xs * ys # Less than in case there's absolutely no overlap in some cases. assert state["num_matches"] <= 1 def test_dense_broadcasting(monkeypatch): orig_unmatch_coo = sparse.numba_backend._umath._Elemwise._get_func_coords_data state = {"num_matches": 0} xs = sparse.random((3, 4), density=0.5) ys = sparse.random((3, 4), density=0.5) def mock_unmatch_coo(*args, **kwargs): result = orig_unmatch_coo(*args, **kwargs) if result is not None: state["num_matches"] += 1 return result monkeypatch.setattr(sparse.numba_backend._umath._Elemwise, "_get_func_coords_data", mock_unmatch_coo) xs + ys # Less than in case there's absolutely no overlap in some cases. assert state["num_matches"] <= 3 @pytest.mark.parametrize("format", ["coo", "dok", "gcxs"]) def test_sparsearray_elemwise(format): xs = sparse.random((3, 4), density=0.5, format=format) ys = sparse.random((3, 4), density=0.5, format=format) x = xs.todense() y = ys.todense() fs = sparse.elemwise(operator.add, xs, ys) if format == "gcxs": assert isinstance(fs, GCXS) elif format == "dok": assert isinstance(fs, DOK) else: assert isinstance(fs, COO) assert_eq(fs, x + y) def test_ndarray_densification_fails(rng): xs = sparse.random((2, 3, 4), density=0.5) y = rng.random((3, 4)) with pytest.raises(ValueError): xs + y def test_elemwise_noargs(): def func(): return np.float64(5.0) with pytest.raises(ValueError, match=r"None of the args is sparse:"): sparse.elemwise(func) @pytest.mark.parametrize( "func", [ operator.pow, operator.truediv, operator.floordiv, operator.ge, operator.le, operator.eq, operator.mod, ], ) @pytest.mark.filterwarnings("ignore:divide by zero") @pytest.mark.filterwarnings("ignore:invalid value") @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_nonzero_outout_fv_ufunc(func, format): xs = sparse.random((2, 3, 4), density=0.5, format=format) ys = sparse.random((2, 3, 4), density=0.5, format=format) x = xs.todense() y = ys.todense() f = func(x, y) fs = func(xs, ys) assert isinstance(fs, format) assert_eq(f, fs) @pytest.mark.parametrize( "func, scalar", [ (operator.mul, 5), (operator.add, 0), (operator.sub, 0), (operator.pow, 5), (operator.truediv, 3), (operator.floordiv, 4), (operator.gt, 5), (operator.lt, -5), (operator.ne, 0), (operator.ge, 5), (operator.le, -3), (operator.eq, 1), (operator.mod, 5), ], ) @pytest.mark.parametrize("convert_to_np_number", [True, False]) @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_elemwise_scalar(func, scalar, convert_to_np_number, format): xs = sparse.random((2, 3, 4), density=0.5, format=format) if convert_to_np_number: scalar = np.float32(scalar) y = scalar x = xs.todense() fs = func(xs, y) assert isinstance(fs, format) assert xs.nnz >= fs.nnz assert_eq(fs, func(x, y)) @pytest.mark.parametrize( "func, scalar", [ (operator.mul, 5), (operator.add, 0), (operator.sub, 0), (operator.gt, -5), (operator.lt, 5), (operator.ne, 0), (operator.ge, -5), (operator.le, 3), (operator.eq, 1), ], ) @pytest.mark.parametrize("convert_to_np_number", [True, False]) def test_leftside_elemwise_scalar(func, scalar, convert_to_np_number): xs = sparse.random((2, 3, 4), density=0.5) if convert_to_np_number: scalar = np.float32(scalar) y = scalar x = xs.todense() fs = func(y, xs) assert isinstance(fs, COO) assert xs.nnz >= fs.nnz assert_eq(fs, func(y, x)) @pytest.mark.parametrize( "func, scalar", [ (operator.add, 5), (operator.sub, -5), (operator.pow, -3), (operator.truediv, 0), (operator.floordiv, 0), (operator.gt, -5), (operator.lt, 5), (operator.ne, 1), (operator.ge, -3), (operator.le, 3), (operator.eq, 0), ], ) @pytest.mark.filterwarnings("ignore:divide by zero") @pytest.mark.filterwarnings("ignore:invalid value") def test_scalar_output_nonzero_fv(func, scalar): xs = sparse.random((2, 3, 4), density=0.5) y = scalar x = xs.todense() f = func(x, y) fs = func(xs, y) assert isinstance(fs, COO) assert fs.nnz <= xs.nnz assert_eq(f, fs) @pytest.mark.parametrize("func", [operator.and_, operator.or_, operator.xor]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_bitwise_binary(func, shape, format): # Small arrays need high density to have nnz entries # Casting floats to int will result in all zeros, hence the * 100 xs = (sparse.random(shape, density=0.5, format=format) * 100).astype(np.int64) ys = (sparse.random(shape, density=0.5, format=format) * 100).astype(np.int64) x = xs.todense() y = ys.todense() assert_eq(func(xs, ys), func(x, y)) @pytest.mark.parametrize("func", [operator.iand, operator.ior, operator.ixor]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) @pytest.mark.parametrize("format", [COO, GCXS, DOK]) def test_bitwise_binary_inplace(func, shape, format): # Small arrays need high density to have nnz entries # Casting floats to int will result in all zeros, hence the * 100 xs = (sparse.random(shape, density=0.5, format=format) * 100).astype(np.int64) ys = (sparse.random(shape, density=0.5, format=format) * 100).astype(np.int64) x = xs.todense() y = ys.todense() xs = func(xs, ys) x = func(x, y) assert_eq(xs, x) @pytest.mark.parametrize("func", [operator.lshift, operator.rshift]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) def test_bitshift_binary(func, shape): # Small arrays need high density to have nnz entries # Casting floats to int will result in all zeros, hence the * 100 xs = (sparse.random(shape, density=0.5) * 100).astype(np.int64) # Can't merge into test_bitwise_binary because left/right shifting # with something >= 64 isn't defined. ys = (sparse.random(shape, density=0.5) * 64).astype(np.int64) x = xs.todense() y = ys.todense() assert_eq(func(xs, ys), func(x, y)) @pytest.mark.parametrize("func", [operator.ilshift, operator.irshift]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) def test_bitshift_binary_inplace(func, shape): # Small arrays need high density to have nnz entries # Casting floats to int will result in all zeros, hence the * 100 xs = (sparse.random(shape, density=0.5) * 100).astype(np.int64) # Can't merge into test_bitwise_binary because left/right shifting # with something >= 64 isn't defined. ys = (sparse.random(shape, density=0.5) * 64).astype(np.int64) x = xs.todense() y = ys.todense() xs = func(xs, ys) x = func(x, y) assert_eq(xs, x) @pytest.mark.parametrize("func", [operator.and_]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) def test_bitwise_scalar(func, shape, rng): # Small arrays need high density to have nnz entries # Casting floats to int will result in all zeros, hence the * 100 xs = (sparse.random(shape, density=0.5) * 100).astype(np.int64) y = rng.integers(100) x = xs.todense() assert_eq(func(xs, y), func(x, y)) assert_eq(func(y, xs), func(y, x)) @pytest.mark.parametrize("func", [operator.lshift, operator.rshift]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) def test_bitshift_scalar(func, shape, rng): # Small arrays need high density to have nnz entries # Casting floats to int will result in all zeros, hence the * 100 xs = (sparse.random(shape, density=0.5) * 100).astype(np.int64) # Can't merge into test_bitwise_binary because left/right shifting # with something >= 64 isn't defined. y = rng.integers(64) x = xs.todense() assert_eq(func(xs, y), func(x, y)) @pytest.mark.parametrize("func", [operator.invert]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) def test_unary_bitwise_nonzero_output_fv(func, shape): # Small arrays need high density to have nnz entries # Casting floats to int will result in all zeros, hence the * 100 xs = (sparse.random(shape, density=0.5) * 100).astype(np.int64) x = xs.todense() f = func(x) fs = func(xs) assert isinstance(fs, COO) assert fs.nnz <= xs.nnz assert_eq(f, fs) @pytest.mark.parametrize("func", [operator.or_, operator.xor]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) def test_binary_bitwise_nonzero_output_fv(func, shape, rng): # Small arrays need high density to have nnz entries # Casting floats to int will result in all zeros, hence the * 100 xs = (sparse.random(shape, density=0.5) * 100).astype(np.int64) y = rng.integers(1, 100) x = xs.todense() f = func(x, y) fs = func(xs, y) assert isinstance(fs, COO) assert fs.nnz <= xs.nnz assert_eq(f, fs) @pytest.mark.parametrize( "func", [operator.mul, operator.add, operator.sub, operator.gt, operator.lt, operator.ne], ) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) def test_elemwise_nonzero_input_fv(func, shape, rng): xs = sparse.random(shape, density=0.5, fill_value=rng.random()) ys = sparse.random(shape, density=0.5, fill_value=rng.random()) x = xs.todense() y = ys.todense() assert_eq(func(xs, ys), func(x, y)) @pytest.mark.parametrize("func", [operator.lshift, operator.rshift]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) def test_binary_bitshift_densification_fails(func, shape, rng): # Small arrays need high density to have nnz entries # Casting floats to int will result in all zeros, hence the * 100 x = rng.integers(1, 100) ys = (sparse.random(shape, density=0.5) * 64).astype(np.int64) y = ys.todense() f = func(x, y) fs = func(x, ys) assert isinstance(fs, COO) assert fs.nnz <= ys.nnz assert_eq(f, fs) @pytest.mark.parametrize("func", [operator.and_, operator.or_, operator.xor]) @pytest.mark.parametrize("shape", [(2,), (2, 3), (2, 3, 4), (2, 3, 4, 5)]) def test_bitwise_binary_bool(func, shape): # Small arrays need high density to have nnz entries xs = sparse.random(shape, density=0.5).astype(bool) ys = sparse.random(shape, density=0.5).astype(bool) x = xs.todense() y = ys.todense() assert_eq(func(xs, ys), func(x, y)) def test_elemwise_binary_empty(): x = COO({}, shape=(10, 10)) y = sparse.random((10, 10), density=0.5) for z in [x * y, y * x]: assert z.nnz == 0 assert z.coords.shape == (2, 0) assert z.data.shape == (0,) @pytest.mark.parametrize("dtype", [np.complex64, np.complex128]) def test_nanmean_regression(dtype): array = np.array([0.0 + 0.0j, 0.0 + np.nan * 1j], dtype=dtype) sparray = sparse.COO.from_numpy(array) assert_eq(array, sparray) # Regression test for gh-580 @pytest.mark.filterwarnings("error") def test_no_deprecation_warning(): a = np.array([1, 2]) s = sparse.COO(a, a, shape=(3,)) assert_eq(s == s, np.broadcast_to(True, s.shape)) # Regression test for gh-587 def test_no_out_upcast(): a = sparse.COO([[0, 1], [0, 1]], [1, 1], shape=(2, 2)) with pytest.raises(TypeError): a *= 0.5 sparse-0.18.0/sparse/numba_backend/tests/test_io.py000066400000000000000000000013721514474157100223410ustar00rootroot00000000000000import sparse from sparse import load_npz, save_npz from sparse.numba_backend._utils import assert_eq import pytest import numpy as np @pytest.mark.parametrize("compression", [True, False]) @pytest.mark.parametrize("format", ["coo", "gcxs"]) def test_save_load_npz_file(tmp_path, compression, format): x = sparse.random((2, 3, 4, 5), density=0.25, format=format) y = x.todense() filename = tmp_path / "mat.npz" save_npz(filename, x, compressed=compression) z = load_npz(filename) assert_eq(x, z) assert_eq(y, z.todense()) def test_load_wrong_format_exception(tmp_path): x = np.array([1, 2, 3]) filename = tmp_path / "mat.npz" np.savez(filename, x) with pytest.raises(RuntimeError): load_npz(filename) sparse-0.18.0/sparse/numba_backend/tests/test_namespace.py000066400000000000000000000066121514474157100236700ustar00rootroot00000000000000import sparse def test_namespace(): from sparse.numba_backend._settings import IS_NUMPY2 all_set = { "COO", "DOK", "GCXS", "SparseArray", "abs", "acos", "acosh", "add", "all", "any", "argmax", "argmin", "argwhere", "asCOO", "as_coo", "asarray", "asin", "asinh", "asnumpy", "astype", "atan", "atan2", "atanh", "bitwise_and", "bitwise_invert", "bitwise_left_shift", "bitwise_not", "bitwise_or", "bitwise_right_shift", "bitwise_xor", "bool", "broadcast_arrays", "broadcast_to", "can_cast", "ceil", "clip", "complex128", "complex64", "concat", "concatenate", "conj", "copysign", "cos", "cosh", "diagonal", "diagonalize", "diff", "divide", "dot", "e", "einsum", "elemwise", "empty", "empty_like", "equal", "exp", "expand_dims", "expm1", "eye", "finfo", "flip", "float16", "float32", "float64", "floor", "floor_divide", "full", "full_like", "greater", "greater_equal", "hypot", "iinfo", "imag", "inf", "int16", "int32", "int64", "int8", "interp", "isfinite", "isinf", "isnan", "isneginf", "isposinf", "kron", "less", "less_equal", "load_npz", "log", "log10", "log1p", "log2", "logaddexp", "logical_and", "logical_not", "logical_or", "logical_xor", "matrix_transpose", "matmul", "max", "maximum", "mean", "min", "minimum", "moveaxis", "multiply", "nan", "nanmax", "nanmean", "nanmin", "nanprod", "nanreduce", "nansum", "negative", "newaxis", "nextafter", "nonzero", "not_equal", "ones", "ones_like", "outer", "pad", "permute_dims", "pi", "positive", "pow", "prod", "random", "real", "reciprocal", "remainder", "repeat", "reshape", "result_type", "roll", "round", "save_npz", "sign", "signbit", "sin", "sinh", "sort", "sqrt", "square", "squeeze", "stack", "std", "subtract", "sum", "take", "tan", "tanh", "tensordot", "tile", "tril", "triu", "trunc", "uint16", "uint32", "uint64", "uint8", "unique_counts", "unique_values", "unstack", "var", "vecdot", "where", "zeros", "zeros_like", } if IS_NUMPY2: all_set.update({"isdtype"}) assert set(sparse.__all__) == all_set for attr in sparse.__all__: assert hasattr(sparse, attr) assert sorted(sparse.__all__) == sparse.__all__ sparse-0.18.0/sparse/tests/000077500000000000000000000000001514474157100155455ustar00rootroot00000000000000sparse-0.18.0/sparse/tests/__init__.py000066400000000000000000000000001514474157100176440ustar00rootroot00000000000000sparse-0.18.0/sparse/tests/conftest.py000066400000000000000000000005541514474157100177500ustar00rootroot00000000000000import sparse import pytest import numpy as np @pytest.fixture(scope="session") def backend(): yield sparse._BACKEND @pytest.fixture(scope="module") def graph(): return np.array( [ [0, 1, 1, 0, 0], [0, 0, 1, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 1], [0, 1, 0, 1, 0], ] ) sparse-0.18.0/sparse/tests/test_backends.py000066400000000000000000000176201514474157100207360ustar00rootroot00000000000000import warnings import sparse import pytest import numpy as np import scipy as sp import scipy.sparse as sps import scipy.sparse.csgraph as spgraph import scipy.sparse.linalg as splin from numpy.testing import assert_almost_equal, assert_equal def test_backends(backend): rng = np.random.default_rng(0) x = sparse.random((100, 10, 100), density=0.01, random_state=rng) y = sparse.random((100, 10, 100), density=0.01, random_state=rng) if backend == sparse._BackendType.Finch: import finch def storage(): return finch.Storage(finch.Dense(finch.SparseList(finch.SparseList(finch.Element(0.0)))), order="C") x = x.to_storage(storage()) y = y.to_storage(storage()) else: x.asformat("gcxs") y.asformat("gcxs") z = x + y result = sparse.sum(z) assert result.shape == () def test_finch_lazy_backend(backend): if backend != sparse._BackendType.Finch: pytest.skip("Tested only for Finch backend") import finch np_eye = np.eye(5) sp_arr = sps.csr_array(np_eye) finch_dense = finch.Tensor(np_eye) assert np.shares_memory(finch_dense.todense(), np_eye) finch_arr = finch.Tensor(sp_arr) assert_equal(finch_arr.todense(), np_eye) transposed = sparse.permute_dims(finch_arr, (1, 0)) assert_equal(transposed.todense(), np_eye.T) @sparse.compiled() def my_fun(tns1, tns2): tmp = sparse.add(tns1, tns2) return sparse.sum(tmp, axis=0) result = my_fun(finch_dense, finch_arr) assert_equal(result.todense(), np.sum(2 * np_eye, axis=0)) @pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")]) def test_asarray(backend, format, order): arr = np.eye(5, order=order) result = sparse.asarray(arr, format=format) assert_equal(result.todense(), arr) @pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")]) def test_scipy_spsolve(backend, format, order): x = np.eye(10, order=order) * 2 y = np.ones((10, 1), order=order) x_pydata = sparse.asarray(x, format=format) y_pydata = sparse.asarray(y, format="coo") actual = splin.spsolve(x_pydata, y_pydata) expected = np.linalg.solve(x, y.ravel()) assert_almost_equal(actual, expected) @pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")]) def test_scipy_inv(backend, format, order): x = np.eye(10, order=order) * 2 x_pydata = sparse.asarray(x, format=format) with warnings.catch_warnings(): warnings.simplefilter("ignore", category=sps.SparseEfficiencyWarning) actual = splin.inv(x_pydata) expected = np.linalg.inv(x) assert_almost_equal(actual.todense(), expected) @pytest.mark.skip(reason="https://github.com/scipy/scipy/pull/20759") @pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")]) def test_scipy_norm(backend, format, order): x = np.eye(10, order=order) * 2 x_pydata = sparse.asarray(x, format=format) actual = splin.norm(x_pydata) expected = sp.linalg.norm(x) assert_almost_equal(actual, expected) @pytest.mark.skip(reason="https://github.com/scipy/scipy/pull/20759") @pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")]) def test_scipy_lsqr(backend, format, order): x = np.eye(10, order=order) * 2 y = np.ones((10, 1), order=order) x_pydata = sparse.asarray(x, format=format) actual_x, _ = splin.lsqr(x_pydata, y)[:2] expected_x, _ = sp.linalg.lstsq(x, y)[:2] assert_almost_equal(actual_x, expected_x.ravel()) @pytest.mark.skip(reason="https://github.com/scipy/scipy/pull/20759") @pytest.mark.parametrize("format, order", [("csc", "F"), ("csr", "C"), ("coo", "F"), ("coo", "C")]) def test_scipy_eigs(backend, format, order): x = np.eye(10, order=order) * 2 x_pydata = sparse.asarray(x, format=format) x_sp = sps.coo_array(x) actual_vals, _ = splin.eigs(x_pydata, k=3) expected_vals, _ = splin.eigs(x_sp, k=3) assert_almost_equal(actual_vals, expected_vals) @pytest.mark.parametrize( "matrix_fn, format, order", [(sps.csc_array, "csc", "F"), (sps.csr_array, "csr", "C"), (sps.coo_array, "coo", "F")], ) def test_scipy_connected_components(backend, graph, matrix_fn, format, order): graph = matrix_fn(np.array(graph, order=order)) sp_graph = sparse.asarray(graph, format=format) actual_n_components, actual_labels = spgraph.connected_components(sp_graph) expected_n_components, expected_labels = spgraph.connected_components(graph) assert actual_n_components == expected_n_components assert_equal(actual_labels, expected_labels) @pytest.mark.parametrize( "matrix_fn, format, order", [(sps.csc_array, "csc", "F"), (sps.csr_array, "csr", "C"), (sps.coo_array, "coo", "F")], ) def test_scipy_laplacian(backend, graph, matrix_fn, format, order): graph = matrix_fn(np.array(graph, order=order)) sp_graph = sparse.asarray(graph, format=format) actual_lap = spgraph.laplacian(sp_graph) expected_lap = spgraph.laplacian(graph) assert_equal(actual_lap.todense(), expected_lap.toarray()) @pytest.mark.parametrize("matrix_fn, format, order", [(sps.csc_array, "csc", "F"), (sps.csr_array, "csr", "C")]) def test_scipy_shortest_path(backend, graph, matrix_fn, format, order): graph = matrix_fn(np.array(graph, order=order)) sp_graph = sparse.asarray(graph, format=format) actual_dist_matrix, actual_predecessors = spgraph.shortest_path(sp_graph, return_predecessors=True) expected_dist_matrix, expected_predecessors = spgraph.shortest_path(graph, return_predecessors=True) assert_equal(actual_dist_matrix, expected_dist_matrix) assert_equal(actual_predecessors, expected_predecessors) @pytest.mark.parametrize( "matrix_fn, format, order", [(sps.csc_array, "csc", "F"), (sps.csr_array, "csr", "C"), (sps.coo_array, "coo", "F")], ) def test_scipy_breadth_first_tree(backend, graph, matrix_fn, format, order): graph = matrix_fn(np.array(graph, order=order)) sp_graph = sparse.asarray(graph, format=format) actual_bft = spgraph.breadth_first_tree(sp_graph, 0, directed=False) expected_bft = spgraph.breadth_first_tree(graph, 0, directed=False) assert_equal(actual_bft.todense(), expected_bft.toarray()) @pytest.mark.parametrize( "matrix_fn, format, order", [(sps.csc_array, "csc", "F"), (sps.csr_array, "csr", "C"), (sps.coo_array, "coo", "F")], ) def test_scipy_dijkstra(backend, graph, matrix_fn, format, order): graph = matrix_fn(np.array(graph, order=order)) sp_graph = sparse.asarray(graph, format=format) actual_dist_matrix = spgraph.dijkstra(sp_graph, directed=False) expected_dist_matrix = spgraph.dijkstra(graph, directed=False) assert_equal(actual_dist_matrix, expected_dist_matrix) @pytest.mark.parametrize( "matrix_fn, format, order", [(sps.csc_array, "csc", "F"), (sps.csr_array, "csr", "C"), (sps.coo_array, "coo", "F")], ) def test_scipy_minimum_spanning_tree(backend, graph, matrix_fn, format, order): graph = matrix_fn(np.array(graph, order=order)) sp_graph = sparse.asarray(graph, format=format) actual_span_tree = spgraph.minimum_spanning_tree(sp_graph) expected_span_tree = spgraph.minimum_spanning_tree(graph) assert_equal(actual_span_tree.todense(), expected_span_tree.toarray()) @pytest.mark.skip(reason="https://github.com/scikit-learn/scikit-learn/pull/29031") @pytest.mark.parametrize("matrix_fn, format, order", [(sps.csc_array, "csc", "F")]) def test_scikit_learn_dispatch(backend, graph, matrix_fn, format, order): from sklearn.cluster import KMeans graph = matrix_fn(np.array(graph, order=order)) sp_graph = sparse.asarray(graph, format=format) neigh = KMeans(n_clusters=2) actual_labels = neigh.fit_predict(sp_graph) neigh = KMeans(n_clusters=2) expected_labels = neigh.fit_predict(graph) assert_equal(actual_labels, expected_labels) sparse-0.18.0/tox.ini000066400000000000000000000001361514474157100144210ustar00rootroot00000000000000[tox] envlist = py36, py37 [testenv] commands= pytest {posargs} extras= tests tox sparse-0.18.0/xp-tests/000077500000000000000000000000001514474157100146755ustar00rootroot00000000000000sparse-0.18.0/xp-tests/Finch-array-api-skips.txt000066400000000000000000000006361514474157100215040ustar00rootroot00000000000000# `test_nonzero` name conflict array_api_tests/test_searching_functions.py::test_nonzero_zerodim_error # flaky test array_api_tests/test_special_cases.py::test_unary[sign((x_i is -0 or x_i == +0)) -> 0] # `broadcast_to` is not defined in Finch, hangs as xfail array_api_tests/test_searching_functions.py::test_where # `test_solve` is not defined in Finch, hangs as xfail array_api_tests/test_linalg.py::test_solve sparse-0.18.0/xp-tests/Finch-array-api-xfails.txt000066400000000000000000000426051514474157100216430ustar00rootroot00000000000000# test_signatures # not implemented # stats functions array_api_tests/test_signatures.py::test_func_signature[mean] array_api_tests/test_signatures.py::test_func_signature[std] array_api_tests/test_signatures.py::test_func_signature[var] # set functions array_api_tests/test_signatures.py::test_func_signature[unique_all] array_api_tests/test_signatures.py::test_func_signature[unique_counts] array_api_tests/test_signatures.py::test_func_signature[unique_inverse] array_api_tests/test_signatures.py::test_func_signature[unique_values] # creation functions array_api_tests/test_signatures.py::test_func_signature[meshgrid] array_api_tests/test_signatures.py::test_func_signature[tril] array_api_tests/test_signatures.py::test_func_signature[triu] # inspection functions array_api_tests/test_signatures.py::test_func_signature[isdtype] array_api_tests/test_signatures.py::test_func_signature[result_type] # other functions array_api_tests/test_signatures.py::test_func_signature[concat] array_api_tests/test_signatures.py::test_func_signature[argsort] array_api_tests/test_signatures.py::test_func_signature[sort] array_api_tests/test_signatures.py::test_func_signature[broadcast_arrays] array_api_tests/test_signatures.py::test_func_signature[broadcast_to] array_api_tests/test_signatures.py::test_func_signature[expand_dims] array_api_tests/test_signatures.py::test_func_signature[flip] array_api_tests/test_signatures.py::test_func_signature[roll] array_api_tests/test_signatures.py::test_func_signature[squeeze] array_api_tests/test_signatures.py::test_func_signature[stack] array_api_tests/test_signatures.py::test_func_signature[matrix_transpose] array_api_tests/test_signatures.py::test_func_signature[vecdot] array_api_tests/test_signatures.py::test_func_signature[take] array_api_tests/test_signatures.py::test_func_signature[argmax] array_api_tests/test_signatures.py::test_func_signature[argmin] array_api_tests/test_signatures.py::test_func_signature[from_dlpack] array_api_tests/test_signatures.py::test_func_signature[cumulative_sum] array_api_tests/test_signatures.py::test_func_signature[searchsorted] array_api_tests/test_signatures.py::test_func_signature[repeat] array_api_tests/test_signatures.py::test_func_signature[tile] array_api_tests/test_signatures.py::test_func_signature[unstack] array_api_tests/test_signatures.py::test_func_signature[clip] array_api_tests/test_signatures.py::test_func_signature[copysign] array_api_tests/test_signatures.py::test_func_signature[hypot] array_api_tests/test_signatures.py::test_func_signature[logical_not] array_api_tests/test_signatures.py::test_func_signature[maximum] array_api_tests/test_signatures.py::test_func_signature[minimum] array_api_tests/test_signatures.py::test_func_signature[signbit] # linalg namespace array_api_tests/test_signatures.py::test_extension_func_signature[linalg.cross] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matmul] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.cholesky] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_norm] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_rank] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_transpose] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.outer] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.pinv] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.svdvals] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.tensordot] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.vecdot] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.det] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.diagonal] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.eigh] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.eigvalsh] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.inv] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_power] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.qr] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.slogdet] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.solve] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.svd] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.trace] # Array object namespace array_api_tests/test_signatures.py::test_array_method_signature[__dlpack__] array_api_tests/test_signatures.py::test_array_method_signature[__dlpack_device__] array_api_tests/test_signatures.py::test_array_method_signature[__setitem__] # not implemented array_api_tests/test_creation_functions.py::test_meshgrid # test_array_object array_api_tests/test_array_object.py::test_getitem array_api_tests/test_array_object.py::test_setitem array_api_tests/test_array_object.py::test_getitem_masking array_api_tests/test_array_object.py::test_setitem_masking # test_operators_and_elementwise_functions # throws for x < 1 instead of NaN array_api_tests/test_operators_and_elementwise_functions.py::test_acosh # not implemented array_api_tests/test_operators_and_elementwise_functions.py::test_logical_not # test_data_type_functions # not implemented array_api_tests/test_data_type_functions.py::test_broadcast_arrays array_api_tests/test_data_type_functions.py::test_broadcast_to array_api_tests/test_data_type_functions.py::test_isdtype array_api_tests/test_data_type_functions.py::test_result_type array_api_tests/test_data_type_functions.py::test_finfo[Float32] # test_has_names array_api_tests/test_has_names.py::test_has_names[linalg-cholesky] array_api_tests/test_has_names.py::test_has_names[linalg-cross] array_api_tests/test_has_names.py::test_has_names[linalg-det] array_api_tests/test_has_names.py::test_has_names[linalg-diagonal] array_api_tests/test_has_names.py::test_has_names[linalg-eigh] array_api_tests/test_has_names.py::test_has_names[linalg-eigvalsh] array_api_tests/test_has_names.py::test_has_names[linalg-inv] array_api_tests/test_has_names.py::test_has_names[linalg-matmul] array_api_tests/test_has_names.py::test_has_names[linalg-matrix_norm] array_api_tests/test_has_names.py::test_has_names[linalg-matrix_power] array_api_tests/test_has_names.py::test_has_names[linalg-matrix_rank] array_api_tests/test_has_names.py::test_has_names[linalg-matrix_transpose] array_api_tests/test_has_names.py::test_has_names[linalg-outer] array_api_tests/test_has_names.py::test_has_names[linalg-pinv] array_api_tests/test_has_names.py::test_has_names[linalg-qr] array_api_tests/test_has_names.py::test_has_names[linalg-slogdet] array_api_tests/test_has_names.py::test_has_names[linalg-solve] array_api_tests/test_has_names.py::test_has_names[linalg-svd] array_api_tests/test_has_names.py::test_has_names[linalg-svdvals] array_api_tests/test_has_names.py::test_has_names[linalg-tensordot] array_api_tests/test_has_names.py::test_has_names[linalg-trace] array_api_tests/test_has_names.py::test_has_names[linalg-vecdot] array_api_tests/test_has_names.py::test_has_names[statistical-cumulative_sum] array_api_tests/test_has_names.py::test_has_names[statistical-mean] array_api_tests/test_has_names.py::test_has_names[statistical-std] array_api_tests/test_has_names.py::test_has_names[statistical-var] array_api_tests/test_has_names.py::test_has_names[set-unique_all] array_api_tests/test_has_names.py::test_has_names[set-unique_counts] array_api_tests/test_has_names.py::test_has_names[set-unique_inverse] array_api_tests/test_has_names.py::test_has_names[set-unique_values] array_api_tests/test_has_names.py::test_has_names[searching-argmax] array_api_tests/test_has_names.py::test_has_names[searching-argmin] array_api_tests/test_has_names.py::test_has_names[searching-searchsorted] array_api_tests/test_has_names.py::test_has_names[creation-from_dlpack] array_api_tests/test_has_names.py::test_has_names[creation-meshgrid] array_api_tests/test_has_names.py::test_has_names[creation-tril] array_api_tests/test_has_names.py::test_has_names[creation-triu] array_api_tests/test_has_names.py::test_has_names[manipulation-broadcast_arrays] array_api_tests/test_has_names.py::test_has_names[manipulation-broadcast_to] array_api_tests/test_has_names.py::test_has_names[manipulation-concat] array_api_tests/test_has_names.py::test_has_names[manipulation-expand_dims] array_api_tests/test_has_names.py::test_has_names[manipulation-flip] array_api_tests/test_has_names.py::test_has_names[manipulation-repeat] array_api_tests/test_has_names.py::test_has_names[manipulation-roll] array_api_tests/test_has_names.py::test_has_names[manipulation-squeeze] array_api_tests/test_has_names.py::test_has_names[manipulation-stack] array_api_tests/test_has_names.py::test_has_names[manipulation-tile] array_api_tests/test_has_names.py::test_has_names[manipulation-unstack] array_api_tests/test_has_names.py::test_has_names[sorting-argsort] array_api_tests/test_has_names.py::test_has_names[sorting-sort] array_api_tests/test_has_names.py::test_has_names[data_type-isdtype] array_api_tests/test_has_names.py::test_has_names[data_type-result_type] array_api_tests/test_has_names.py::test_has_names[elementwise-clip] array_api_tests/test_has_names.py::test_has_names[elementwise-copysign] array_api_tests/test_has_names.py::test_has_names[elementwise-hypot] array_api_tests/test_has_names.py::test_has_names[elementwise-logical_not] array_api_tests/test_has_names.py::test_has_names[elementwise-maximum] array_api_tests/test_has_names.py::test_has_names[elementwise-minimum] array_api_tests/test_has_names.py::test_has_names[elementwise-signbit] array_api_tests/test_has_names.py::test_has_names[linear_algebra-matrix_transpose] array_api_tests/test_has_names.py::test_has_names[linear_algebra-vecdot] array_api_tests/test_has_names.py::test_has_names[indexing-take] array_api_tests/test_has_names.py::test_has_names[array_method-__dlpack__] array_api_tests/test_has_names.py::test_has_names[array_method-__dlpack_device__] array_api_tests/test_has_names.py::test_has_names[array_method-__setitem__] array_api_tests/test_has_names.py::test_has_names[array_attribute-T] # test_indexing_functions # not implemented array_api_tests/test_indexing_functions.py::test_take # test_linalg # not implemented array_api_tests/test_linalg.py::test_matrix_transpose array_api_tests/test_linalg.py::test_vecdot array_api_tests/test_linalg.py::test_eigh array_api_tests/test_linalg.py::test_eigvalsh array_api_tests/test_linalg.py::test_inv array_api_tests/test_linalg.py::test_linalg_matmul array_api_tests/test_linalg.py::test_matrix_norm array_api_tests/test_linalg.py::test_matrix_power array_api_tests/test_linalg.py::test_matrix_rank array_api_tests/test_linalg.py::test_linalg_matrix_transpose array_api_tests/test_linalg.py::test_outer array_api_tests/test_linalg.py::test_pinv array_api_tests/test_linalg.py::test_qr array_api_tests/test_linalg.py::test_slogdet array_api_tests/test_linalg.py::test_cholesky array_api_tests/test_linalg.py::test_det array_api_tests/test_linalg.py::test_diagonal array_api_tests/test_linalg.py::test_vector_norm array_api_tests/test_linalg.py::test_svdvals array_api_tests/test_linalg.py::test_svd array_api_tests/test_linalg.py::test_trace array_api_tests/test_linalg.py::test_linalg_vecdot array_api_tests/test_linalg.py::test_linalg_tensordot # test_manipulation_functions # not implemented array_api_tests/test_manipulation_functions.py::test_concat array_api_tests/test_manipulation_functions.py::test_expand_dims array_api_tests/test_manipulation_functions.py::test_squeeze array_api_tests/test_manipulation_functions.py::test_flip array_api_tests/test_manipulation_functions.py::test_roll array_api_tests/test_manipulation_functions.py::test_stack # test_searching_functions # not implemented array_api_tests/test_searching_functions.py::test_argmax array_api_tests/test_searching_functions.py::test_argmin # 0D issue array_api_tests/test_searching_functions.py::test_nonzero # test_set_functions # not implemented array_api_tests/test_set_functions.py::test_unique_all array_api_tests/test_set_functions.py::test_unique_counts array_api_tests/test_set_functions.py::test_unique_inverse array_api_tests/test_set_functions.py::test_unique_values # test_sorting_functions # not implemented array_api_tests/test_sorting_functions.py::test_argsort array_api_tests/test_sorting_functions.py::test_sort # test_special_cases array_api_tests/test_special_cases.py::test_unary[acos(x_i > 1) -> NaN] array_api_tests/test_special_cases.py::test_unary[acos(x_i < -1) -> NaN] array_api_tests/test_special_cases.py::test_unary[acosh(x_i is NaN) -> NaN] array_api_tests/test_special_cases.py::test_unary[acosh(x_i < 1) -> NaN] array_api_tests/test_special_cases.py::test_unary[acosh(x_i is 1) -> +0] array_api_tests/test_special_cases.py::test_unary[acosh(x_i is +infinity) -> +infinity] array_api_tests/test_special_cases.py::test_unary[asin(x_i > 1) -> NaN] array_api_tests/test_special_cases.py::test_unary[asin(x_i < -1) -> NaN] array_api_tests/test_special_cases.py::test_unary[atanh(x_i < -1) -> NaN] array_api_tests/test_special_cases.py::test_unary[atanh(x_i > 1) -> NaN] array_api_tests/test_special_cases.py::test_unary[cos(x_i is +infinity) -> NaN] array_api_tests/test_special_cases.py::test_unary[cos(x_i is -infinity) -> NaN] array_api_tests/test_special_cases.py::test_unary[log(x_i < 0) -> NaN] array_api_tests/test_special_cases.py::test_unary[log1p(x_i < -1) -> NaN] array_api_tests/test_special_cases.py::test_unary[log2(x_i < 0) -> NaN] array_api_tests/test_special_cases.py::test_unary[log10(x_i < 0) -> NaN] array_api_tests/test_special_cases.py::test_unary[signbit(x_i is +0) -> False] array_api_tests/test_special_cases.py::test_unary[signbit(x_i is -0) -> True] array_api_tests/test_special_cases.py::test_unary[signbit(x_i is +infinity) -> False] array_api_tests/test_special_cases.py::test_unary[signbit(x_i is -infinity) -> True] array_api_tests/test_special_cases.py::test_unary[signbit(isfinite(x_i) and x_i > 0) -> False] array_api_tests/test_special_cases.py::test_unary[signbit(isfinite(x_i) and x_i < 0) -> True] array_api_tests/test_special_cases.py::test_unary[signbit(x_i is NaN) -> False] array_api_tests/test_special_cases.py::test_unary[signbit(x_i is NaN) -> True] array_api_tests/test_special_cases.py::test_unary[sin((x_i is +infinity or x_i == -infinity)) -> NaN] array_api_tests/test_special_cases.py::test_unary[sqrt(x_i < 0) -> NaN] array_api_tests/test_special_cases.py::test_unary[tan((x_i is +infinity or x_i == -infinity)) -> NaN] array_api_tests/test_special_cases.py::test_binary[copysign(x2_i < 0) -> NaN] array_api_tests/test_special_cases.py::test_binary[copysign(x2_i is -0) -> NaN] array_api_tests/test_special_cases.py::test_binary[copysign(x2_i is +0) -> NaN] array_api_tests/test_special_cases.py::test_binary[copysign(x2_i > 0) -> NaN] array_api_tests/test_special_cases.py::test_binary[maximum(x1_i is NaN or x2_i is NaN) -> NaN] array_api_tests/test_special_cases.py::test_binary[minimum(x1_i is NaN or x2_i is NaN) -> NaN] array_api_tests/test_special_cases.py::test_binary[pow(x1_i is -infinity and x2_i > 0 and not (x2_i.is_integer() and x2_i % 2 == 1)) -> +infinity] array_api_tests/test_special_cases.py::test_binary[pow(x1_i is -infinity and x2_i < 0 and x2_i.is_integer() and x2_i % 2 == 1) -> -0] array_api_tests/test_special_cases.py::test_binary[pow(x1_i is -0 and x2_i > 0 and x2_i.is_integer() and x2_i % 2 == 1) -> -0] array_api_tests/test_special_cases.py::test_binary[pow(x1_i < 0 and isfinite(x1_i) and isfinite(x2_i) and not x2_i.is_integer()) -> NaN] array_api_tests/test_special_cases.py::test_binary[__pow__(x1_i < 0 and isfinite(x1_i) and isfinite(x2_i) and not x2_i.is_integer()) -> NaN] array_api_tests/test_special_cases.py::test_binary[__pow__(x1_i is -infinity and x2_i > 0 and not (x2_i.is_integer() and x2_i % 2 == 1)) -> +infinity] array_api_tests/test_special_cases.py::test_binary[__pow__(x1_i is -infinity and x2_i < 0 and x2_i.is_integer() and x2_i % 2 == 1) -> -0] array_api_tests/test_special_cases.py::test_binary[__pow__(x1_i is -0 and x2_i > 0 and x2_i.is_integer() and x2_i % 2 == 1) -> -0] array_api_tests/test_special_cases.py::test_iop[__ipow__(x1_i is -infinity and x2_i > 0 and not (x2_i.is_integer() and x2_i % 2 == 1)) -> +infinity] array_api_tests/test_special_cases.py::test_iop[__ipow__(x1_i is -infinity and x2_i < 0 and x2_i.is_integer() and x2_i % 2 == 1) -> -0] array_api_tests/test_special_cases.py::test_iop[__ipow__(x1_i is -0 and x2_i > 0 and x2_i.is_integer() and x2_i % 2 == 1) -> -0] array_api_tests/test_special_cases.py::test_iop[__ipow__(x1_i < 0 and isfinite(x1_i) and isfinite(x2_i) and not x2_i.is_integer()) -> NaN] array_api_tests/test_special_cases.py::test_empty_arrays[mean] array_api_tests/test_special_cases.py::test_empty_arrays[std] array_api_tests/test_special_cases.py::test_empty_arrays[var] array_api_tests/test_special_cases.py::test_nan_propagation[cumulative_sum] array_api_tests/test_special_cases.py::test_nan_propagation[max] array_api_tests/test_special_cases.py::test_nan_propagation[mean] array_api_tests/test_special_cases.py::test_nan_propagation[min] array_api_tests/test_special_cases.py::test_nan_propagation[prod] array_api_tests/test_special_cases.py::test_nan_propagation[std] array_api_tests/test_special_cases.py::test_nan_propagation[sum] array_api_tests/test_special_cases.py::test_nan_propagation[var] # test_statistical_functions # not implemented array_api_tests/test_statistical_functions.py::test_mean sparse-0.18.0/xp-tests/Numba-array-api-skips.txt000066400000000000000000000000001514474157100215000ustar00rootroot00000000000000sparse-0.18.0/xp-tests/Numba-array-api-xfails.txt000066400000000000000000000177631514474157100216650ustar00rootroot00000000000000array_api_tests/test_array_object.py::test_setitem array_api_tests/test_array_object.py::test_getitem_masking array_api_tests/test_array_object.py::test_setitem_masking array_api_tests/test_creation_functions.py::test_arange array_api_tests/test_creation_functions.py::test_linspace array_api_tests/test_creation_functions.py::test_meshgrid array_api_tests/test_data_type_functions.py::test_finfo[float32] array_api_tests/test_has_names.py::test_has_names[linalg-cholesky] array_api_tests/test_has_names.py::test_has_names[linalg-cross] array_api_tests/test_has_names.py::test_has_names[linalg-det] array_api_tests/test_has_names.py::test_has_names[linalg-diagonal] array_api_tests/test_has_names.py::test_has_names[linalg-eigh] array_api_tests/test_has_names.py::test_has_names[linalg-eigvalsh] array_api_tests/test_has_names.py::test_has_names[linalg-inv] array_api_tests/test_has_names.py::test_has_names[linalg-matmul] array_api_tests/test_has_names.py::test_has_names[linalg-matrix_norm] array_api_tests/test_has_names.py::test_has_names[linalg-matrix_power] array_api_tests/test_has_names.py::test_has_names[linalg-matrix_rank] array_api_tests/test_has_names.py::test_has_names[linalg-matrix_transpose] array_api_tests/test_has_names.py::test_has_names[linalg-outer] array_api_tests/test_has_names.py::test_has_names[linalg-pinv] array_api_tests/test_has_names.py::test_has_names[linalg-qr] array_api_tests/test_has_names.py::test_has_names[linalg-slogdet] array_api_tests/test_has_names.py::test_has_names[linalg-solve] array_api_tests/test_has_names.py::test_has_names[linalg-svd] array_api_tests/test_has_names.py::test_has_names[linalg-svdvals] array_api_tests/test_has_names.py::test_has_names[linalg-tensordot] array_api_tests/test_has_names.py::test_has_names[linalg-trace] array_api_tests/test_has_names.py::test_has_names[linalg-vecdot] array_api_tests/test_has_names.py::test_has_names[linalg-vector_norm] array_api_tests/test_has_names.py::test_has_names[set-unique_all] array_api_tests/test_has_names.py::test_has_names[set-unique_inverse] array_api_tests/test_has_names.py::test_has_names[creation-arange] array_api_tests/test_has_names.py::test_has_names[creation-from_dlpack] array_api_tests/test_has_names.py::test_has_names[creation-linspace] array_api_tests/test_has_names.py::test_has_names[creation-meshgrid] array_api_tests/test_has_names.py::test_has_names[sorting-argsort] array_api_tests/test_has_names.py::test_has_names[array_method-__dlpack__] array_api_tests/test_has_names.py::test_has_names[array_method-__dlpack_device__] array_api_tests/test_has_names.py::test_has_names[array_method-__setitem__] array_api_tests/test_indexing_functions.py::test_take array_api_tests/test_set_functions.py::test_unique_all array_api_tests/test_set_functions.py::test_unique_inverse array_api_tests/test_signatures.py::test_func_signature[unique_all] array_api_tests/test_signatures.py::test_func_signature[unique_inverse] array_api_tests/test_signatures.py::test_func_signature[arange] array_api_tests/test_signatures.py::test_func_signature[from_dlpack] array_api_tests/test_signatures.py::test_func_signature[linspace] array_api_tests/test_signatures.py::test_func_signature[meshgrid] array_api_tests/test_signatures.py::test_func_signature[argsort] array_api_tests/test_signatures.py::test_array_method_signature[__dlpack__] array_api_tests/test_signatures.py::test_array_method_signature[__dlpack_device__] array_api_tests/test_signatures.py::test_array_method_signature[__setitem__] array_api_tests/test_sorting_functions.py::test_argsort array_api_tests/test_has_names.py::test_has_names[fft-hfft] array_api_tests/test_has_names.py::test_has_names[fft-ihfft] array_api_tests/test_has_names.py::test_has_names[fft-fftfreq] array_api_tests/test_has_names.py::test_has_names[fft-rfftfreq] array_api_tests/test_has_names.py::test_has_names[fft-fftshift] array_api_tests/test_has_names.py::test_has_names[fft-ifftshift] array_api_tests/test_has_names.py::test_has_names[fft-fft] array_api_tests/test_has_names.py::test_has_names[fft-ifft] array_api_tests/test_has_names.py::test_has_names[fft-fftn] array_api_tests/test_has_names.py::test_has_names[fft-ifftn] array_api_tests/test_has_names.py::test_has_names[fft-rfft] array_api_tests/test_has_names.py::test_has_names[fft-irfft] array_api_tests/test_has_names.py::test_has_names[fft-rfftn] array_api_tests/test_has_names.py::test_has_names[fft-irfftn] array_api_tests/test_creation_functions.py::test_empty_like array_api_tests/test_data_type_functions.py::test_finfo[complex64] array_api_tests/test_manipulation_functions.py::test_squeeze array_api_tests/test_has_names.py::test_has_names[statistical-cumulative_sum] array_api_tests/test_has_names.py::test_has_names[statistical-cumulative_prod] array_api_tests/test_has_names.py::test_has_names[indexing-take_along_axis] array_api_tests/test_has_names.py::test_has_names[searching-count_nonzero] array_api_tests/test_has_names.py::test_has_names[searching-searchsorted] array_api_tests/test_signatures.py::test_func_signature[take_along_axis] array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is +infinity and isfinite(x2_i) and x2_i > 0) -> +infinity] array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is +infinity and isfinite(x2_i) and x2_i < 0) -> -infinity] array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is -infinity and isfinite(x2_i) and x2_i > 0) -> -infinity] array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is -infinity and isfinite(x2_i) and x2_i < 0) -> +infinity] array_api_tests/test_special_cases.py::test_binary[floor_divide(isfinite(x1_i) and x1_i > 0 and x2_i is -infinity) -> -0] array_api_tests/test_special_cases.py::test_binary[__floordiv__(x1_i is +infinity and isfinite(x2_i) and x2_i > 0) -> +infinity] array_api_tests/test_special_cases.py::test_binary[floor_divide(isfinite(x1_i) and x1_i < 0 and x2_i is +infinity) -> -0] array_api_tests/test_special_cases.py::test_binary[__floordiv__(x1_i is +infinity and isfinite(x2_i) and x2_i < 0) -> -infinity] array_api_tests/test_special_cases.py::test_binary[__floordiv__(x1_i is -infinity and isfinite(x2_i) and x2_i > 0) -> -infinity] array_api_tests/test_special_cases.py::test_binary[__floordiv__(x1_i is -infinity and isfinite(x2_i) and x2_i < 0) -> +infinity] array_api_tests/test_special_cases.py::test_binary[__floordiv__(isfinite(x1_i) and x1_i > 0 and x2_i is -infinity) -> -0] array_api_tests/test_special_cases.py::test_binary[__floordiv__(isfinite(x1_i) and x1_i < 0 and x2_i is +infinity) -> -0] array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(x1_i is +infinity and isfinite(x2_i) and x2_i > 0) -> +infinity] array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(x1_i is -infinity and isfinite(x2_i) and x2_i < 0) -> +infinity] array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(x1_i is +infinity and isfinite(x2_i) and x2_i < 0) -> -infinity] array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(isfinite(x1_i) and x1_i > 0 and x2_i is -infinity) -> -0] array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(x1_i is -infinity and isfinite(x2_i) and x2_i > 0) -> -infinity] array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(isfinite(x1_i) and x1_i < 0 and x2_i is +infinity) -> -0] array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_1[1] array_api_tests/test_statistical_functions.py::test_cumulative_prod array_api_tests/test_statistical_functions.py::test_cumulative_sum array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_1[None] array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_2[1] array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_2[None] array_api_tests/test_searching_functions.py::test_count_nonzero array_api_tests/test_searching_functions.py::test_searchsorted array_api_tests/test_signatures.py::test_func_signature[cumulative_sum] array_api_tests/test_signatures.py::test_func_signature[cumulative_prod] array_api_tests/test_signatures.py::test_func_signature[count_nonzero] array_api_tests/test_signatures.py::test_func_signature[searchsorted] sparse-0.18.0/xp-tests/array-api-tests-rev.txt000066400000000000000000000000511514474157100212510ustar00rootroot000000000000002db6c7b807a609a1539e312e01af093a45d34764